자바 다이아몬드 연산자: Java 7+에서 제네릭 간소화하기
자바 다이아몬드 연산자(Diamond Operator)
다이아몬드 연산자(`<>`)는 Java 7에서 제네릭 코드 가독성을 높이기 위해 도입되었습니다. 제네릭은 타입 인자의 일종으로, 클래스 메서드에서 처리할 모든 종류의 객체를 전달할 수 있게 합니다. 예를 들어, Java 7 이전에는 문자열 리스트를 ArrayList 객체로 인스턴스화할 때 다음 구문을 사용해야 했습니다.
List<String> listOfStrings = new ArrayList<String>();
Java 7부터는 다이아몬드 연산자로 위 구문을 다음과 같이 간소화할 수 있습니다.
List<String> listOfStrings = new ArrayList<>();
단, 익명 내부 클래스에서는 사용할 수 없었습니다. 예를 들어, Java 9 이전에는 아래 구문에서 다이아몬드 연산자에서 객체 타입을 생략할 수 없었습니다.
Handler<Integer> intHandler = new Handler<Integer>(1) {
@Override public void handle() { System.out.println(content); }
};
익명 클래스에서의 다이아몬드 연산자
Java 9부터는 익명 클래스에서도 다이아몬드 연산자를 사용해 코드를 간소화하고 가독성을 높일 수 있습니다.
Handler<Integer> intHandler = new Handler<>(1) {
@Override public void handle() { System.out.println(content); }
};
Java 7, Java 8에서의 다이아몬드 연산자
아래 예제에서는 제네릭 인자를 받는 추상 클래스 Handler에 대한 익명 클래스를 생성하며, 익명 클래스 생성 시 객체 타입을 전달해야 합니다(전달하지 않으면 컴파일 에러).
예제
public class Tester {
public static void main(String[] args) {
// 익명 클래스로 1 처리
// Java 9 이전에는 다이아몬드 연산자에 타입 인자 전달 필수
Handler<Integer> intHandler = new Handler<Integer>(1) {
@Override public void handle() { System.out.println(content); }
};
intHandler.handle();
// 익명 클래스로 2 처리
Handler<? extends Number> intHandler1 = new Handler<Number>(2) {
@Override public void handle() { System.out.println(content); }
};
intHandler1.handle();
Handler<?> handler = new Handler<Object>("test") {
@Override public void handle() { System.out.println(content); }
};
handler.handle();
}
}
abstract class Handler<T> {
public T content;
public Handler(T content) { this.content = content; }
abstract void handle();
}
출력
1
2
Test
Java 9 이후 다이아몬드 연산자
Java 9부터는 아래와 같이 익명 클래스에서도 `<>` 연산자를 사용할 수 있습니다.
예제
아래 예제에서는 추상 클래스 Handler에 대한 익명 클래스를 생성하지만, 익명 클래스 생성 시 객체 타입을 전달하지 않습니다. 컴파일러가 타입을 자동 추론하기 때문입니다.
public class Tester {
public static void main(String[] args) {
// 익명 클래스로 1 처리
// Java 9 컴파일러가 타입을 자동 추론하므로 다이아몬드 연산자에 타입 인자 불필요
Handler<Integer> intHandler = new Handler<>(1) {
@Override public void handle() { System.out.println(content); }
};
intHandler.handle();
Handler<? extends Number> intHandler1 = new Handler<>(2) {
@Override public void handle() { System.out.println(content); }
};
intHandler1.handle();
Handler<?> handler = new Handler<>("test") {
@Override public void handle() { System.out.println(content); }
};
handler.handle();
}
}
abstract class Handler<T> {
public T content;
public Handler(T content) { this.content = content; }
abstract void handle();
}
출력
1
2
Test