Java 15의 새로운 기능
1. Record (Preview)
record는 불변 데이터 객체를 더 쉽게 생성할 수 있게 해주는 새로운 타입의 자바 class이다.
Java 14에서 Preview모드로 소개되었으며, Java 15에서는 공식 Production 기능이 되기 전, 몇 가지를 더 개선하는 것을 목표로 하고 있다.
1.1 Record가 없을 때
record가 생기기 전에는 불변 데이터 전송 객체(DTO)를 다음과 같이 생성했을 것이다.
public class Person {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
상태를 유지하는 불변 객체를 생성하기 위해 위와 같은 많은 코드가 필요하다. 모든 필드들은 명시적으로 final로 지정되어있고, 모든 필드를 파라미터로 가지는 한 개의 생성자를 가지고 있다. 또한 모든 필드들에 대한 getter가 있다. 때때로 우리는 subclass 생성을 막기 위해 class 자체를 final로 선언해야 한다.
대부분의 상황에서 우리는 한 단계 더 나아가 의미있는 로그를 출력하기 위해 toString() 메서드를 오버라이드한다. 또한 아마도 우리는 2개의 객체를 비교할 때 예측하지 못한 결과를 초래하지 않기 위해 equals()와 hashCode()메서드를 오버라이드 해야할 것이다.
1.2 Record를 사용할 때
record class를 사용함으로써, 우리는 똑같은 불변 객체를 훨씬 더 간편한 방법으로 정의할 수 있다.
public record Person(String name, int age) {
}
맨 앞에 위치한 class 정의는 Record에 대한 새로운 syntax이다. 이것은 record내의 필드들에 대한 정보를 제공한다.
또한 이를 통해 컴파일러는 class 내부의 필드를 추론할 수 있다. 이를 통해 우리는 멤버 변수나 getter와 같은 것들을 따로 정의할 필요가 없다. 또한 생성자도 정의할 필요가 없다.
게다가 컴파일러는 toString(), equals(), hashCode()에 대한 오버라이드된 메서드를 제공한다.
이처럼 record가 많은 보일러플레이트 코드를 삭제해주는 반면, 디폴트 동작을 오버라이드하는 것도 가능하다. 예를 들면 다음과 같이 생성자 내에 유효성 검사를 추가하는 것이 가능하다.
public record Person(String name, int age) {
public Person {
if(age < 0) {
throw new IllegalArgumentException("Age cannot be negative");
}
}
}
record들은 언제나 final이다. 그러므로 abstact로 선언되거나 native 메서드를 사용할 수 없다.
2. Sealed Class (Preview)
Sealed class는 어떤 타입이 subclass로서 사용되는 것이 가능한지를 나타낼 수 있다. 이것은 인터페이스에도 적용되어 어떤 타입이 그것을 구현할 수 있을지를 결정할 수 있다.
Sealed class는 2가지 키워드로 구성된다. - sealed, permits
public abstract sealed class Person permits Employee, Manager {
//...
}
위의 예제에서 우리는 Person이라는 class를 abstract로 선언하였다. 그리고 우리는 오직 Employee, Manager class만이 Person class를 상속하는 것이 가능하다는 것을 명시하였다. 아래는 Person class를 상속한 예시이다.
public final class Employee extends Person {
}
public non-sealed class Manager extends Person {
}
sealed class를 상속하는 class는 반드시 sealed나 non-sealed 혹은 final로 선언되어야 한다. 이것은 class의 계층구조를 유한하게 유지시켜 준다.
이 유한한 계층구조는 sealed class를 사용하는 장점 중의 하나이다. 아래 예시를 보자.
if (person instanceof Employee) {
return ((Employee) person).getEmployeeId();
}
else if (person instanceof Manager) {
return ((Manager) person).getSupervisorId();
}
sealed class가 없다면, 컴파일러는 모든 subclass가 커버되었는지를 if-else문을 통해 알 수 없을 것이다. 컴파일러는 else 구문이 없다면, 이 로직이 모든 케이스를 커버하지 못한다는 경고를 할 것이다.
3. 기타 변경 사항
Java 15에서는 Java 13과 14에서 Preview 모드로 제공되었던 텍스트 블록이 Production 기능으로 제공된다.
또한 Java 14에서 제공되었던 유용한 NullpointerException 기능이 디폴트로 제공된다.
※ 참조
https://www.baeldung.com/java-15-new