확장된 try-with-resources
- 자바 7부터 생긴 try-with-resources 구문을 통해 생성한 자원을 정리하지 않는 실수를 막을 수 있고, 코드가 간단해짐
// AS-IS (Java 7 미만)
Resource resource = new Resource();
try {
...
} finally {
resource.close(); // finally 구문으로 인한 코드 복잡도 증가 + 실수로 빼먹을 수 있음
}
// TO-BE (Java 7)
try (Resource resource = new Resource()) { // 자동으로 리소스 close
...
}
- 그러나 자바 7의 try-with-resources 구문은 try 외부에서 선언한 자원에 대해서는 적용이 불가했음
- 자바 9는 try 외부에서 선언한 final 자원 or 생성 후 변경이 없는 자원에 대해서 적용 가능
// AS-IS (Java 7)
Resource resource = new Resource();
try (resource) { // 컴파일 에러
...
}
// TO-BE (Java 9)
final Resource r1 = new Resource(); // final
Resource r2 = new Resource(); // 선언 이후 변경 X
try (r1; r2) { // OK
...
}
@SafeVarargs를 private 메서드에 적용 가능
- 가변인자가 제네릭과 함께 쓰이면 컴파일 타임에 잡지 못하는 힙 오염(Heap Pollution)으로 인한 런타임 오류의 위험이 있다.
- 다음 예시와 같이 List<String>[] 형태의 가변인자를 Object[] 에 넣고, Object 원소로 Integer 값을 넣어도 컴파일 타임에 오류가 발생하지 않는다.
public static void flatten(List<String> ... lists) {
Object[] = lists; // List<String>[]
Object[0] = 1; // Integer (힙 오염, 컴파일 오류 X, 런타임 오류 발생)
...
}
- 런타임에 힙 오염으로 인한 오류가 발생한다.
- 이렇듯, 가변인자와 제네릭이 함께 쓰일 때 컴파일러는 기본적으로 경고하는데, 개발자가 해당 메서드가 이러한 경고에서 안전하다고 판단할 때 해당 어노테이션을 붙일 수 있다.
- 제네릭 가변인자가 안전하기 위해서는 두가지 조건이 필요하다.
- 가변인자 배열에 아무것도 저장하지 않는다. (메서드 내 변경 불가)
- 가변인자 배열이 외부에 노출되지 않는다. (참조를 통한 변경 불가)
- 해당 조건은 재정의 가능한 메서드에 대해서는 성립하지 않으므로 재정의 불가한 메서드에 대해서만 @SaveVarargs를 붙일 수 있다.
- 자바 8에서는 static, final 메서드에 대해서만 해당 어노테이션을 붙이는 게 가능했다.
- 자바 9부터는 private 메서드에 대해서도 해당 어노테이션을 붙일 수 있다.
inner class + diamond Syntax
- 자바 9 이전에는 제네릭 클래스인 inner class의 생성 시 우항에 반드시 해당 타입을 명시해주어야 했다.
- 자바 9 부터는 제네릭 클래스인 inner class 생성 시 우항에 타입을 생략할 수 있는 diamond syntax 적용이 가능하다.
public class Outer {
public static class InnerClass<T> {
public InnerClass() {
}
}
}
// AS-IS (Java 9 미만)
InnerClass<Integer> inner = new InnerClass<Integer>(); // 우항에 타입 명시 필수
// TO-BE (Java 9)
InnerClass<Integer> inner = new InnterClass<>(); // Diamond Syntax 적용 가능
Interface + private method
- 자바 9 이전에는 인터페이스에 대해 default method는 가능했으나, private method를 정의할 수 없었다. (public만 가능)
- 이는 코드의 중복 / 캡슐화의 어려움을 야기한다.
- 두개의 default method가 동일한 코드를 가지게 됨
- 공통 코드를 메서드로 뺐을 때, 두 default method에 필요한 일부 코드임에도 외부에 public으로 불필요하게 노출되어 캡슐화 어려움
// case 1. 코드 중복
public interface TestInterface {
default void defaultMethod1() {
int common = 10;
System.out.println("common logic" + common); // 공통로직 (중복)
System.out.println("default method 1");
}
default void defaultMethod2() {
int common = 10;
System.out.println("common logic" + common); // 공통로직 (중복)
System.out.println("default method 2");
}
}
// case 2. 중복 코드 메서드 추출 시 불필요한 외부 노출
public interface TestInterface {
default void defaultMethod1() {
commonLogic();
System.out.println("default method 1");
}
default void defaultMethod2() {
commonLogic();
System.out.println("default method 2");
}
default void commonLogic() { // default method에만 필요한 일부 코드임에도 불필요하게 public 노출
int common = 10;
System.out.println("common logic" + common);
}
}
- 자바 9 이후부터는 인터페이스에 private method의 정의가 가능해 코드의 중복제거, 재사용성 증대, 캡슐화 증대를 가져올 수 있다.
public interface TestInterface {
default void defaultMethod1() {
commonLogic();
System.out.println("default method 1");
}
default void defaultMethod2() {
commonLogic();
System.out.println("default method 2");
}
private void commonLogic() { // private 가능
int common = 10;
System.out.println("common logic" + common);
}
}
Reference
'Java' 카테고리의 다른 글
[Java 16] Switch Expression, instanceof Pattern Matching (0) | 2024.05.21 |
---|---|
[Java 9] 주요 변경내용 : Collection / Optional / Stream 관련 기능, 내부 문자열 처리방식, G1 GC (0) | 2024.05.18 |
[Java 9] 자바 플랫폼 모듈 시스템 (JPMS) (0) | 2024.05.16 |
인터페이스의 default method와 다이아몬드 문제 (0) | 2023.06.19 |
참조변수와 인스턴스에 따른 method, 변수, static method 참조 결과 비교 (0) | 2023.06.19 |