티스토리 뷰

Java 17 이 2021년 9월에 Release 됐고 최신 LTS 버전이 됐다. 아직도 Java 11, 8 등이 가장 많이 쓰이긴 하지만 Spring 6 부터는 최소 권장하는 자바 버전이 17 이상이고 다음 세대를 준비하기 위해 Java 17을 적극적으로 도입해야 하지 않을까 생각한다. JVM 성능 향상이나 기타 유틸리티등은 제외하고 코드를 작성할 때 자바 8 과 비교해서 자바 17일 선택할 경우 쓸 수 있는 주요 feature 들만 정리해보겠다. 


var keyword (java 10+)

가변형 변수 type 이다. 동적 타이핑 되는 python, 코틀린과 같은 언어에서 사용되고 있으면 java 에서도 도입했다.
멤버 변수로는 사용할 수 없으면 지역 스코프에서만 사용 가능하다. 

public void sayHello() {
    var greeting = "Hello world!";
    System.out.println(greeting);
}

항상 var 를 쓴다기 보다 위와 같이 타입을 보지 않아도 개발자도 충분히 추론 가능할 때 쓰면 좋을거 같다. (때론 타입이 선언 됐을 경우 가독성이 높다고 생각한다.)

record (java 14+)

Java 14에서 도입됐으면 코들린의 Data 클래스와 같은 데이터을 위한 클래스이다.

이전 자바에서는 DTO 클래스를 만들 경우 getter, setter , construcotr 등 직접 작성하거나 3rd party 라이브러리인 lombok 을 이용할 수 있었다. 하지만 Java 14 에 와서 record 라는 새로운 structure 추가됐고 이를 이용해 코틀린 처럼 DTO 클래스를 쉽게 만들 수 있다. 

public static void main(String[] args) {
    createMember();
}

public static void createMember() {
    var m  = new Member("marco", 30);
    System.out.println(m);
    System.out.println("Age=" + m.age());
    System.out.println("Name=" + m.name());
    //출력
    /*
    Member[name=marco, age=30]
	Age=30
	Name=marco
    */
}

public static record Member(String name, int age) {
    public Member(int age) {
        this("Anonymous", age);
    }
}

한 가지 아쉬운 점은 record 만으로 Builder 패턴은 적용하기 위해서 다음과 같은 라이브러리 추가가 필요하다.https://github.com/Randgalt/record-builder

 

GitHub - Randgalt/record-builder: Record builder generator for Java records

Record builder generator for Java records. Contribute to Randgalt/record-builder development by creating an account on GitHub.

github.com

 

Sealed Class (java 17+)

Sealed 클래스는 상속 제한을 위해서 도입됐다. 이 역시 코들린에 비슷한 기능이 있고 생각해보니 자바에서 신규 지원하는 많은 기능들이 코틀린에서 사용하는것 같다. 기존의 자바에서 상속 금지를 위해서 아래와 같이 약간의 기교(?)를 부려야 했다.

public final class Member {
 private Member() {
  //no constuctor
 }
}

- Sealed class 를 이용한 상속제한

public static sealed abstract class Bird permits Sparrow, Penguin {
    public abstract void fly();
}

public static final class Sparrow extends Bird {
    @Override
    public void fly() {
        System.out.println("Sparrow fly");
    }
}

public static final class Penguin extends Bird {
    @Override
    public void fly() {
        System.out.println("Penguin can't fly");
    }
}
public static final class Tiger extends Bird { //compile error: 'Tiger' is not allowed in the sealed hierarchy
    @Override
    public void fly() {
        
    }
}

인터페이스에서도 동일하게 사용가능하면 한가지 지켜야할 점은 점은 상속받는 클래스들 역시 반드시 final, sealed, non-sealed 세가지 키워드중 한 개를 사용해야 된다. 상속 받은 클래스(위 예제에서 Sparrow, Penguin) 들 역시 부모 클래스가 될 수 있기 때문에 제약성을 유지할지 아니면  상속 금지를 할지를 정해야 된다.(make sense하다.) 아래는 관련된 예시이다.

public static sealed class Sparrow  extends Bird permits KingSparrow {
    @Override
    public void fly() {
        System.out.println("Sparrow fly");
    }
}

public static non-sealed class Penguin extends Bird {
    @Override
    public void fly() {
        System.out.println("Sparrow fly");
    }
}

//Penguin non-sealed 이기 때문에 어떤한 클래스도 상속 가능
public static final class NorthPerson extends Penguin {
    public void fly(Bird bird) {
        bird.fly();
    }
}

public static final class KingSparrow extends Sparrow {
    public void fly(Bird bird) {
        bird.fly();
    }
}
//Sparrow 는 sealed class 로 KingSparrow 만 상속 가능하다.
public static final class NorthPerson extends Sparrow { //compile error 
    public void fly(Bird bird) {
        bird.fly();
    }
}

 

TextBlocks (Java 15+)

개인적으로 너무 환영하는 기능이다. 웹 애플리케이션에서 많이 사용하는 자바에서 SQL 과 같이 여러라인의 문자열을 사용할 일이 많은데 멀티라인이 될 경우 + 연산자 등으로 라인이 변경될 경우 코드가 읽기 어렵고 실수하기 쉽다. formatted 까지 이용하면 아래와 같이 깔끔한 멀티 라인 문자열 작성이 가능하다. 

public static void main(String[] args) {
    System.out.println(greeting("무명소졸"));
    //print Hello 무명소졸
}

public static String greeting(String name) {
    return """
        Hello %s
        """.formatted(name);
}

 

Optional methods (java 9+)

자바 8 에서 처음 소개된 Opitonal 은 null 에대한 처리를 좀 더 세련되게 처리 할 수 있다. feature 가 소개된 이후 활용도가 굉장히 높다.8 이후 버전에서 유용한 메서들이 추가 됐다. 아래는 예시이다.

public class Main {
    public static void main(String[] args) {
        Optional<String> test = Optional.ofNullable("무명소졸");

        if (test.isEmpty()) { //비어 있을 경우 체크 (java 11+) 이전에는 if (!test.isPresent()) 사고의 흐름과 반대되서 가독성이 떨어진다.
            System.out.println(test.get());
        }

        test.ifPresentOrElse(System.out::println, () -> System.out.println("Empty name")); //java 9+

        test.or(() -> Optional.of("Empty name")).ifPresent(System.out::println); //java 9+

        test.orElseThrow(() -> new IllegalArgumentException("Empty name")); //java 10+
    }
}


Stream() 의 toList() (java 16+)

collection stream 을 이용해 filter, map 등을 이용한 작업후 결과를 다시 List 등으로 반환할 때 아래와 같은 코드를 작성했다.

List<Integer> integers = List.of(1,2,3).stream()
    .filter(i -> i > 1)
    .collect(Collectors.toList());

오래전부터 .collect(Collectors.toList()) 가 verbose 한 느낌을 받았는데 16부터 아래와 같이 작성이 가능하다.

List<Integer> integers = List.of(1, 2, 3).stream()
    .filter(i -> i > 1)
    .toList();


New Instance of matching (java 16+)

객체의 타입을 비교하기 위한 문법이다. 이 또한 코틀린에 해당 기능이 있고 형 체크와 변환을 동시에 할 수 있는 유용한 기능이다.

//as-is
Flyable f1 = new Bird();
Flyable f2 = new Plane();

if (f1 instanceof Bird) {
    Bird b = (Bird) f1;
    b.fly();
}

//java 16+
Flyable f1 = new Bird();
Flyable f2 = new Plane();

if (f1 instanceof Bird b) {
    b.fly();
}

 

Enhancement Switch Expressions (Java 17+)

몇 차례 개선을 통한 자바 Switch 문은 Java 17 에 이르러 아래와 같은 형태와 같은 코딩까지 가능하게 됐다. switch case 문 자체가 가독성은 높았지만 타입 제약과 장황한 문법때문에 잘 안 쓰게 됐는데 이제 가독성이 높아졌으니 활용을 많이 해보자.

static double getDoubleUsingSwitch(Object o) {
    return switch (o) {
        case Integer i -> i.doubleValue();
        case Float f -> f.doubleValue();
        case String s -> Double.parseDouble(s);
        default -> 0d;
    };
}
//reference: https://www.baeldung.com/java-switch-pattern-matching

 

 

지금까지 Java 8 대신 Java 17을 사용할 때 쓸수 있는 몇 가지 feature 를 알아봤다. 그 외 많은 기능들이 있겠지만 많이 쓸만한 기능은 이정도로 정리 할 수 있을거 같다. 알려진바에 의하면 기존 자바 버전에서 최신 17을 도입했을 경우 많은 시스템들이 자원 효율의 증가와 속도 개선을 했다고 한다. 미션크리티컬하고 버전 업그레이드에 대한 비용 부담이 큰 조직이라면 업그레이드를 안 하는 편이 나을수 있겠지만 신규 프로젝트나 업그레이드 부담이 적은 조직이라면 최신 LTS 인 Java 17 도입은 적극적으로 검토할만하다.

참고

https://pretius.com/blog/java-17-features/

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크