Post

java11 to java17





참고



11 to 17

  • 오랜 기간 8 또는 11을 많이 사용해왔다.
  • 이제 스프링 6과 스프링 부트 3으로 버전업이 되었고,
  • jdk 17을 알아둘 필요가 있다고 느껴져 글로 정리하여 작성한다.





New features

  • 11에서 17로 변경하면서 새롭게 추가된 기능들을 정리한다.



텍스트 블록

1
2
3
4
{
    "name": "bogeun",
    "age": 20
}
1
2
3
4
5
6
7
8
9
10
11
12
13
String s1 = "{\n" +
    "    \"name\": \"bogeun\",\n" +
    "    \"age\": 20\n" +
    "}";

String s2 = """
    {
        "name": "bogeun",
        "age": 20
    }""";

sout(s1.equals(s2));  // true
sout(s1 == s2);       // true
  • 11까지는 위 json을 스트링으로 작성하려면 s1처럼 작성해야 했다.
    • 작성하는 것도 IDE를 사용하지 않으면 불편했고,
    • 읽는 것도 불편했다.
  • 17에서는 s2처럼 텍스트 블록을 사용할 수 있다.
    • 훨씬 편하게 작성할 수 있고
    • 보기도 편하다.
    • 다트에서 써보고 너무 편해서 왜 자바는 없나 했는데, 15부터 생겼다고 한다.
  • 그 외에도
    • 큰 따옴표를 이스케이프 처리하던 기존의 문자열의 문제점을 해결해준다.
    • 개행문자를 따로 작성하지 않아도 된다.
  • 주의해야할 것
    • 텍스트 블록을 여는 삼따옴표와 닫는 삼따옴표의 indent에 따라 만들어지는 텍스트 앞의 공백이 생길 수도 있다.



Switch 표현식

  • 기존의 스위치 문은 너무 많은 공간을 차지하고 불편했다.
    • 솔직히 스위치 문을 쓸까 싶다가도 그냥 if문으로 처리해 버렸다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
switch (operator) {
    case '+':
        System.out.println(n1 + n2);
        break;

    case '-':
        System.out.println(n1 - n2);
        break;

    case '*':
        System.out.println(n1 * n2);
        break;

    default:
        System.out.println("해당되는 연산자가 없습니다.");
        System.out.println("다시 입력해 주세요.");
}
  • 읽기 불편하다.
    • 너무 많은 공간을 차지한다.
  • 작성하기 불편하다.
    • 매 케이스마다 break를 넣어줘야 한다.
1
2
3
4
5
6
7
8
9
switch (operator) {
    case '+' -> System.out.println(n1 + n2);
    case '-' -> System.out.println(n1 - n2);
    case '*' -> System.out.println(n1 * n2);
    default  -> {
        System.out.println("해당되는 연산자가 없습니다.");
        System.out.println("다시 입력해 주세요.");
    }
}
  • 화살표 연산자로 훨씬 깔끔하고 간단하게 스위치 문을 작성할 수 있다.
    • 이 정도면 나도 쓸듯
  • 두 줄 이상의 코드를 실행해야 할 때는 중괄호 블럭으로 처리하면 된다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
System.out.println(switch (operator) {
        case '+':
            yield n1 + n2;
        case '-':
            yield n1 - n2;
        case '*':
            yield n1 * n2;
        default:
             yield "해당되는 연산자가 없습니다.\n" +
                    "다시 입력해 주세요.";
    });

int sum = switch(arrLength) {
    case 0 -> 0;
    case 1 -> yield arr[0];     // error
    default  -> {
        int temp = 0;
        for(int i = 0 ; i < arrLength ; i++) {
            temp += arr[i];
        }

        yield temp;
    }
};
  • 화살표 연산자 외에 yield 키워드도 사용할 수 있다.
    • 함수의 return과 비슷한 느낌이다.
    • break를 따로 작성하지 않아도 된다.
    • 기존의 스위치 문에서도 사용이 가능하다.
  • yield는 return과 비슷하다.
    • 화살표 스위치에서 하나의 결과만 보여준다면 yield를 넣어줄 필요가 없다.
      • 넣으면 컴파일 에러남.
    • 2줄 이상의 코드 블럭에서 리턴값을 명시해줄 때 사용된다.



Record

  • Record는 immutable한 데이터 클래스를 만들 수 있도록 해준다.
    • Record를 통해 boilerplate를 줄일 수 있다.
  • 기존에는 데이터 클래스를 만들기 위해서
    • 직접 constructor, getter, setter, hashCode(), equals(), toString() 등의 메서드들을 만들거나
    • lombok에 의존하는 경우가 많았다.
  • Record는 간단하게 데이터 클래스를 만들 수 있게 해준다.



1
2
3
4
5
6
7
8
9
10
11
public class PersonDto {
    // constructor

    // getter

    // setter

    // toString()

    // ...
}
  • 기존에 우리가 데이터 클래스를 만들던 방식이다.
1
2
public record PersonRecord(String name, int age, Gender gender) {
}
  • Record는 class 대신 record 키워드를 사용해 만들 수 있다.
  • 이렇게만 작성해도 위와 같은 메서드를 지원한다.
    • constructor, getter 등
    • Record는 불변 객체이기 때문에 setter는 지원하지 않는다.



1
2
3
4
5
6
7
8
9
10
PersonRecord p1 = new PersonRecord("bogeun", 20, Gender.MALE);
PersonRecord p2 = new PersonRecord("babo", 10, Gender.FEMALE);

sout(p1.name()); // getter
sout(p1.age());
sout(p1.gender());

sout(p1); // toString()

sout(p1.equals(p2));
  • 위와 같은 방식으로 사용할 수 있다.
    • 대부분 같지만 getter()만 살짝 다르다.
  • Record도 내부에 메서드를 작성할 수 있다.
    • toString()이나 다른 메서드들도 재정의가 가능하다.



Sealed Class





This post is licensed under CC BY 4.0 by the author.