JDK 17 기능

정훈·2023년 10월 19일
0

우테코

목록 보기
2/8

우테코 프리코스를 시작하기 전에는 JDK 11을 사용하였었다. JDK 11를 사용하면서 아직 불편한 점도 없었지만 프리코스를 시작하면서 JDK17 버전을 사용 하라는 문구를 보고 단순히 17 다운받아서 11처럼 사용해도 될 것 같았지만 JDK 17 버전에서 새롭게 생긴 부분이나, 추가 된 메서드 등을 학습해서 적극적으로 문제에 적용해 보기 위해 작성하게 되었다.

https://dzone.com/articles/whats-new-between-java-11-and-java-17 문서를 통해 참고 하였다.

String 메서드에 대해서 알게된 부분

strip: 문자열 공백 제거 (기존 “trim()”이 ‘\u0020’ 이하 공백만을 제거 하였다면, “strip()”은 유니코드의 공백들을 전부 제거)
stripLeading: 문자열 앞의 공백을 제거
stripTrailing: 문자열 뒤의 공백을 제거

이건 진짜 몰랐는데 ...

1. Text Blocks

String text = "{\n" +
                 "  \"name\": \"김정훈\",\n" +
                 "  \"age\": 26,\n" +
                 "  \"address\": \"서울시 송파구"\n" +
                 "}";
System.out.println(text);

Java11에서는 JSON 같은 문자열이 필요할때 아래 와 같은 이스케이프 처리로 가독성이 많이 안좋았지만,

위와 같은 방식대로 개발을 하였다면 JDK 17 버전에서는 아래와 같은 표현방식이 가능하다.

String text = """ 
				{ 
					"name": "김정훈", 
					"age": 26, 
					"address": "서울시 송파구"
				} 
		     """;
System.out.println(text);

위에 text 형식을 보면 큰 따옴표 세개를 통해 이전 이스케이프 방식보다 쉽게 사용 할 수 있다.

마지막 큰 따옴표는 텍스트 블록의 시작 위치 를 나타내며 왼쪽으로 이동하게되면 각 줄 앞에
아래와 같이 2개의 공백을 출력한게 된다 .

 // result 1 
  {  
	"name": 김정훈,
	 "age": 26, 
	 "address": "서울시 송파구" 
  }

마지막 큰따옴표를 아래와 같이 오른쪽 으로 옮겼다면 텍스트 블록의 시작이 첫 번째 문자에 의해 결정된다.

String text = """ 
				{ 
				  "name": "김정훈", 
				  "age": 26, 
				  "address": "서울시 송파구"
				} 
		               """;
// result 2  

{// result 1과 다르게 대괄호 시작하는 부분 앞에 공백이 없다 
  "name": 김정훈,
  "age": 26,  
  "address": "서울시 송파구" 
}

2. Switch Expressions

기존에 switch문 방식은 아래와 같다.

switch (hobby) {
        case "영화": {
        	System.out.println("영화");
    		break;
    	}
        case "게임" : {
        	System.out.println("게임");
    		break;
        }
}

하지만 아래와 같이 바뀐 Switch문을 보면 정말 가독성이 좋아진걸 확인 할 수 있다.

 switch (hobby) {
        case "영화" -> System.out.println("영화");
        case "게임" -> System.out.println("게임");
        default -> System.out.println("case에 없다");
}

몰랐던 부분이지만 출력문안에서도 가능하다고 하네요 ?!

	System.out.println(
    	switch (hobby) {
    	case "게임"-> "좋아하는 취미";
        case "오잉" -> "이건 취미가 아닌데";
        default -> "취미가 없네 ?"
    	}
    );

3. Records - 레코드 추가

Records는 현재 모르고 있는 부분을 새롭게 알게되는 부분이였다. Records는 JDK 14 버전일때 나온 것 같다.

레코드는 불변(immutable) 한 데이터 객체를 쉽게 생성할 수 있도록 하는 새로운 유형의 클래스이다.

기존에 불변한 데이터를 만들려고 한다면 아래와 같이 작성하였다.

public class User{
	private final String userName;
    privae final int age;
    
    public Person(String userName, int age) {
    	this.userName = userName; 
    	this.age = age; 
    }
    public int getAge(){
      ...
    }
    
    public String toString() {
    	...
    }
    public int hashCode(){
    	
    }
    public boolean equals(){
    
    }
	...

}

기존 스프링 프로젝트를 사용할때는 @ToString등 어노테이션을 적용해서 적용해서 사용하였지만, JDK17를 적용해서 사용한다면 더 쉽게 적용할 수 있을것같다.

아래는 레코드를 사용할 때 코드이다.

public record User(String userName, int age){
}

  • 레코드를 통해 명시하게되면 헤더를(userName,age) 통해 불변한 객체를 만들 수 있다.
  • 레코드는 final 클래스 이고, abstract 선언 불가하다.
    컴파일러가 헤드를 통해 내부 필드를 추론해서 생성자, toString,equals,hashCode 등을 제공한다고합니다.

4. Sealed Class

JDK15에서 제공되었던 Sealed Class가 JDK 17 에서 추가 되었다. Sealed Class는 interface나 class 상속, 구현 등 클래스를 지정된 해당 클래스만 상속 이나 구현을 하게 하는 기능 입니다. 쉽게 말해 봉인된 클래스입니다.

public sealed class Computer permits Mouse,KeyBoard{}

sealed

  • final, seald,non-sealed 키워드를 꼭 붙여서 사용해야한다.
  • 같은 패키지에 위치해야한다.
  • sealed 와 permits 는 필수로 넣어줘야한다.
  • non-sealed는 어떤 클래스도 상속할 수 있다라고 정의 하는 것.

permits

  • 허용되는 하위 타입 목록을 지정한다
  • 만약 같은 .java 파일에 하위 타입 클래스가 존재한다면 permits 키워드를 생략 할 수 있다.

5. Pattern matching for instanceof

public boolean equals(Object obj){
	if(obj instanceof User){
    	User uesr = (User) obj;
        ...
    }
}

객체 타입이 object인지 확인하기 위해 기존에 casting하는 과정이 있었지만 캐스팅 없이도 참조변수를 스코프안에 넣을 수 있다.

public boolean equals(Object obj){
	if(obj instanceof User user){
        ...
    }

6.Helpful NullPointerExceptions

기존에 Java11에서 사용할때 null값이 들어갔을 경우

Exception in thread "main" java.lang.NullPointerException
        at com.example.Application.HelpfulNullPointerExceptions.main(HelpfulNullPointerExceptions.java:13)

위 사진처럼 줄 번호 만 표시되는 부분이 있었지만, 어떤 메서드인지 분명하게 알 수 없었는데


17버전 부터는 정확한 발생 위치를 알려주게됩니다.

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.lang.Integer.intValue()" because the return value of "java.util.Map.get(Object)" is null
	at example.Application.main(Application.java:15)
  • 이건 좀 ....그래도 좋다 ! 콕 집어주네 ㅎㅎ

7. Compact Number Formatting Support

JDK 11 에서는 getCompactNumberInstance라는 메서드가 없었습니다, 하지만 JDK17부터는

getCompactNumberInstance 메서드를 통해 숫자 형식을 보다 간결하게 지정 할 수 있게 되었습니다.

//SHORT 
  NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.ENGLISH, NumberFormat.Style.SHORT);
        System.out.println(fmt.format(1000));
        System.out.println(fmt.format(100000));
        System.out.println(fmt.format(1000000));
        

//LONG
  NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.ENGLISH, NumberFormat.Style.LONG);
        System.out.println(fmt.format(1000));
        System.out.println(fmt.format(100000));
        System.out.println(fmt.format(1000000));
//SHORT style 
1K
100K
1M
// LONG style
1 thousand
100 thousand
1 million

오... 신기하다....

Stream.toList()

JDK 11 버전을 사용할때 아래와 같이 사용하였다. 하지만 JDK 17에서는 조금 더 간결하게 사용 가능한 toList()로 바뀌었다.

JDK 11
Stream<String> stream = Stream.of("1","2","3");
List<String> list = stream.collect(COllectors.toList());
JDK 17
Stream<String> stream = Stream.of("1","2","3");
List<String> list = stream.toList();

Referrence

0개의 댓글