Table of Contents

Java
Java 9부터 변경점
9
10
11(LTS)
12 ~ 17(LTS)

15

Text Block

여러 줄에 걸친 문자열을 만들기 위한 새로운 문법

12에서 preview였다가 15에서 정식 기능으로 승격

// """ 다음으로 문자가 올 수 없고, 한줄로 작성할 수 없다!
// \를 사용하면 개행 제거
// 들여쓰기도 가능
String str = """
  A
  BC
  DEF"""

Switch Expression 개선

12에서 preview였다가 14에서 정식 기능으로 승격

    private String calculateTestGrade1(int score) {
        return switch (score) {
            case 5:
                yield "A";
            case 4, 3:
                yield "B";
            case 2:
                yield "C";
            default:
                yield "F";
        };
    }
    
    private String calculateTestGrade2(int score) {
        return switch (score) {
            case 5 -> "A";
            case 4, 3 -> "B";
            case 2 -> {
                System.out.println("C!");
                yield "C";
            }
            default -> "F";
        };
    }

'Instance of' Pattern Matching

14에서 preivew였다가 16에서 정식 기능으로 승격

    public String say(Animal animal) throws IllegalAccessException {
        if (animal instanceof Dog dog) {
            return dog.bark();
        } else if (animal instanceof Cat cat) {
            return cat.purr();
        }

        throw new IllegalAccessException();
    }
    
    // 아래처럼 부정인 경우 Scope가 괄호 밖까지 확장 가능
    public String sayIfDog(Animal animal) throws IllegalAccessException {
        if (!(animal instanceof Dog dog)) {
            throw new IllegalAccessException();
        }

        return dog.bark();
    }


    public interface Animal {
    }

    public static class Dog implements Animal {
        public String bark() {
            return "Dog barking...";
        }
    }

    public static class Cat implements Animal {
        public String purr() {
            return "Cat purring...";
        }
    }

Record Class

데이터 전달을 위한 클래스 (DTO) → Lombok 기능을 대체

14에서 preivew였다가 16에서 정식 기능으로 승격

public record PersonDtoV1 (
        String name,
        int age
) {

    // Compact Constructor. 매개변수를 전혀 받지 않는다. this를 사용하지 않는다. (매개변수가 있다고 가정)
    /*public PersonDtoV1 {
    }*/
}

Sealed Class/Interface

하위 클래스를 지정된 클래스로만 상속을 제한(봉인)

자바 15에서 preview였다가 17에서 정식 기능으로 승격


    // 한 파일에 있다면 permits 생략 가능
    public sealed interface Animal permits Dog, Cat {
    }

    // final : 재상속 불가능
    // sealed : 한 번더 sealed class로 동작
    // non-seald : 상속 가능하지만 하위 타입 추적 불가능
    public final static class Dog implements Animal {
        public String bark() {
            return "Dog barking...";
        }
    }

    public final static class Cat implements Animal {
        public String purr() {
            return "Cat purring...";
        }
    }

18 ~ 21(LTS)

record pattern

19 Preview → 21 정식 record class를 instanceof pattern matching과 함께 사용할 때 내부 필드에 바로 접근할 수 있는 기능 (구조 분해)

    record Point(double x, double y) {}

    record Line(Point p1, Point p2) {}

    public static void findDistanceIfPoint2(Object object) {
        if (object instanceof Point(double x, double y)) {
            double distance = Math.hypot(x, y);
            System.out.printf("원점으로부터의 거리 : %3.f\n", distance);
        }

        if(object instanceof Line(Point(var x1, var y1), Point(var x2, var y2))) {
            double distance = Math.hypot(x1 - x2, y1 - y2);
            System.out.printf("두 점 사이의 거리 : %3.f\n", distance);
        }
    }

switch pattern matching

17 preivew → 21 정식

switch 선택자 안에 reference type도 들어갈 수 있는 기능

    public String say(Animal animal) {
        return switch (animal) {
            case Dog d -> d.bark();
            case Cat c -> c.purr();
            default -> throw new IllegalStateException("Unexpected value: animal");
        };
    }


    interface Animal {}

    public static class Dog implements Animal {
        public String bark() {
            return "Dog bark";
        }
    }

    public static class Cat implements Animal {
        public String purr() {
            return "Cat purr";
        }
    }

만약 sealed class로 상속을 제한하면 Dog와 Cat 두 가지 밖에 없으므로 switch 문의 default를 제거할 수 있다. 그러면 객체를 Enum처럼 사용할 수 있다.

    public String say(Animal animal) {
        return switch (animal) {
            case Dog d -> d.bark();
            case Cat c -> c.purr();
            // default가 필요없다!
        };
    }


    sealed interface Animal {}

    public static final class Dog implements Animal {
        public String bark() {
            return "Dog bark";
        }
    }

    public static final class Cat implements Animal {
        public String purr() {
            return "Cat purr";
        }
    }

한 번 더 검사할 수 있는 when 절도 생김

    public String say(Animal animal) {
        return switch (animal) {
            case Dog d when d.isQuiet() -> "";
            case Dog d -> d.bark();
            case Cat c -> c.purr();
        };
    }


    sealed interface Animal {}

    public static final class Dog implements Animal {
        public String bark() {
            return "Dog bark";
        }

        public boolean isQuiet() {
            return (new Random().nextBoolean());
        }
    }

    public static final class Cat implements Animal {
        public String purr() {
            return "Cat purr";
        }
    }

null인 경우 NPE가 발생하지 않고 제어할 수 있다.

    public String say(Animal animal) {
        return switch (animal) {
            case Dog d when d.isQuiet() -> Boolean.toString(d.isQuiet());
            case Dog d -> d.bark();
            case Cat c -> c.purr();
            case null -> "";
        };
    }

Virtual Thread

“가상 Thread n개 - 플랫폼 Thread 1개 - OS Thread 1개” Mapping 관계

여러 요청을 동시에 처리해 전체 처리량을 늘리는 기능. 그래서 단일 요청에서 플랫폼 Thread보다 느릴 수 있다.

Pooling 방식을 권장하지 않는다. 그때 그때 필요할 때 만들어 사용하라!

        /*Thread t = Thread.ofVirtual()
                .start(() -> System.out.println("Hello World!"));

        t.join();*/

        try (ExecutorService executorService = Executors.newVirtualThreadPerTaskExecutor()) {
            Future<?> future = executorService.submit(() -> System.out.println("Hello, Virtual Thread"));
            future.get();
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }


1) 참인 경우 뒤에 버림
2) 참인 경우 앞에 버림