java 제네릭중 제한에 대해 알아보자

솔직히 주니어 개발자들은 제니릭을 제대로 쓰는사람은 드물것으로 예상된다. 물론 나도 완벽히 이해 하지 못했다.ㅠㅠ
그만큼 제네릭은 쉽지 않다.
여기 포스팅에선 제네릭을 설명은 하지 않고 제네릭의 제한만 설명할 예정이다.

일단 아래와 같이 클래스가 있다고 가정하자.

class ChildOfChild extends Child {
    void setChildExtends(List<? extends ChildOfChild> c) {
    }

    void setChildSuper(List<? super ChildOfChild> c){
    }
}

class Child extends Parent {

    void set(List<Child> e) {
    }

    void setExtends(List<? extends Child> e) {
    }

    void setSuper(List<? super Child> s) {
    }
}

class Parent {

}

부모와 자식들간의 관계이다. 최상의 클래스는 Parent이다 (물론 Object는 제외다.)
그리고 그 밑에 Child 가 있고 Child 밑에는 ChildOfChild 이라는 클래스가 있다.
평범한 상속의 구조이다.
Child 클래스의 setExtends 를 보면 List<? extends Child> 라는 것이 눈에 띈다.
또한 그 밑에는 List<? super Child> 도 보인다.
쉽게 말해서 extends 는 자기 자신의 객체와 상속을 통한 자기 하위 객체들만 인식할 수 있다.
super는 그 반대다. 자기 자신과 상속을 통한 상위 객체들만 인식한다.
super는 상위 클래스를 가르키는거는 다 알기 때문에 그것만 기억해서 super 상위 라고 기억하자!
예를 보자

List<Child> children = new ArrayList<>();
List<Parent> parents = new ArrayList<>();
List<ChildOfChild> childOfChildren = new ArrayList<>();


ChildOfChild childOfChild = new ChildOfChild();
Child child = new Child();

이렇게 객체들을 만들었다. List<Child>, List<Parent>, List<ChildOfChild> 들은 파라미터로 넘기기위해 만들어 놨다.

child.setExtends(children); //동일한 객첸 당연히 된다.
child.setExtends(childOfChildren); //하향은 된다.
child.setExtends(parents); //상향은 안된다. 컴파일 에러

다음과 같이 테스트를 해보자
아까 설명 했듯이 extends는 자기자신과 하위 클래스만 가능하다. 그러므로 parent 는 상위 클래스 이므로 컴파일 에러가 발생한다.

child.setSuper(children);// 동일한건 당연히 된다.
child.setSuper(childOfChild); //하향은 안된다. //컴파일 에러
child.setSuper(parents); //상향은 된다.

우리는 다음과 같이 테스트를 했다.
super는 자기 자신 혹은 상위 클래스만 가능하다. 그러므로 하향인 childOfChild 객체는 컴파일 에러가 발생한다.

child.set(children); //동일한건 당연히 된다.
child.set(parents);  //상향은 안된다. 컴파일 에러 
child.set(childOfChild); //하향도 안된다. 컴파일 에러

이번엔 하향 상향 없이 그냥 List를 받는 메소드를 호출 해봤다.
그러면 자기 자신 말고는 상위 클래스 하위클래스 모두 되지 않는다.

이번엔 childOfChild 기준으로 다시한번 살펴 보겠다.

childOfChild.setChildExtends(childOfChildren); //동일한건 당연히 된다.
childOfChild.setChildExtends(children); //상향은안된다. 컴파일 에러
childOfChild.setChildExtends(parents); //이것또한 상향이다. 컴파일 에러

setChildExtends 메소드는 List<? extends ChildOfChild>로 하향만 가능하다.
그러므로 상위 클래스를 넣으면 모두 컴파일 에러가 난다.

childOfChild.setChildSuper(childOfChildren); //동일한건 당연히 된다.
childOfChild.setChildSuper(children); //상향은된다.
childOfChild.setChildSuper(parents); //상향은된다.

이번에는 setChildSuper메서드는 List<? super ChildOfChild> 상향만 가능하다.
모두다 상위 클래스 이므로 컴파일 에러가 나지않는다.

이렇게 간단하게 자바의 제네릭 제한에 대해 알아봤다.