제네릭(generic)
- 자바에서 제네릭이란 데이터의 타입을 일반화한다는 것을 의미한다.
클래스에서 사용하는 변수의 자료형이 다양할 수 있고, 그 메소드는 동일한 경우 클래스의 자료형을 특정하지 않고 추후 해당 클래스를 사용할 때 지정할 수 있도록 선언한다.
- 클래스나 메소드에서 사용할 내부 데이터 타입을 컴파일할 때 미리 지정하는 방법으로 클래스나 메소드 내부에서 사용되는 객체의 타입 안정성을 높일 수 있다.
class MyArray<T, K, V> {
T element;
void setElement(T element) { this.element = element; }
T getElement() { return element; }
}
- 위와 같이
< >
다이아몬드 연산자를 사용하여 선언한다.
T
, K
, V
를 타입 변수라고 하며, 임의의 참조형 타입을 의미한다. 어떠한 문자를 사용해도 상관이 없고, 쉼표로 구분하여 여러개를 명시할 수 있다.
MyArray<Integer> myArr = new MyArray<>();
- 제네릭 클래스를 생성하려면 다이아몬드 연산자 안에 사용할 실제 타입을 입력해야한다.
제네릭 사용 예시
- 예를 들어, 3D프린터 있고, 3D프린터에서 사용할 재료가 다양하다고 가정하자.
그러면 3D프린터는 각 재료마다 클래스를 만들어줘야 한다.
- 아래 코드는 재료로 사용하는 클래스이다.
public class Powder {
public String toString() {
return "재료는 Powder 입니다";
}
}
public class Plastic {
public String toString() {
return "재료는 Plastic 입니다";
}
}
- 각 재료마다 3D프린터 클래스를 만들어줘야한다.
- 지금은 재료가 2개뿐이지만, 재료가 1억개라고 한다면 1억개의 클래스를 각각 만들어줘야한다.
public class ThreeDPrinter1{
private Powder material;
public void setMaterial(Powder material) {
this.material = material;
}
public Powder getMaterial() {
return material;
}
}
public class ThreeDPrinter2{
private Plastic material;
public void setMaterial(Plastic material) {
this.material = material;
}
public Plastic getMaterial() {
return material;
}
}
- JDK 1.5 이전에서는 이러한 낭비를 줄이기위해 여러 타입을 사용하는 대부분의 클래스나 메소드에서 Object 타입을 사용하였다.
- 하지만 이 경우에서는 반환된 Object 객체를 다시 원하는 타입으로 타입 변환해야 하며,
오류가 발생할 가능성도 존재한다.
public class ThreeDPrinter{
private Object material;
public void setMaterial(Object material) {
this.material = material;
}
public Object getMaterial() {
return material;
}
}
- JDK 1.5 부터 도입된 제네릭을 사용하면 컴파일을 할 때 타입이 미리 정해지기 때문에, 오류가 발생하지 않고, 타입 변환도 쉬워진다.
public class GenericPrinter<T> {
private T material;
public void setMaterial(T material) {
this.material = material;
}
public T getMaterial() {
return material;
}
public String toString(){
return material.toString();
}
}
public class GeneriPrinterTest {
public static void main(String[] args) {
GenericPrinter<Powder> powderPrinter = new GenericPrinter<>();
powderPrinter.setMaterial(new Powder());
System.out.println(powderPrinter);
GenericPrinter<Plastic> plasticPrinter = new GenericPrinter<>();
plasticPrinter.setMaterial(new Plastic());
System.out.println(plasticPrinter);
}
}