변수의 선언, 메소드의 반환형, 매개변수의 자료형 등 모든 것은 자료형을 가진다. 이미 한 번 정의 된 자료형은 상속 관계의 상위 자료형의 형 변환이 아니면 바꿀 수 없다. 하지만 제네릭이란 기술을 사용하면 여러 참조 자료형을 유연하게 대입할 수 있다.

제네릭은 객체가 생성되는 순간 자료형이 정해지게 한다.

 

1. 제네릭


제네릭은 다이아몬드 연산자 <> 안에 자료형을 명시해주면서 객체를 생성한다. 3D 프린터 클래스와 프린팅 재료를 예로 들어 사용법을 보자.

package genericex;

//파우더 재료 클래스
public class Powder {

   public void doPrinting() {
      System.out.println("use powder to print");
   }

   @Override
   public String toString() {
      return "The material is powder";
   }
}

 

package genericex;

//플라스틱 재료 클래스
public class Plastic {

   public void doPrinting() {
      System.out.println("use plastic to print");
   }

   @Override
   public String toString() {
      return "The material is plastic";
   }
}
package genericex;

public class GenericPrinter<T> {

   private T material;

   public T getMaterial() {
      return material;
   }

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

   @Override
   public String toString() {

      return material.toString();
   }

}

클래스를 선언하면서 오른쪽에 라고 썼다. T를 자료형 매개변수라고 한다. 이제부터 클래스 안의 멤버변수, 메소드의 반환형, 혹은 메소드의 매개변수의 자료형으로 T를 사용할 수 있다. 그리고 나중에 객체를 생성할 때 정해준 자료형이 T를 대체하며 컴파일 된다.

이로써 클래스를 선언할 때에는 어떠한 참조자료형이 들어갈 지 몰라 제네릭 프로그래밍을 해주어서 유연하게 자료형이 변환될 수 있다.

이제 실행을 시켜보자.

package genericex;

public class GenericPrinterTest {

   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);
   }
}

실행결과

The material is powder

The material is plastic

 

2. 자료형 매개변수의 자료형 제한


예를 들어 프린터를 하려는데 누가 재료로 물을 넣어주려 한다고 해보자. 물로는 프린팅을 할 수 없다. 이런 경우처럼 자료형 매개변수를 특정 타입으로 재한하려 하는 경우 T를 extends 예약어로 상속받을 수 있다.

package genericex;

public class GenericPrinter<T extends Material> {
   ...    
}

 

여기서 Material이라는 추상 클래스를 상속 받았다. Material 추상클래스에는 Powder, Plastic 클래스에 구현된 메소드들이 있다.

package genericex;

public abstract class Material {

   public abstract void doPrinting();
}

 

이후 T에 Material을 상속받은 클래스가 들어오는 경우가 아니면 컴파일 오류가 난다.

그리고 T는 Material을 상속받았으므로 Material 추상클래스에 정의 된 모든 메소드를 사용할 수 있다.

package genericex;

public class GenericPrinter<T extends Material> {

      ...

   public void printing() {
      material.doPrinting(); //T 자료형인 material은 Material클래스의 doPrinting()메소드 사용 가능
   }
}

 

'프로그래밍 언어 > Java' 카테고리의 다른 글

(Java) 46 - Map 인터페이스  (0) 2020.05.17
(Java) 45 - Set 인터페이스  (0) 2020.05.17
(Java) 43 - List 인터페이스  (0) 2020.05.17
(Java) 42 - 컬렉션 프레임워크  (0) 2020.05.17
(Java) 41 - Wrapper 클래스  (0) 2020.05.17

+ Recent posts