자바 17
- 자바 11 릴리즈 이후 자바 17싸지 추가된 자바 작성에 대한 새로운 기능
- Text 블록
- switch 표현식
- record
- sealed 타입
Text 블록
- 자바는 큰따음표로 감싼 문자열만 제공했음
- 긴문자열 사용이 불편했고 특정 문자 사용시 이스케이프가 필요
- 예시 - json 표현시
- to-be
// language=json
String json = "{\"key\":\"value\"}";
- as-is
// language=json
String json = """
{
"key1": "value",
"key2": "value",
"key3": "value"
}
""";
- 특징
- “““text”””
- 각 줄은 공백으로 들여쓰기 가능, 공백은 무시됨
- 가장 잛은 들여쓰기가 기준점이됨
- 클래스 파일에 상수를 기록하기전 javac가 Text블록을 처리
- 종결문자 LF로 처리
- 이스케이프 시퀀스를 마지막에 해석
- 아직까지는 보간법을 지원하지 않음
- kotlin 예시
val nameForPrint: String = "[${codeItem.code}] ${codeItem.name}"
21에 preview feature로 존재
https://openjdk.org/jeps/430
switch 표현식
- 기존
- break가 없으면 다음 case가 수행됨
- 표현식(expression) 불가
- 리턴 불가
- 예시
String message = switch (month) {
case 1, 2, 12 -> "Winter, brrrr";
case 3, 4, 5 -> "Spring has sprung!";
case 6, 7, 8 -> "Summer is here!";
case 9, 10, 11 -> "Fall has descended";
default -> {
throw new IllegalArgumentException("Oops, that's not a month");
}
};
- 표현식으로 처리 가능
- 쉼표로 여러개 처리 가능
- default가 없는경우 컴파일 에러
- enum 인경우 모든 상수가 명시되어있으면 default 구문 생략가능
- 이후 살펴볼 패턴 매칭으 위한 디딤돌이기도함
record
- 다음을 위한 새로운 형태의 자바 클래스 (아래의 순서가 중요 - 상용구 감소, 문법보다 언어 의미론에 더 중점을 둠)
- 데이터 전용 집계 모델링을 위한 최고 수준의 수단 제공
- 자바의 타입 시스템에서 발생할 수 있는 격차 해소
- 공통 프로그래밍 패턴을 위한 언어 수준 문법 제공
- 클래스 상용구 감소
- record의 아이디어는 자바 언어를 확장해서 클래스를 ‘필드, 오직 필드만’으로 명시하는 방법을 만드는것
- 클래스를 유용하기 위해 너무 많은 메서드들을 정의해야함, 지루하고 반복적, 기계적으로 생성가능(이펙티브 자바 참고)
- toString
- hashCode, equals
- getter 메서드들
- 공개 생성자
- 코드가 변경될때마다 위 메서드들을 확인하고 수정하는 작업이 필요
- record는 이러한 문제를 해결
- 컴파일과 런타임에 동작
- FXOrderClassic 예시 클래스
- FX 통화 거래의 기본 주문 유형을 표현
- 주문을 표현하는 필드 외 부가적인 코드들이 많음
- 생성자
- getter
- equals
- hashCode
- toString
- 특징
- 모든 멤버는 final
- 동일한 이름의 접근자
- 표준 생성자(canonical constructor)
- toString, equals, hashCode는 invokedynamic 기반의 메커니즘에 의해 구현됨
- 최상위 클래스는 java.lang.Record
- final 클래스
- record 기능의 디자인적 측면
- 자바의 열거형은 디자인 패턴(유한한 수의 타입세이프 인스턴스로 관리됨)을 구현한 구문 오버헤드를 최소화한 형태
- 레코드 또한 최소한의 구문으로 패턴(데이터 캐리어, 일면 just holds fields)을 구현한 특수한 형태
- 초기 디자인
- POJO의 상용구 감소
- 자바 빈 2.0
- 네임드 튜플
- 곱 타입
- 추가 질문들
- 하이버네이트에서 프록시 가능여부
- 전통적인 자바빈과의 호환여부
- 이름제거와 형식 유연성 지원여부
- 패턴 매칭과 구조 분해 지원여부
- 최종적 디자인 결정은 네임드 튜플
명목적 타이핑
- 자바는 명목적 타이핑(nominal typing) 기반 언어
- 타입의 이름으로 객체의 타입결정객체의 타입결정
- 구조적 타이핑 (structural typing)
- 객체의 필드와 메서드에 따라 타입결정
- record는 명목적 타이핑에 기반하여 도입
- 복합키(맵), 다중반환
- 메서드, 생성자, 정적 필드를 정의가능
- 이러한 선택은 신중해야함
- 레코드의 설계 의도는 관련된 필드를 하나의 불변속성의 데이터로 그룹화하는것
콤팩트 레코드 생성자
- 콤팩트 레코드 생성자를 사용하면 커스텀 생성자를 정의하면서도 불필요한 코드를 줄일수 있음
- 책 예시 참고
- 유효성 검사
- 정적 팩토리 메서드
- 대체 생성자
- record 기반 map key
- 책 예시 참고
레코드 결론
- 튜플 버전인 단순한 캐리어로 설계됨
- 클래스를 더 명확하고 작게 만들수 있음
- 많은 수작업 코딩 생략 가능
- lombok과 같은 별도 라이브러리 사용을 줄이거나 제거 가능
sealed 타입
- 열거형은 해당 유형이 가질 수 있는 모든 값을 타입세이프하도록 처리가능
- 디컴파일시
- 클래스 파일 내에서 열거형 값들은 public static final로 처리
- 싱글톤과 비슷하지만 하나가 아닌 유한한 개수가 있음
- 열거형 타입의 객체가 주어졌을때 완전성(exhaustiveness)을 제공
- 객체가 표현가능한 모든값을 알 수 있음
- 자바 11에서 다양한 주문을 모델링 하고 싶은경우
- 모든 필드가 포함된 여러개의 주문
- 개발자가 일일이 어떤 타입의 주문이 있는지 확인필요
- 추상 클래스를 만들고 이를 서브 클래싱해서 구체적인 타입들 정의
- 원하지 않는 확장 발생가능
- 모든 필드가 포함된 여러개의 주문
- 문제는 자바는 항상 기본적으로 확장 가능한(open inheritance) 언어로 설계 된 것
- sealed는 이러한 문제를 해결
- 알려진 하위 타입들에 의해서만 확장가능
- 책 예시
- 현재 컴파일 유닛 내에서만 확장 가능
- 내부 클래스가 상속
- abstract를 사용해서 앞서 설명한 객체지향 모델링 패턴을 깔끔한 방식으로 구현
- 현재 컴파일 유닛 내에서만 확장 가능
- 인터페이스에서도 사용가능
- 클래스 보다 인터페이스에서 사용될 가능성이 더 높음
- 책 예시
- permits 키워드
- sealed 인터페이스를 구현할수 있는 클래스를 나열
- record가 구현
- 이제 상위 인터페이스만으로 실제 구현체를 알 수 있음
- 라이브러리 코드는 두 경우만 있다고 안전하게 가정 가능
- 사용하는 클라이언트도 불필요한 위반불가능
- permits 키워드
- 자바 객체 지향의 두 가지 모델간 관계에 한 가지가 추가됨
- is-a
- has-a
- is-either-a (sealed)
- 또 다른 관점
- 최종(final)과 공개(open) 사이의 중간 지점
- 타입에 적용된 열거형 패턴
- 여러 언어의 타입에 대한 이론적인 측면 소개
- 마지막으로 짚고 넘어가야하는것은 허용하는 모든 타입은 확장하는 베이스 클래스가 있다는것
- String, Integer는 Object를 제외하고는 공통 상속 관계가 없음
- String 또는 Integer 표현 불가능
- String, Integer는 Object를 제외하고는 공통 상속 관계가 없음
instanceof의 새로운 형식
- x instanceof Y
- Y 유형의 변수에 x를 할당할 수 있으면 true, 아니면 false
- 악평을 받고 있는데, 객체의 타입과 매개변수의 타입 선택에서 정확성이 부족하다는 것을 의미
- 객체지향 훼손
- 컴파일 시점에 완전히 알 수 없는 유형들을 직면하는 경우도 있음, 이러한 상황에서는 사용
- ClassCastException 예방
- 자바 17에서는 instanceof 연산자가 타입이나 타입 패턴을 받도록 확장됨
- 타입 패턴은 타입을 지정하는 술어와 단일 패턴 변수로 구성됨
- 책 예시
- 분기내 포함, 별도 캐스팅 불필요
- JEP 394: instanceof에 대한 패턴 매칭
- 패턴이란 두 가지의 조합?
- 값에 적용될 술어
- 값에서 추출할 로컬 변수 집합
- 핵심은 술어가 값에 적용된 경우에만 패턴 변수가 추출된다는것
- 자바 17에서는 instanceof 연산자가 타입이나 타입 패턴을 받도록 확장된것
패턴 매칭과 프리뷰 기능
- 언어의 새로운 기능은 모두 동일한 생명 주기를 거침
- 프리뷰 → 공개 프리뷰 → 최종 기능으로 제공됨
- 여기서는 instanceof에서 switch로 패턴 매칭을 확장하는 프리뷰 기능을 살펴봄
- 알 수 없는 타입의 객체를 처리해야하는 경우 패턴 매칭
- 이렇게 작성하면 코드가 불편하고 장황해짐
- switch로 처리하면?
- 자바 17의 패턴 매칭 프리뷰 버전에서는 Sealed 타입과 긴밀하게 통합 할 수 있는 기능 존재
- 주의할 점
- case null을 포함, null-safe하고 NPE 발생을 예방
- default가 필요없음
- 컴파일러가 FX.. 모든 하위 타입 검사가능
- 누락된 케이스가 존재하는 경우에만 default를 사용하면됨
요약
- 여러 줄 문자열을 위한 Text 블록
- switch 표현식
- records
- seald 타입
- 패턴 매칭