목차

Java; Generics Type

🗓️

제네릭

제네릭이란?

  • 프로그램에서 변수를 선언할 때 모든 변수는 자료형이 있다.
  • 메소드에서 인자를 사용할 때도 자료형을 갖고 있따.
  • 변수나 메소드의 자료형을 필요에 따라 여러 자료형으로 바꿀 수 있다면 프로그램이 훨씬 유연할 것이다.
  • 어떤 갑싱 하나의 참조 자료형이 아닌 여러 참조 자료형을 사용할 수 있도록 프로그래밍 하는 것을 Generic programming 이라고 한다
  • Generic 프로그램은 reference 자료형에 대한 검증을 컴파일러가 해 안정적이다.
  • Collection 역시 generic으로 구현되어있다 (ex ArrayList<String>)

제네릭의 정의

public class GenericPrinter<T> {
    private T material;

    public void setMaterial(T material) {
        this.material = material;
    }

    public T getMaterial() {
        return material;
    }
}
  • 여러 자료형으로 바꿔 사용할 material 변수의 자료형을 T라고 지정했다. 이때의 T를 type parameter라고 부른다.
  • 클래스 이름을 GenericPrinter<T>라고 정의하고 나중에 클래스를 사용할때 T위치에 실제 사용할 자료형을 지정한다.

다이아몬드 연산자

  • 자바 7부터는 제네릭 자료형의 클래스를 생성할 때 생성자에 사용하는 자료형을 명시하지 않을 수 있다.
ArrayList<String> list = new ArrayList<>();

자료형 매개변수 T와 static

  • static 변수나 메소드는 인스턴스 생성 여부와 상관 없이 클래스 이름으로 호출할 수 있다.
  • 그런데 T의 자료형이 정해지는 순간은 generic 클래스의 인스턴스가 생성되는 순간이다. 따라서 T의 자료형이 결정되는 시점보다 빠르기 때문에 static변수의 자료형이나 메소드 내부 변수의 자료형으로 T 키워드를 사용할 수 없다.

제네릭 테스트

  • generic을 사용할 나머지 클래스를 만든다.
public class ABS {
    public void doPrinting() {
        System.out.printf("Using ABS");
    }

    public String toString() {
        return "Material is ABS.";
    }
}
public class PBT {
    public void doPrinting() {
        System.out.printf("Using PBT");
    }

    public String toString() {
        return "Material is PBT.";
    }
}
public class GenericPrinterTest {
    public static void main(String[] args) {
        GenericPrinter<ABS> absPrinter = new GenericPrinter<>();

        absPrinter.setMaterial(new ABS());
        ABS abs = absPrinter.getMaterial();
        System.out.println(absPrinter);

        GenericPrinter<PBT> pbtPrinter = new GenericPrinter<>();

        pbtPrinter.setMaterial(new PBT());
        PBT pbt = pbtPrinter.getMaterial();
        System.out.println(pbtPrinter);
    }
}
  • 아래는 실행결과다
Material is ABS.
Material is PBT.

T 자료형에 사용할 자료형을 제한하는 <T extends Class>

  • 제네릭 클래스에서 T에 사용할 자료형을 제한할 수 있다.
  • abstract 클래스의 extends를 통해 구현한다.
public abstract class Material {
    public abstract void doPrinting();
}

추상클래스에 대해 상속(extends)을 받는다.

public class ABS extends Material {
    public void doPrinting() {
        ...

public class ABS extends Material {
    public void doPrinting() {
        ...
  • 그리고 제네릭 클래스에 다음과 같이 추가한다
public class GenericPrinter<T extends Material> {
    private T material;
...
  • 이렇게 하면 Material을 상속(extends)받는 클래스만이 제네릭을 사용할 수 있게 된다.