Java 8과 11에 이은 새로운 LTS(Long-Term Support) 버전인 Java 17이 릴리즈 되었다.
토이 프로젝트에서 Spring Boot 3.1.0 버전을 사용하게 되었는데, 스프링 부트 3 버전부터는 Java17 이상을 지원한다.
따라서 Java11이후의 Java17의 주요 변경점을 알아보자
1. 텍스트 블록
private static void oldStyle() {
String text = "{\n" +
" \"name\": \"John Doe\",\n" +
" \"age\": 45,\n" +
" \"address\": \"Doe Street, 23, Java Town\"\n" +
"}";
System.out.println(text);
}
위와 같이 JSON 문자열 생성시 큰 따옴표를 통해 이스케이프 처리 및 가독성이 떨어지는 문제를 해결해 주었습니다.
private static void jsonBlock() {
String text = """
{
"name": "John Doe",
"age": 45,
"address": "Doe Street, 23, Java Town"
}
""";
System.out.println(text);
}
2. Switch 표현식
기존의 스위치 표현식은 다음과 같습니다
private static void oldStyleWithBreak(Fruit fruit) {
switch (fruit) {
case APPLE, PEAR:
// multivalue labels, and are indeed not supported prior to Java 14
System.out.println("Common fruit");
break;
case ORANGE, AVOCADO:
System.out.println("Exotic fruit");
break;
default:
System.out.println("Undefined fruit");
}
}
기존의 스위치 표현식에서는 break누락, 가독성 문제가 있었는데, 다음과 같이 변경하였습니다.
private static void withSwitchExpression(Fruit fruit) {
switch (fruit) {
case APPLE, PEAR -> System.out.println("Common fruit");
case ORANGE, AVOCADO -> System.out.println("Exotic fruit");
default -> System.out.println("Undefined fruit");
}
}
위와 같은 스위치문을 반환값으로 이용할 수 있습니다.
private static void withReturnValue(Fruit fruit) {
String text = switch (fruit) {
case APPLE, PEAR -> "Common fruit";
case ORANGE, AVOCADO -> "Exotic fruit";
default -> "Undefined fruit";
};
System.out.println(text);
}
하나의 스위치문에서 여러개의 동작을 사용할 때는 다음과 같이 사용합니다.
private static void withYield(Fruit fruit) {
String text = switch (fruit) {
case APPLE, PEAR -> {
System.out.println("the given fruit was: " + fruit);
yield "Common fruit";
}
case ORANGE, AVOCADO -> "Exotic fruit";
default -> "Undefined fruit";
};
System.out.println(text);
}
yield
키워드를 이용해서 값을 리턴시켜 줄 수 있습니다.
예전 스위치 문에서도 yield 키워드를 사용 할 수 있으며, break 키워드는 사용하지 않아도 됩니다.
private static void oldStyleWithYield(Fruit fruit) {
System.out.println(switch (fruit) {
case APPLE, PEAR:
yield "Common fruit";
case ORANGE, AVOCADO:
yield "Exotic fruit";
default:
yield "Undefined fruit";
});
}
3. Records
Java14 부터 도입된 Record 클래스는 불변 데이터를 객체 간에 전달하는 작업을 간단하게 만들어준다. Spring에서의 반복되는 보일링 플레이트 코드를 제거 할 수 있고, 적은 코드로도 명확하게 의도를 표현 할 수 있게 만들어 줍니다.
Record의 특징
- 멤버변수는 private final로 선언된다.
- 필드별 모든 getter가 자동으로 생성된다.
- 모든 멤버변수를 인자로 하는 public 생성자를 자동으로 생성한다.
- equals, hashcode, toString을 자동으로 생성한다.
- 기본 생성자는 제공하지 않으므로 필요한 경우 직접 생성해야한다.
해당 기능은 Dto 클래스에서 중복되는 코드를 줄이기 위해 고안되었는데, 기존의 코드와 비교해 봅시다.
기존의 코드에서는 Lombok에서 제공하는 어노테이션을 통해 Dto를 주로 생성하였습니다.
요청용 Dto 예시이고, 컨트롤러에서 @RequestBody
를 통해 해당 Dto의 생성자로 값이 초기화 됩니다.
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class PatientRequestDto {
private String loginId;
private String password;
public Patient toPatient(PasswordEncoder passwordEncoder) {
return Patient.builder()
.loginId(loginId)
.password(passwordEncoder.encode(password))
.userRole(UserRole.PATIENT)
.build();
}
}
이를 recode로 바꾸어 보면,
public record PatientRequestDto (
String loginId,
String password
){
public Patient toPatient(PasswordEncoder passwordEncoder) {
return Patient.builder()
.loginId(loginId)
.password(passwordEncoder.encode(password))
.userRole(UserRole.PATIENT)
.build();
}
}
이렇게 바꿀 수 있습니다.
Dto가 가지고 있는 Lombok의 의존성을 지울 수 있으며, 소괄호 안에 멤버변수를 포함되게 됩니다.
해당 멤버변수들은 기존적으로 private으로 선언되므로, 접근 제어자를 명시해주지 않습니다.
4. Instanceof 변수 생성
instanceof를 이용해서 객체를 체크할시, 변수를 생성가능 하게 변경하였습니다.
private static void oldStyle() {
Object o = new GrapeClass(Color.BLUE, 2);
if (o instanceof GrapeClass) {
GrapeClass grape = (GrapeClass) o;
System.out.println("This grape has " + grape.getNbrOfPits() + " pits.");
}
}
private static void patternMatching() {
Object o = new GrapeClass(Color.BLUE, 2);
if (o instanceof GrapeClass grape) { // 변수 생성
System.out.println("This grape has " + grape.getNbrOfPits() + " pits.");
}
}
5. Stream.toList()
이제 Stream에서 List로 변환시에, 기존의 Collectors.toList()
를 호출하지 않고, toList() 만으로 List형식으로 변경이 가능하다.
private static void oldStyle() {
Stream<String> stringStream = Stream.of("a", "b", "c");
List<String> stringList = stringStream.collect(Collectors.toList());
for(String s : stringList) {
System.out.println(s);
}
}
private static void streamToList() {
Stream<String> stringStream = Stream.of("a", "b", "c");
List<String> stringList = stringStream.toList();
for(String s : stringList) {
System.out.println(s);
}
}
참고
https://dzone.com/articles/whats-new-between-java-11-and-java-17