관련 이론 및 문법

(제네릭 범위에 따른 구분 참고)

http://kkikkodev.tistory.com/191


문제 의도

보기 중, 주어진 소스코드의 6 라인에 각각 삽입하여 정상적으로 컴파일 되는 것을 3 개 고르는 문제입니다.


답안

B, C, D


풀이 방법

소스 코드를 보면 4 라인에 G1 이라는 클래스가 정의되어 있고, 5 라인에는 takeList 라는 메소드가 있습니다. 이 메소드는 매개변수로 List<? extends String> 형 변수 list 를 받고 있습니다. <? extends String> 의 의미는, 제네릭 자료형으로 String 을 상속하는 모든 클래스가 올 수 있다는 의미입니다.


먼저, 보기 A 인, list.add("foo"); 문을 살펴보면, String 형 상수인 "foo" 를 list 의 add 메소드를 호출하면서 매개변수로 넘기고 있습니다. String 클래스는 final 클래스이므로 사실 상속하면 안됩니다. 하지만, 제네릭 변수를 선언할 때는, 이를 문법 에러로 체크하지 않습니다. 따라서, 5 라인에서 컴파일 에러가 발생하지 않는 것입니다. 그러나, 실제로 list.add("foo"); 문 처럼 Collection 의 메소드를 사용하여, 매개변수로 어떠한 자료형 (이 문제에서는 String 형) 을 넘기게 되면, 컴파일 에러를 발생시킵니다. 즉, 제네릭 변수 선언시에는 final 클래스 에러 체크를 하지 않고, 실제 메소드 호출시 에러 체크를 한다는 이야기 입니다. 따라서, 보기 A 는 답안 후보에서 제외합니다.


보기 B 인, Object o = list; 를 살펴보면, list 의 자료형은 List<? extends String> 이기 때문에, 모든 클래스는 Object 클래스를 상속하므로, 자식 클래스의 인스턴스 변수를 부모 클래스 변수 o (Object 형) 에 대입하므로 이는 정상적으로 컴파일 됩니다. 따라서 보기 B 는 답안 후보가 됩니다.


보기 C 인, String s = list.get(0); 문을 살펴보면, list.get(0) 의 반환형은, String 형입니다. 따라서, String 형을 String 형 변수 s 에 대입하는 것이므로, 문제 없이 정상적으로 컴파일되고, 이 또한 답안 후보가 됩니다.


보기 D 인, list = new ArrayList<String>(); 문을 살펴보면, 제네릭 자료형으로, String 을 설정하고 있는데, 이는, 선언된 <? extends String> 형의 규칙에 부합하기 때문에 (String 을 상속하는 모든 클래스라는 의미에는 String 클래스 자기 자신도 포함됩니다.) 정상 컴파일되고, 답안 후보가 됩니다.


마지막으로 보기 E 인, list = new ArrayList<Object>(); 문을 살펴보면, 제네릭 자료형으로 Object 를 설정하고 있는데, Object 는 String 의 부모 클래스이기 때문에, <? extends String> 형의 규칙에 부합하지 않습니다. 따라서 답안 후보에서 제외합니다.


결과적으로, 답안은 B, C, D 가 됩니다.


by kkikkodev 2015. 8. 14. 18:31