본문 바로가기

Java

Java- 제네릭(2)

제네릭 클래스의 심화 문법

 제네릭 클래스간의 상속

일반 클래스간 상속이 가능하듯이 제네릭 간에도 상속이 가능하다.

class Box<T>{
    T ob;

    public T get() {
        return ob;
    }

    public void set(T ob) {
        this.ob = ob;
    }
}
class SteelBox<T> extends Box<T>{
    SteelBox(T o){
        ob = o;
    }
}

public class ExtendedGenericClass {
    public static void main(String[] args) {
        Box<Integer> iBox = new SteelBox<Integer>(123);
        
        //Box<Object> oBox = new SteelBox<Integer>(123);
        //Box<Number> nBox = new SteelBox<Integer>(123);
    }
}

제네릭 클래스 SteelBox<T>는 Box<T>를 상속받는다. 위 같은 방식으로 얼마든지 제네릭 간에도 상속이 가능하다. 그리고 main을 보자.

 

 1) Box<Integer> iBox = new SteelBox<Integer>(123);는 상위 클래스의 제네릭 타입은 Box<Integer>이고 이를 하위 클래스의 제네릭 타입 SteelBox<Integer>로 new 해주고 있다. 

 

 2) 주석 부분은 에러가 나는 부분이다. (1)과는 달리 주석부분에서는 에러가 발생하는데, 이는 기본적으로 제네릭 타입에 문제가 있기 때문이다. Object는 Integer를 상속한다. 또한 Number도 마찬가지이다. 또한 Box는 SteelBox의 상위 클래스이기 때문에 별 문제가 없는 것 같이 생각 할 수 있지만, 자바에서는 제네릭 타입의 경우 타입 인자(Object, Number, Integer)간의 상속 관계를 인정하지 않는다. 

 그로인해 Object, Number, Integer가 실제로는 상속관계를 가진다고 해도 타입 인자에서는 그것이 성립하지 않는다.

 

정리하자면...

  • Parent<T> = new Child<T>   (가능)
  • Parent<T1> = new Child<T2>  (타입 인자간 상속관계가 인정되지 않아 불가능)

 타겟 타입(Target Type)

이는 자바 컴파일러의 제네릭 자료형 유추능력과 관계가 있는 내용이다.

class Box<T>{
    T ob;

    public T get() {
        return ob;
    }

    public void set(T ob) {
        this.ob = ob;
    }
}
class BoxFactory{
    public static <T> Box<T> makeBox(){
        return new Box<T>();
    }
}

public class TargetTypes {
    public static void main(String[] args) {
        Box<Integer> iBox = BoxFactory.makeBox();  // 1
        iBox.set(1);

        Box<String> sBox = BoxFactory.<String>makeBox();  // 2
        sBox.set("String");

        Box<Double> dBox = new Box<>();  // 3
        dBox.set(1.1);

        Box<Long> lBox = new Box<Long>();  // 4
        lBox.set(12345678901234L);
    }
}

BoxFactory는 Box 인스턴스를 생성해서 반환하는 제네릭 메소드 makeBox를 갖고있다. main에는 1,2,3,4번 코드를 확인 할 수 있다. 1, 2만 보자.

 

2번을 보면 sBox의 제네릭 타입이 Box<String>이라서 BoxFactor.<String>makeBox();처럼 makeBox()의 인자도 <String>으로 지정해주었음을 볼 수 있다. 이제 1번을 보자.

 

1번은 2번과 동일한 코드이지만 makeBox앞에 타입 인자를 넣어주지 않았음을 볼 수 있다. 그래도 정상적으로 잘 실행이 된다. 이게 가능한 것은 자바 컴파일러가 Box<Integer>를 보고 makeBox()의 타입인자 <T>를 Integer로 유추했기 때문이다. 그리고 여기서 자바 컴파일러가 추론을 할 때 사용한 제네릭 타입 Box<Integer>를 "타겟 타입"이라고 한다.

 

3번과 4번도 비슷한 맥락이다. 3번은 4번과 달리 명시적으로 타입인자를 적어주지 않았지만 컴파일러에 의해 자동적으로 Double로 처리되었다.

'Java' 카테고리의 다른 글

Java- 사용자 지정 예외와 예외처리  (0) 2023.12.26
Java- 제네릭(3) 와일드 카드  (0) 2023.01.27
Java- 제네릭(1)  (0) 2023.01.07
Java- Arrays 클래스  (0) 2023.01.06
Java- Random 클래스, 난수 생성  (0) 2023.01.06