파란하늘의 지식창고
Published 2020. 3. 30. 07:54
JDK 14 New Features Study/Java
반응형

JDK의 버전별 변경 사항은 이곳을 참고하세요.

Spec

Java SE 14 Platform JSR 389에 정의된 바와 같이 JSR 389 구현이 목표

실제 Spec은 Final Release Specification 문서를 참고해야 함

Final Release Specification Feature Summary

전체 JEP Feature 목록은 OpenJDK의 JDK 14 문서로 확인할 수 있다.

Component Feature
specification / language Pattern Matching for instanceof (Preview)
hotspot / runtime Helpful NullPointerExceptions
specification / language Records (Preview)
tools / javac Switch Expressions (Standard)
hotspot / gc Remove the Concurrent Mark Sweep (CMS) Garbage Collector
hotspot / gc Deprecate the ParallelScavenge + SerialOld GC Combination
specification / language Text Blocks (Second Preview)

JEP 305: Pattern Matching for instanceof (Preview)

Pattern Matching을 좀 더 편하게 사용할 수 있는 기능이 제공된다.

기존엔 instanceof를 다음처럼 사용하였다.

if (obj instanceof String) {
    String s = (String) obj;
    // use s
}

String 인 경우를 확인한 후 String으로 해당 값을 캐스팅하기 위한 과정이 필요했다.

다음과 같이 casting 후 변수 지정을 할 수 있게 된다.

if (obj instanceof String s) {
    // can use s here
} else {
    // can't use s here
}

이는 복잡한 조건식에도 적용이 가능하다.

if (obj instanceof String s && s.length() > 5) {.. s.contains(..) ..}

&& 연산자의 경우 s에 해당 값이 캐스팅되어 다음 조건 연산자에서 사용할 수 있고 블록 내에서도 사용할 수 있다.

하지만 아래처럼 || 연산인 경우 이후에 s가 생성되지 않기 때문에 사용할 수 없다.

if (obj instanceof String s || s.length() > 5) {.. s.contains(..) ..}

명시적인 캐스팅 수를 줄여준다.

@Override public boolean equals(Object o) { 
    return (o instanceof CaseInsensitiveString) && 
        ((CaseInsensitiveString) o).s.equalsIgnoreCase(s); 
}

위의 경우 아래처럼 줄일 수 있다.

@Override public boolean equals(Object o) { 
    return (o instanceof CaseInsensitiveString cis) && 
        cis.s.equalsIgnoreCase(s); 
}

JEP 358: Helpful NullPointerExceptions

NullPointerException에 대해 null 인 변수를 정확하게 설명하도록 수정되었다.

기존의 경우 아래 호출에 NullPointerException이 발생하면

a.i = 99;

아래처럼 발생한 파일 이름과 라인을 출력했다.

Exception in thread "main" java.lang.NullPointerException
    at Prog.main(Prog.java:5)

에러가 발생한 위치를 알 수 있지만 아래처럼 중첩해서 변수를 호출한 경우 어느 변수에서 NPE가 발생한 것인지 알기 어려웠다.

a.b.c.i = 99;

비슷한 경우로 배열을 사용하는 경우나 객체의 값을 지정하는 경우도 있다.

a[i][j][k] = 99;
a.i = b.j;

이제 아래처럼 NPE에 대해 에러를 설명하도록 변경되었다.

Exception in thread "main" java.lang.NullPointerException: 
        Cannot assign field "i" because "a" is null
    at Prog.main(Prog.java:5)
Exception in thread "main" java.lang.NullPointerException: 
        Cannot read field "c" because "a.b" is null
    at Prog.main(Prog.java:5)
Exception in thread "main" java.lang.NullPointerException:
        Cannot load from object array because "a[i][j]" is null
    at Prog.main(Prog.java:5)

a.i = b.j에서 NPE가 발생한 경우는 다음과 같다.

Exception in thread "main" java.lang.NullPointerException:
        Cannot read field "j" because "b" is null
    at Prog.main(Prog.java:5)

JEP 359: Records (Preview)

14에 preview로 추가된 record 란 개념이 생겼다.

record는 단순한 불변 데이터를 선언하기 위한 간단한 문법을 제공한다.

java 개발을 하면 대부분 lombok을 사용해 필드의 getter, setter를 간단하게 구현하게 되지만 순수 java는 object를 생성하고 기본적인 getter/setter를 관리하는 것이 불편하다.

kotlin은 아예 필드를 public으로 사용하고 getter, setter를 사용하지 않는 형태의 data class를 사용하는 것을 제안하는데 record는 이와 유사하다.

record Point(int x, int y) { }

다만 record는 확장할 수 없고, final 필드만 선언할 수 있다.

또한 선언된 모든 다른 필드는 static 하다.

따라서 생성자를 통해 필드가 선언되어야 한다.

유효성 검증을 생성자에서 사용해야 한다. 생성자는 아래처럼 쓴다. (생성자 매개 변수가 생략됨)

record Range(int lo, int hi) {
  public Range {
    if (lo > hi)  /* referring here to the implicit constructor parameters */
      throw new IllegalArgumentException(String.format("(%d,%d)", lo, hi));
  }
}

개인 의견 : 개인적으로 좋아하지 않는 방향이지만 간단한 데이터 도메인을 만들어 사용하기 위한 방식을 java에서 제공하는 것이려니 생각한다. Kotllin처럼 nullsafe 개념으로 확장하고 decorator 패턴을 쓰는 방향으로 가려는 것인지도 모르겠다.

JEP 361: Switch Expressions (Standard)

앞으로 표현식이나 구문으로 Switch 구문을 사용할 수 있게 된다.

Switch 표현식은 JDK 12에서 이미 Preview로 공개되었고 JDK 13을 거처 14에서 표준으로 지정되었다.

자세한 내용은 이전 글을 참고하면 된다.

2019/07/18 - [Study/Java] - JDK 12 New Features

2019/09/25 - [Study/Java] - JDK 13 New Features

JEP 363: Remove the Concurrent Mark Sweep (CMS) Garbage Collector

G1 GC가 나온 이후 옵션으로 계속 사용 가능했던 CMS가 제거된다. 

현재 G1과 ZGC, Shenandoah를 GC로 제공하고 있다.

또한 이번에 반영된 JEP 364, JEP 365를 통해 Window와 macOS에서 ZGC를 사용할 수 있도록 추가되었다. (둘 다 아직 Experimental이라 아래 옵션을 추가해서 사용한다.

-XX:+UnlockExperimentalVMOptions -XX:+UseZGC

JEP 366: Deprecate the ParallelScavenge + SerialOld GC Combination

CMS와 마찬가지로 ParallelGC도 제거된다.

JEP 368: Text Blocks (Second Preview)

JDK 13에 추가되었던 Text Block의 두 번째 Preview.

자세한 내용은 이전 글을 참고하면 된다.

2019/09/25 - [Study/Java] - JDK 13 New Features

추가된 내용은 New escape sequences인데 \<line-terminator>를 사용한 경우 명시적으로 개행 문자의 삽입을 억제한다.

코딩할 땐 줄 바꿔서 처리해도 실제 실행 시엔 줄이 안 바뀌는 기능이다.

기존 사용은 아래와 같다.

String literal = "Lorem ipsum dolor sit amet, consectetur adipiscing " +
                 "elit, sed do eiusmod tempor incididunt ut labore " +
                 "et dolore magna aliqua.";

이와 동일한 효과를 아래처럼 쓸 수 있게 된다.

String text = """
                Lorem ipsum dolor sit amet, consectetur adipiscing \
                elit, sed do eiusmod tempor incididunt ut labore \
                et dolore magna aliqua.\
                """;

또한 \s를 사용하면 후행 공백 제거를 방지할 수 있다.

아래처럼 사용하면 각 줄의 길이가 정확히 6자임을 보장한다.

String colors = """
    red  \s
    green\s
    blue \s
    """;

 

반응형
profile

파란하늘의 지식창고

@Bluesky_

내용이 유익했다면 광고 배너를 클릭 해주세요