변수의 선언이나 메서드의 매개 변수를 하나의 참조 자료형이 아닌
여러 자료형으로 변환 될 수 있도록 프로그래밍 하는 방식입니다.
실제 사용되는 참조 자료형으로의 변환은 컴파일러가 검증하므로 안정적입니다.
public class Plastic {}
public class Powder {}
모든 클래스는 'Object'의 하위 클래스이므로 자료형을 'Object'로 대체 할 수 있습니다.
그러므로 'Plastic'이든 'Powder'든 모든 재료의 타입으로 사용해 호출 할 수 있습니다.
public class TreeDPrinter {
private Object material;
public Object getMaterial() {
return material;
}
public void setMaterial(Object material) {
this.material = material;
}
}
모든 참조 자료형을 쓰고 싶다면 'Object'를 일단 쓸 수 있지만
원하는 타입으로 반환 받으려면 다운캐스팅이 필요합니다.
public class TreeDPrinterTest {
public static void main(String[] args) {
TreeDPrinter printer = new TreeDPrinter();
printer.setMaterial(new Powder());
Powder powder = (Powder)printer.getMaterial();
// 다운캐스팅 하지 않는 경우 - Type mismatch: cannot convert from Object to Powder
}
}
여러 참조 자료형으로 대체 될 수 있는 부분을 하나의 문자로 표현합니다.
이 문자를 자료형 매개 변수
라고 합니다.
사용할 자료형이 대체 될 곳을 '<>' 표시로 감싸고 참조할 타입(클래스)을 쓰면 됩니다.
위에서 작성한 'TreeDPrinter' 클래스를 제네릭 클래스로 만들면 아래와 같습니다.
이후 제네릭 클래스 객체를 생성하고 메서드를 호출하는 것(TreeDPrinterTest)은
아래와 같이 변경 할 수 있습니다.
위에서는 다운캐스팅을 해야 했는데, 여기서는 제네릭 클래스로 참조할 타입을 명시하므로
따로 다운캐스팅(강제 형 변환) 할 필요 없이 컴파일 할 때에 자동으로 찾습니다.
public class TreeDPrinterTest {
public static void main(String[] args) {
TreeDPrinter<Powder> printer = new TreeDPrinter<Powder>();
printer.setMaterial(new Powder());
Powder powder = printer.getMaterial();
}
}
.. 그나저나 ThreeDPrinter 라고 써야하는데 h를 빼먹었네요
아래와 같이 대체할 참조 매개 변수에 'extends 제한할 클래스명(여기서는 Material)'을 추가하면 됩니다.
그러면 해당 클래스를 상속받은 타입만 사용할 수 있습니다.
public class TreeDPrinter<T extends Material> {}
이때 상위 클래스를 추상 클래스(abstract)로 설정하면서 메서드를 선언하면
구현 클래스에서 해당 메서드들을 구현하게 되는데
이 경우 'Object' 클래스의 메서드 뿐 아니라 새로 구현한 메서드 또한 호출 할 수 있습니다.
'Type'의 의미로 'T'를 많이 사용합니다. <T>에서 <>는 다이아몬드 연산자
라고 합니다.
'static' 키워드를 사용하면 인스턴스 생성과 관계없이 메모리를 잡기 때문에 'T'에 사용할 수 없습니다.
다이아몬드 연산자 내부에서 자료형은 생략 가능 합니다.
ArrayList<String> list = new ArrayList<>();
자바 10부터 제네릭 자료형 추론이 가능합니다.
// 기존
ArrayList<String> list = new ArrayList<String>();
// 자바 10 이후
var list = new ArrayList<String>();
용어 | 설명 |
---|---|
GenericPrinter<Powder> | 제네릭 자료형(Generic Type), 매개 변수화 된 자료형(Parameterized Type) |
Powder | 대입된 자료형 |
GenericPrinter<Powder> 과 같이 사용할 자료형(Powder)을 명시해야합니다.
자료형을 명시하지 않고 사용할 수는 있지만 이 경우 자료형을 명시하라는 경고가 나타납니다.
반환되는 형태에 따라 강제 형 변환을 해야 합니다.
이는 맨 처음 제네릭 프로그래밍을 이야기하면서 작성한 코드에서
다운캐스팅 한 것에 대한 이야기입니다.
메서드의 매개 변수를 자료형 매개 변수로 사용하는 경우가 있습니다.
public class Point<T, V> {
T x;
V y;
Point (T x, V y) {
this.x = x;
this.y = y;
}
public T getX() {
return x;
}
public V getY() {
return y;
}
}