2020. 9. 6. 17:13ㆍJava/버전별 변화
불변 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의 기능을 온전히 활용할 수 있습니다.