문제4.
Util.getValue( ) 메소드는 첫 번째 매개값으로 pair타입과 하위 타입만 받고, 두 번째 매개값으로 키 값을 받는다.
리턴값은 키값이 일치할 경우 Pair에 저장된 값을 리턴하고, 일치하지 않으면 null을 리턴하도록 getValue()제네릭 메소드를 정의하라
실행클래스 (UtilExample)
public class UtilExample {
public static void main(String[] args) {
Pair<String,Integer> pair = new Pair<>("홍길동",35);
Integer age = Util.getValue(pair, "홍길동");
System.out.println(age);
ChildPair<String,Integer> childpair = new ChildPair<>("홍삼원",20);
Integer childage = Util.getValue(childpair, "홍삼순");
System.out.println(childage);
/* OtherPair는 예외가 발생해야 한다.
OtherPair<String, Integer> otherPair = new OtherPair<>("홍삼원",20);
int otherAge = Util.getValue(otherPair, "홍삼원");
System.out.println(otherAge);
*/
}
}
제네릭 타입 클래스 (Pair)
public class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
}
Pair를 상속하는 클래스(ChildPair)
public class ChildPair<K,V> extends Pair<K,V> {
public ChildPair(K key, V value) {
super(key, value);
}
}
제네릭 타입 클래스(OtherPair)
public class OtherPair<K,V> {
private K Key;
private V value;
public OtherPair(K key, V value) {
this.Key = key;
this.value = value;
}
public K getKey() {
return Key;
}
public V getValue() {
return value;
}
}
실행결과
35
null
정답은 2개가 될 수 있다.
정답1)
public class Util {
public static <K,V> V getValue(Pair<K,V> pair, K key) {
if(pair.getKey().equals(key))
{
return pair.getValue();
}
else
{
return null;
}
}
}
정답 1 풀이)
getValue함수의 조건은 다음과 같다.
첫번째 매개값: Pair타입과 하위타입 , 두번째 매개값: 키값
키값이 일치할 경우 Pair에 저장된 값 리턴 , 일치하지 않으면 null리턴
1. 실행클래스에서 Util의 객체를 만들지 않고 곧바로 메소드를 사용했으므로 메소드는 static메소드 이어야 한다.
2. 첫번째 매개값에는 Pair타입과 하위타입이 온다. --> 자동타입변환 발생 , 두번째 매개값에는 키값이 온다.
public static 타입파라미터 리턴타입 getValue(Pair<K,V> pair, K key) {
}
3. 이때 매개변수에 Pair이라는 클래스가 사용되었고, Pair는 제네릭타입의 클래스이다.
컴파일러는 K와 V에 대해 알길이 없으므로 우리는 타입파라미터에 K와 V를 명시해주어야 한다.
public static <K,V> 리턴타입 getValue(Pair<K,V> pair, K key) {
}
4. 키값이 일치할 경우 Pair에 저장된 값 리턴 --> value값 리턴 , 일치하지 않으면 null리턴
public static <K,V> V getValue(Pair<K,V> pair, K key) {
if(pair.getKey == key)
{
return pair.getValue();
}
else
{
return null;
}
}
이문제를 풀면서 나는 첫번째 매개변수에서 고민을 많이 했다.
첫번째 매개값에는 Pair타입과 그 하위타입이 올 수 있다고 하는데,
온전히 Pair<K,V>를 써주면 Pair클래스가 ChildPair의 부모 클래스이기 때문에
ChildPair의 객체가 온다고 해도 자동으로 부모타입으로 타입변환이 이루어진다는 것을 생각을 못한 것이다.
상속에 대한 개념이 부족했던 것이다!!!
다시 자동 타입 변환의 개념에 대해 살펴 보았다.
자동 타입 변환
" 자식객체는 부모타입으로 자동 타입 변환 가능"
- 예를 들어, 부모 : Animal 자식: Cat 이라고 한다면
Cat cat = new Cat();
Animal animal = cat; 이 성립한다.
이때, 변수 cat과 animal은 타입만 다를 뿐 동일한 Cat객체를 참조한다. (cat==animal : true)
부모 타입으로 자동 타입 변환된 이후에는 부모클래스에서 선언된 필드와 메소드만 접근이 가능하다.
그러나! 메소드가 자식 클래스에서 오버라이딩(재정의)되었다면 자식 클래스의 메소드가 대신 호출 된다. --> 다형성
강제 타입 변환
"자동 타입 변환된 객체가 다시 자식타입으로 변환하는 것"
- 자식 타입으로 변환하면 자식 타입의 필드와 메소드를 사용할 수 있다.
정답2)
public class Util {
public static <T extends Pair<K,V>,K,V> V getValue(T t, K key) {
if(t.getKey().equals(key)) {
return t.getValue();
}
else
{
return null;
}
}
정답 2 풀이)
정답2는 정답1과 관점이 조금 다르다.
"첫번째 매개값에는 Pair타입과 그 하위타입이 올 수 있다" 에 초점을 맞춘 것이다.
타입파라미터에 타입을 정의할 때 Pair타입과 그 하위타입만 올 수 있는 새로운 타입을 정의한 것이다.
따라서 타입파라미터에는 T, K, V 세개의 파라미터가 정의되어 있는 것이다.
T extends Pair<K,V> 는 T자리에 Pair<K,V> 또는 Pair<K,V>의 하위클래스가 올 수 있다는 뜻이다. (*제한된 타입 파라미터 참고)
또한 여기서의 extends는 상속 개념이 아니라! 종류라는 의미!!!
따라서 인터페이스(box<T>)의 구현객체만 올 수 있도록 타입정의를 하고 싶다면 T extends box<T> 라고 쓸 수 있겠다.
본 포스팅은 이것은 자바다 책을 참고하여 작성하였습니다.
'Java 공부' 카테고리의 다른 글
15장 컬렉션 프레임워크 (0) | 2019.06.05 |
---|---|
14장 람다식 (0) | 2019.05.31 |
13장 제네릭(Generic)(7)_정리 (0) | 2019.05.26 |
13장 제네릭(Generic)(6)_제네릭 타입의 상속과 구현 (0) | 2019.05.25 |
13장 제네릭(Generic)(5)_와일드 카드 타입 (0) | 2019.05.24 |