제네릭을 사용하면 타입 안정성과 코드 재사용성의 두가지 장점을 한번에 잡을 수 있다.
package generic.ex1;
public class GenericBox<T> {
private T value;
public void set(T value) {
this.value = value;
}
public T get() {
return value;
}
}
package generic.ex1;
public class BoxMain3 {
public static void main(String[] args) {
// 생성 시점에 T의 타입이 결정
GenericBox<Integer> integerBox = new GenericBox<Integer>();
integerBox.set(10);
// integerBox.set("100"); // Integer 타입만 허용, 컴파일 오류
Integer integer = integerBox.get(); // Integer타입 반환 (캐스팅X)
System.out.println("integer = " + integer);
GenericBox<String> stringBox = new GenericBox<String>();
stringBox.set("hello");
String str = stringBox.get();
System.out.println("str = " + str);
// 원하는 모든 타입 사용 가능
GenericBox<Double> doubleGenericBox = new GenericBox<>();
doubleGenericBox.set(10.5);
Double doubleBoxValue = doubleGenericBox.get();
System.out.println("doubleBoxValue = " + doubleBoxValue);
// 타입 추론: 생성하는 제네릭 타입 생략 가능
GenericBox<Integer> integerBox2 = new GenericBox<>();
}
}
타입 매개변수를 이용하면 내가 원하는 타입으로 생성할 수 있다.
참고로 제네릭을 사용한다고 GenericBox, GenericBox 같은 코드가 실제로 만들어지는 것은 아니다.
자바 컴파일러가 이러한 타입이 있다고 가정을 하고 타입 정보를 반영한다.
이 과정에서 타입이 맞지 않을 경우 컴파일 에러를 발생시킨다.
GenericBox<Integer> integerBox = new GenericBox<Integer>() // 타입 직접 입력
GenericBox<Integer> integerBox2 = new GenericBox<>() // 타입 추론
변수를 선언할 때의 다이아몬드, 인스턴스를 생성할 때의 다이아몬드가 존재한다.
변수를 선언할 당시의 타입을 지정하면 오른쪽에 있는 객체는 타입을 추론할 수 있다.
따라서, 두번째 줄의 new GenericBox<>의 타입은 따로 지정하지 않아도 된다.
단, 언제나 되는 것은 아니고 자바 컴파일러가 추론 가능할 때만 된다.