JAVA 9

2020. 9. 6. 17:13Java/버전별 변화

728x90

불변 Collection 생성 메소드 제공

정적인 Collection 객체를 생성할 수 있는 팩토리 메소드를 제공합니다.

List<String> immutableList = List.of("one","two","three");
Set<String> immutableSet = Set.of("one","two","three");
Map<Integer,String> immutableMap = Map.of(1,"one",2,"two",3,"three");

Java 9 Module System

Java Module 시스템을 이용해 안정적인 구성과 강력하고 유연한 캡슐화를 제공합니다. 이를 통해 개발자는 확장 가능한 플랫폼을 만들고 플랫폼 무결성을 높이며 성능을 향상시킬 수 있습니다.

  • 편하고 효율적인 Java 개발 환경을 만들기 위해서 개발
  • Jar 기반 모노리틱 방식을 개선하여 모듈 지정 및 모듈별 버전 관리 기능이 가능
  • 필요한 모듈만 구동하여 크기와 성능 최적화가 가능
  • 임베디드와 같은 환경에서 필요한 모듈만 탑재되어 적은 메모리로 로딩이 가능
module java.sql {
    requires public java.logging;
    required public java.xml;
    exports java.sql;
    exports javax.sql;
    exports javax.transaction.xa;
}

Jshell

Java 9는 테스트 프로젝트나 main 메소드 없이 code snippets을 신속하게 테스트할 수 있는 대화식 REPL 도구를 제공합니다. 따라서 우리는 Java 기능을 쉽게 배우거나 평가해 볼 수 있습니다. 이제 Code 테스트를 위해 java 프로젝트를 만들거나 main 함수를 정의할 필요 없이 코드를 작성하고 즉시 실행하면 됩니다.

통일된 JVM 로깅

JVM 컴포넌트에 대한 공통 로깅 시스템을 제공합니다. 통합된 JVM 로깅은 모든 로깅 설정에 대한 새로운 명령줄 옵션 -Xlog를 사용하여 복잡한 수준의 JVM 구성요소에 대한 근본 원인 분석을 수행할 수 있는 쉬운 정밀 도구를 제공합니다.

  • Log 메시지는 tag를 사용하여 분류됩니다. 하나의 메세지는 다수의 tag를 가질 수 있습니다.
  • 로깅 레벨: error, warning, info, debug, trace, develop
  • 3가지 유형의 Output(stdout, stderr, text file)
  • 메세지는 time, uptime, pid, tid, level, tags 등으로 꾸밀 수 있습니다.

프로세스 API 개선

프로세스 검색을 위한 Java 9 Processs API로 모든 프로세스, 현재 프로세스, 하위 프로세스 및 종료된 프로세스 정보를 확인할 수 있게 되었습니다.

// 현재 프로세스
ProcessHandle current = ProcessHandle.current();

// 모든 프로세스
Stream<ProcessHandle> processStream = ProcessHandle.allProcesses();

// 종료된 프로세스
ProcessHandle destroy = ProcessHandle.destroy();

try-with-resources 개선

// Java 7
try(BufferedReader br = new BufferedReader(....)) {
    String line = br.readLine();
} catch (IOException e) {
    e.printStackTrace();
}

// Java 9
BufferedReader br = new BufferedReader(....)

try(br) {
    String line = br.readLine();
} catch (IOException e) {
    e.printStackTrace();
}

Diamond Operator의 한계를 개선

Java 7에 등장한 Diamond Operator는 익명클래스에 대해 제한적이었습니다.

// 아래 처럼 익명 클래스를 구현할 시, 컴파일 에러가 발생
MyHandler<Integer> handler = new MyHandler<>(10) { .... };

하지만, 익명 클래스에 대한 Diamond Operator를 할 수 있게 했습니다.

Interface Private Method

Java 8에서 interface 내에서 default 및 static method 생성이 가능해졌습니다. 하지만 특정 기능을 처리하는 내부 method일 뿐인데도 public method로 만들었어야 하고 구현체가 해당 method에 액세스 할 수 있어서 제대로된 캡슐화가 이루어지지 않았습니다. 하지만 private method를 구현할 수 있게 되면서 중복 코드를 피하고 interface에 대한 캡슐화를 유지할 수 있게 되었습니다.

public interface Sample {
    private String instancePrivate() {
        return "instance private";
    }
}

Reactive Stream API 추가

publish-subscribe 프레임워크를 지원하는 java.util.concurrent.Flow에서 Reactive Stream을 추가했습니다.

    @FunctionalInterface
    public static interface Publisher<T> {
        public void subscribe(Subscriber<?superT> subscriber);
    }
    public static interface Subscriber<T> {
        public void onSubscribe(Subscription subscription);
        public void onNext(Titem);
        public void onError(Throwable throwable);
        public void onComplete();
    }
    public static interface Subscription {
        public void request(long n);
        public void cancel();
    }
    public static interface Processor<T,R> extends Subscriber<T>, Publisher<R> {
    }

Optional 개선

Optional :: stream으로 Optional 객체 지연 작업을 제공하며 zeero 또는 하나 이상의 요소를 반환합니다.

// streamOptional(): [(Optional.empty(), Optional.of("one"), Optional.of("two"), Optional.of("three")]
List<String> newStrings = streamOptional()
                .flatMap(Optional::stream)
                .collect(Collectors.toList());
// Result: newStrings[one, two, three]

isPresent() 및 orElse()를 사용하고 코드를 보다 명확하게 만들고 "else" 케이스를 처리하는 대신 Java9의 ifPresentOrElse()메소드를 사용할 수 있습니다.

Optional<Integer> result3 = getOptionalEmpty();
result3.ifPresentOrElse(
        x -> System.out.println("Result = " + x),
        () -> System.out.println("return " + result2.orElse(-1) + ": Result not found."));
// return -1: Result not found.

or() 메소드는 값이 존재하는지 검사하고 해당 값이 있는 경우 해당 Optional을 리턴하고 그렇지 않은 경우 supplying function에서 생성한 다른 Optional 값을 리턴합니다.

Optional<Integer> result = getOptionalEmpty() // Empty Optional object
                .or(() -> getAnotherOptionalEmpty()) // Empty Optional object
                .or(() -> getOptionalNormal())  // this return an Optional with real value 42
                .or(() -> getAnotherOptionalNormal());  // this return an Optional with real value 99
        // Result: Optional[42]

CompletableFuture API 개선

CompletableFuture API에서 지연 및 시간 초과를 지원할 수 있도록 개선되었습니다.

CompletableFuture<String> future = doWork("JavaSampleApproach")
                                    .orTimeout(3, TimeUnit.SECONDS)
                                    .whenComplete((result, error) -> {
                                        if(error == null) {
                                            System.out.println("The result.is " + result);
                                        }
                                    });

future.completeAsync(supplier, CompletableFuture.delayedExecutor(3, TimeUnit.SECONDS))
    .thenAccept(result -> System.out.println("accept: " + result));

Stack-Walking API

StackWalker로 스택 추적을 필터링하여 지연 액세스를 위한 Stack Walking의 효율적인 방법을 제공합니다. StackWalker 객체를 사용하면 스택을 가로질러 액세스 할 수 있으며 여기에는 몇 가지 유용하고 강력한 메소드를 포함하고 있습니다.

    public <T> T walk(Function<? super Stream<StackFrame>, ? extends T> function);
    public void forEach(Consumer<? super StackFrame> action);
    public Class<?> getCallerClass();

Stream API 개선

iterate(), takeWhile(), dropWhile(), ofNullable()과 같은 새로운 추가 메소드를 사용하여 비동기 프로그래밍에 대한 몇 가지 유용한 개선 사항을 제공합니다.

// iterate()
IntStream
    .iterate(1, i -> i < 20, i -> i * 2)
    .forEach(System.out::println);

// takeWhile()
//for ordered Stream
Stream.of(1, 2, 3, 4, 5, 6).takeWhile(i -> i <= 3).forEach(System.out::println);
// The result is:
// 1
// 2
// 3
// for unordered Stream
Stream.of(1, 6, 5, 2, 3, 4).takeWhile(i -> i <= 3).forEach(System.out::println);
// The result is:
// 1

// dropWhile()
//for ordered Stream
Stream.of(1, 2, 3, 4, 5, 6).dropWhile(i -> i <= 3).forEach(System.out::println);
// It drops (1,2,3), the result is:
// 4
// 5
// 6
//for unordered Stream
Stream.of(1, 6, 5, 2, 3, 4).dropWhile(i -> i <= 3).forEach(System.out::println);
// It drops (1), the result is:
// 6
// 5
// 2
// 3
// 4

// ofNullable()
// numbers [1,2,3,null]
// mapNumber [1 - one, 2 - two, 3 - three, null - null]
List<String> newstringNumbers = numbers.stream()
                .flatMap(s -> Stream.ofNullable(mapNumber.get(s)))
                .collect(Collectors.toList());
// The result is: [one, two, three]

Multi-Resolution Image API

  • 해상도가 다른 다수의 이미지를 변형된 이미지로 캡슐화
  • 이미지에서 모든 변형을 얻음
  • 해상도 관련 이미지 변경 가져오기

Multi-Release Jars

특정 버전에서만 원하는 클래스가 동작하도록 할 수 있습니다.

multirelease.jar
├── META-INF
│        └── versions
│                 └── 9
│                          └── multirelease
│                                   └── Helper.class
├── multirelease
        ├── Helper.class
        └── Main.class

여기서 multirelease.jar는 Java 9 에서만 META-INF/veersions/9에 있는 Helper.class가 동작되도록 할 수 있습니다. 이렇게 하면 이 Helper.class 내에서는 Java 9의 기능을 온전히 활용할 수 있습니다.

728x90

'Java > 버전별 변화' 카테고리의 다른 글

Java 15  (0) 2021.10.07
Java 14  (0) 2021.09.25
Java 13  (0) 2021.09.19
Java 12  (0) 2021.09.06
Java 10  (0) 2021.08.10