자바 15버전이 2020년 9월 15일에 공개되었다.
COVID-19로 인해 재택근무가 활성화되면서 적응하느라 정신없이 보냈더니 JDK 버전이 두개나 나왔다.
1년에 두번 패치하는걸 따라잡겠다고 마음먹었는데.. 반성하는중이다.
Java15 (opens new window)
JDK15 (opens new window)
마찬가지로 자바 개발자가 알아두면 좋을 사항 몇가지만 짚어보려고 한다.
Sealed Classes는 Client Code가 부모클래스에서 허용된 모든 자식클래스가 무엇인지 명확하게 하는 기능이다.
Sealed Classes의 목표
아래와 같은 코드가 있다고 가정해보자.
public interface Shape {
...
}
public class Circle implements Shape {
...
}
public class Rectangle implements Shape {
...
}
public class Square implements Shape {
...
}
Shape 변수의 구현체를 추론하는 전통적인 방식으로는 if-else구문과 instanceof를 사용하는 방식이 있다.
int getCenter(Shape shape) {
if (shape instanceof Circle) {
return ... ((Circle)shape).center() ...
} else if (shape instanceof Rectangle) {
return ... ((Rectangle)shape).length() ...
} else if (shape instanceof Square) {
return ... ((Square)shape).side() ...
}
}
하지만 컴파일러는 위 구문만으로 Shape의 모든 구현체를 확인하고 있다는걸 알 수 없다.
따라서 위의 코드는 컴파일 에러가 발생하게 된다.
일반적으로는 if-else구문의 마지막에 else를 붙여 예외 등의 처리를 한다.
물론 구현체는 Circle, Rectangle, Square 세가지 뿐이므로 마지막 else는 실행될 수 없는 코드일 것이다.
int getCenter(Shape shape) {
if (shape instanceof Circle) {
return ... ((Circle)shape).center() ...
} else if (shape instanceof Rectangle) {
return ... ((Rectangle)shape).length() ...
} else if (shape instanceof Square) {
return ... ((Square)shape).side() ...
} else {
throw new IllegalStateException("Unknown implementation.");
}
}
반대로 위와 같은 경우에 컴파일 에러가 나지 않는다고 가정해보자.
그렇다면 반대로 다른 개발자에 의해 구현체가 추가된다고 해도 컴파일 에러를 통해 인지하지 못하는 문제가 발생한다.
Sealed classes는 이러한 상황을 위해 클래스 또는 인터페이스의 자식클래스를 제한하고, 부모클래스만으로 자식클래스를 명확하게 추론할 수 있도록 해 준다.
다만, JEP-375 (opens new window) 에 의해 명확하게 추론하는 기능을 제공할 예정인데, JDK15에서는 아직 사용할 수 없다.
int getCenter(Shape shape) {
return switch (shape) {
case Circle c -> ... c.center() ...
case Rectangle r -> ... r.length() ...
case Square s -> ... s.side() ...
};
}
Sealed classes의 사용 방법은 아래와 같다.
public abstract sealed class Shape permits Circle, Rectangle, Square {
...
}
public final class Circle extends Shape {
...
}
public final class Rectangle extends Shape {
...
}
public final class Square extends Shape {
...
}
모든 클래스가 같은 java파일 내에 있다면 permits를 하지 않아도 된다.
abstract sealed class Shape {
...
}
final class Circle extends Shape {
...
}
final class Rectangle extends Shape {
...
}
final class Square extends Shape {
...
}
Sealed classes의 하위클래스(subclass)에는 세 가지 제약 조건이 있다.
Sealed Classes의 Subclass 제약
제약 3번의 경우 사용할 수 있는 수정자는 3가지가 있다.
public final class Circle extends Shape {
...
}
public sealed class Rectangle extends Shape permits FilledRectangle, TransparentRectangle {
...
}
public final class FilledRectangle extends Rectangle {
...
}
public final class TransparentRectangle extends Rectangle {
...
}
public non-sealed class Square extends Shape {
...
}
public class FilledSquare extends Square {
...
}
이와 마찬가지로 인터페이스와 레코드에도 sealed를 사용할 수 있다.
public sealed interface Expression permits Plus {
...
}
public final class Plus implements Expression {
...
}
public sealed interface Expression permits Plus {
...
}
public record Plus(int i, int b) implements Expression {
...
}
다른 클래스들의 bytecode에서 직접 호출될 수 없는 클래스이다.
프레임워크 또는 언어 레벨에서 동적으로 클래스를 사용하거나, 제한된 시간에만 사용되고 이후에는 필요하지 않은 클래스가 필요해서 만들어졌다. 그리고 이러한 클래스들은 일반 사용자(개발자)들에게 공개되지 않고, 접근하지 못하게 할 필요가 있다.
Hidden Class (opens new window)를 직접 만들 수는 있으나, 그 과정이 복잡하여 관련 링크만 공유한다.
Java11에서 공개된 G1GC를 대체할 ZGC가 Preview에서 Product 되었다.
64비트 운영체제만 지원이 가능하며, G1GC보다 빠르고 더 큰 메모리에 적합하다고 한다.
지원 가능한 운영체제는 아래와 같다.
-XX:+UseZGC 옵션을 이용하여 사용 가능하다.
다만 아직 default GC는 G1GC이다.
자세한 내용은 더 공부해서 별도로 포스팅을 해야겠다.
Java12에서 공개된 Shenandoah GC가 Experimental에서 Product 되었다.
무슨 GC가 이렇게 자꾸 나오는지 모르겠다.
이거 역시 자세한 내용은 더 공부해서 별도로 포스팅을 해야겠다.
Java13에서 공개된 Text Blocks가 Preview에서 Product 되었다.
문법에 변경된 사항이 없으니 내용은 이전 포스팅 (opens new window)에서 확인하면 된다.
참고자료