제네릭을 사용하면 코드 재사용과 타입 안전성이라는 장점을 한 번에 잡을 수 있음
package generic.ex1;
public class GenericBox<T> {
private T value;
public void set(T value) {
this.value = value;
}
public T get() {
return value;
}
}
<>를 사용한 클래스를 제네릭 클래스라고 함
제네릭 클래스를 사용할 때는 Integer, String 같은 타입을 미리 결정하지 않음
그 대신 클래스명 오른쪽에 <T>와 같이 선언하면 제네릭 클래스가 됨
T를 타입 매개변수라고 함Integer, String으로 변할 수 있음클래스 내부에 T 타입이 필요한 곳에 T value와 같이 타입 매개변수를 적어두면 됨
package generic.ex1;
public class BoxMain3 {
public static void main(String[] args) {
GenericBox<Integer> integerBox = new GenericBox<Integer>(); //생성 시점에 T의 타입 결정
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 타입만 허용
String str = stringBox.get(); // String 타입만 반환
System.out.println("str = " + str);
//원하는 모든 타입 사용 가능
GenericBox<Double> doubleBox = new GenericBox<Double>();
doubleBox.set(10.5);
Double doubleValue = doubleBox.get();
System.out.println("doubleValue = " + doubleValue);
//타입 추론: 생성하는 제네릭 타입 생략 가능
GenericBox<Integer> integerBox2 = new GenericBox<>();
}
}
integer = 10
str = hello
doubleValue = 10.5
class GenericBox<T>
<>(다이아몬드 기호)안에 타입 매개변수를 정의하면 됨new GenericBox<Integer>()
GenericeBox의 T가 다음과 같이 지정한 타입으로 변한 다음 생성됨public class GenericBox<Integer> {
private Integer value;
public void set(Integer value) {
this.value = value;
}
public Integer get() {
return value;
}
}
T가 모두 Integer로 변함Integer 타입을 입력하고 조회할 수 있음integerBox.set(10); //성공
integerBox.set("문자100") // Integer 타입만 허용, 컴파일 오류
set(Integer value)이므로 이 메서드에는 Integer 숫자만 담을 수 있음String 타입을 담으려고 시도하면 컴파일 오류가 발생함Integer integer = integerBox.get(); // Integer 타입 변환(캐스팅X)
get()의 경우에도 Integer를 반환하기 때문에, 타입 캐스팅 없이 숫자 타입으로 조회가 가능함new GenericBox<String>()
String도 동일한 방식으로 사용하면 됨public class GenericBox<String> {
private String value;
public void set(String value) {
this.value = value;
}
public String get() {
return value;
}
}
T가 모두 String으로 변함GenericBox 객체를 생성하는 시점에 원하는 타입을 마음껏 지정할 수 있음new GenericBox<Double>()
new GenericBox<Boolean>()
new GenericBox<MyClass>()
제네릭을 도입한다고 해서 앞서 설명한 GenericBox<String>, GenericBox<Integer>와 같은 코드가 실제로 만들어지는 것은 아님
대신에 자바 컴파일러가 우리가 입력한 타입 정보를 기반으로 이런 코드가 있다고 가정하고 컴파일 과정에 타입 정보를 반영함
이 과정에서 타입이 맞지 않으면 컴파일 오류가 발생함
GenericBox<Integer> integerBox = new GenericBox<Integer>() // 타입 직접 입력
GenericBox<Integer> integerBox2 = new GenericBox<>() // 타입 추론
첫 번째 줄의 코드를 보면 변수를 선언할 때와 객체를 생성할 때 <Integer>가 두 번 나옴
<Integer>를 보고, 오른쪽에 있는 객체를 생성할 때 필요한 타입 정보를 얻을 수 있음따라서 두 번째 줄의 오른쪽 코드 new GenericBox<>()와 같이 타입 정보를 생략할 수 있음
이렇게 자바가 스스로 타입 정보를 추론해서 개발자가 타입 정보를 생략할 수 있는 것을 타입 추론이라고 함
자바 컴파일러가 타입을 추론할 수 있는 상황에만 가능함