한모로그 2023. 2. 2. 14:41

제네릭 타입

  • 결정되지 않은 타입을 파라미터로 가지는 클래스와 인터페이스
  • 선언부에 ‘< >’ 부호가 붙고 그 사이에 타입 파라미터들이 위치


    출처, 이것이 자바다


  • 타입 파라미터는 일반적으로 대문자 알파벳 한 글자로 표현
  • 외부에서 제네릭 타입을 사용하려면 타입 파라미터에 구체적인 타입을 지정. 지정하지 않으면 Object 타입이 암묵적으로 사용
package ch13.sec02.exam01;

//제네릭 타입

public class Product <K, M> {

    //필드
    private K kind;  //제품명
    private M model; //모델명

    //메소드 getter, setter
    public K getKind() { return this.kind; }
    public M getModel() { return this.model; }
    public void setKind(K kind) { this.kind = kind; }
    public void setModel(M model) { this.model = model; }
}

package ch13.sec02.exam01;

public class Tv {

}

package ch13.sec02.exam01;

public class Car {

}

package ch13.sec02.exam01;

public class GenericExample {

    public static void main(String[] args) {

        //Product<Tv, String> product1 = new Product<Tv, String>();
        Product<Tv, String> product1 = new Product<>();

        product1.setKind(new Tv());
        product1.setModel("스마트Tv");

        Tv tv = product1.getKind();
        String tvModel = product1.getModel();

        Product<Car, String> product2 = new Product<>();

        product2.setKind(new Car());
        product2.setModel("SUV자동차");

        Car car = product2.getKind();
        String carModel = product2.getModel();
    }
}

인터페이스에서 제네릭 사용


package ch13.sec02.exam02;

/*
 인터페이스 : 제네릭 사용
 */

public interface Rentable<P> {
    //추상메소드. 리턴타입
    P rent();
}

package ch13.sec02.exam02;

public class Home {
    public void turnOnLight() {
        System.out.println("전등을 켭니다.");
    }
}

package ch13.sec02.exam02;

public class Car {
    public void run() {
        System.out.println("자동차가 달립니다.");
    }
}

package ch13.sec02.exam02;

public class HomeAgency implements Rentable<Home> {

    @Override
    public Home rent() {
        return new Home();
    }
}

package ch13.sec02.exam02;

public class CarAgency implements Rentable<Car> {

    @Override
    public Car rent() {
        return new Car();
    }        
}

package ch13.sec02.exam02;

public class GenericExample {

    public static void main(String[] args) {
        HomeAgency homeAgency = new HomeAgency();
        Home home = homeAgency.rent();
        home.turnOnLight();

        CarAgency carAgency = new CarAgency();
        Car car = carAgency.rent();
        car.run();
    }
}

Box의 내용물 비교를 위해 타입 파라미터로 Object의 equals() 메소드 호출 예시


package ch13.sec02.exam03;

/*
 제네릭은 파라미터 타입이 기본으로 Object 타입으로 간주된다.
 그래서, 제네릭 사용하지 않고 클래스를 사용하면, 타입 파라미터에 Object 타입이 적용된다.
 */
public class Box<T> {
    public T content; // Object content

    //Box의 내용물이 같은지 비교
    public boolean compare(Box<T> other) {
        //Object.equals()가 동작됨. 주소비교
        boolean result = content.equals(other.content); // Object.equals() "100".equals("100")
        return result;
    }
}

package ch13.sec02.exam03;

public class GenericExample {

    public static void main(String[] args) {

        //제네릭을 사용하지 않았으므로 Object
        Box box1 = new Box();
        box1.content = "100"; //String -> Object 형변환

        Box box2 = new Box();
        box2.content = "100"; //String -> Object 형변환

        Box box3 = new Box();
        box3.content = 100; //int -> Object 형변환(Boxing)

        boolean result1 = box1.compare(box2);     // "100".equals("100")
        System.out.println("result: " + result1); // true

        boolean result2 = box1.compare(box3);     // "100".equals(100)
        System.out.println("result: " + result2); // false
    }
}