1. 제네릭 클래스의 타입 인자 제한하는 방법과 효과는?
: 인스턴스를 생성할 때, 타입인자를 이용해서 상위 또는 이를 상속받는 클래스만 오게 할 수 있다.
class Box <T extends Number> { // Number 혹은 Number에게 상속 받는 클래스들에게만 대상
private T ob;
public int toValue() {
return ob.intValue(); // Number에 있는 메소드를 호출하기 위함!
}
}
또한 하나의 클래스와 하나의 인터페이스로 동시에 제한할 수 있다.
class Box <T extends Number & Eatable> { ... } // Number라는 클래스와 Eatable이라는 인터페이스를 '&'기호로 동시 제한
이러한 방법으로 타입 인자를 제한하는 이유는 제네릭 타입에서 보다 명확한 타입인자를 제공하기 위함이고 다형성(Polymorphism)에 의한 코드 규칙에 위배되지 않기 위한 효과도 있다.
2. 아래와 같이 출력값이 나오도록 프로그래밍 하시오.
class DDBoxDemo { public static void main(String[] args) { DBox<String, Integer> box1 = new DBox<>(); box1.set("Apple", 25); DBox<String, Integer> box2 = new DBox<>(); box2.set("Orange", 33); DDBox<DBox<String, Integer>, DBox<String, Integer>> ddbox = new DDBox<>(); ddbox.set(box1, box2); System.out.println(ddbox); } }
Apple & 25 Orange & 33
2-1. DBox 클래스
public class DBox<T1, T2> {
private T1 t1;
private T2 t2;
public void set(T1 t1, T2 t2) {
this.t1 = t1;
this.t2 = t2;
}
@Override
public String toString() {
return t1 + " & " + t2;
}
}
2-2 DDBox 클래스
public class DDBox<T1, T2> extends DBox<T1, T2> {
private DBox<String, Integer> box1;
private DBox<String, Integer> box2;
public void set(DBox<String, Integer> box1, DBox<String, Integer> box2) {
this.box1 = box1;
this.box2 = box2;
}
@Override
public String toString() {
return box1 + "\n" + box2;
}
}
3. 아래와 같이 출력값이 나오도록 프로그래밍 하시오.
public static void main(String[] args) { Box<Integer> box1 = new Box<>(); box1.set(99); Box<Integer> box2 = new Box<>(); box2.set(55); System.out.println(box1.get() + " & " + box2.get()); swapBox(box1, box2); System.out.println(box1.get() + " & " + box2.get()); }
> 99 & 55 > 55 & 99
3-1. 메인 클래스(swapBox 메소드 추가)
public class CombinationBox {
public static void main(String[] args) {
Box02<Integer> box1 = new Box02<>();
box1.set(99);
Box02<Integer> box2 = new Box02<>();
box2.set(55);
System.out.println(box1.get() + " & " + box2.get());
swapBox(box1, box2);
System.out.println(box1.get() + " & " + box2.get());
}
private static <T extends Number> void swapBox(Box02<T> box1, Box02<T> box2) {
T temp = box1.get();
box1.set(box2.get());
box2.set(temp);
}
}
3-2. Box 클래스
public class Box02<T> {
private T ob;
public void set(T ob) {
this.ob = ob;
}
public T get() {
return ob;
}
}
4. 지네릭 메소드에 대하여 설명하시오.
: 기존의 클래스 단위가 아닌 메소드의 단위로 제네릭 키워드를 붙이는 것을 의미한다.
class BoxFactory {
public static <T> Box<T> makeBox(T o) { // <T>: 제네릭임을 명시, Box<T>: 해당 제네릭을 리턴타입으로 정함
Box<T> box = new Box<T>(); // 상자(box)를 생성 및 제네릭 타입으로 초기화하고
box.set(o); // 전달된 인스턴스를 상자에 담아서
return box; // 제네릭 타입으로 상자를 반환한다.
}
}
제네릭 메소드의 인자는 메소드 호출 시점에 결정된다.
Box<String> sBox = BoxFactory.<String>makeBox("Sweet");
Box<Double> dBox = BoxFactory.<Double>makeBox("7.59"); // Auto Boxing
제네릭 메소드는 타입 인자를 생략할 수 있다.
Box<String> sBox = BoxFactory.makeBox("Sweet");
Box<Double> dBox = BoxFactory.makeBox("7.59"); // Auto Boxing
제네릭 메소드 또한 타입 매개변수를 제한할 수 있다.
public static <T extends Number> Box<T> makeBox(T o) { // 타입인자 Number를 상속하는 클래스로 제한
...
System.out.println("Boxed data: " + o.intValue());
return box;
}
5. 와일드 카드와 상한 제한, 하한 제한에 대하여 설명하시오.
5-1. 와일드 카드 기능이 생겨나게된 배경
: 제네릭 클래스는 상속을 받을 때 자식 클래스 또한 제네릭 클래스가 될 수 있는 특징을 가지고 있다.
그러나, 제네릭 타입 매개변수가 같은 것들 끼리만 상속관계가 되는 불편한 점이 있었다.
이러한 점을 해결하기 위해 제네릭 타입 인자에 ’?’ 키워드를 붙이는 형태의 기법이 나오게 되었다.
public static void peekBox(Box<?> box) { // ? 키워드로 인해 Box<Integer>와 Box<String>의 인스턴스를 인자로 전달할 수 있다.
System.out.println(box);
}
5-2. 와일드 카드의 상한과 하한 제한(Bounded Wildcards)이 생긴 이유
: 5-1.과 같은 와일드 카드의 특성으로 인해 제네릭 타입 매개변수가 같은 것들 끼리만 상속관계가 되지 않아도 되는 이점이 생겼지만 이와 반대로 어떠한 것들끼리 상속관계가 되는지 명확하지 않다는 단점이 생겼다.
따라서 이를 해결하기 위해 상한과 하한을 두어 어떠한 상속관계를 두는지 좀 더 명확화하기 위해 생겼다.
// 와일드 카드의 상한 제한
public static void peekBox(Box<? extends Number> box) { ... }
// 와일드 카드의 하한 제한
public static void peekBox(Box<? super Integer> box) { ... }
// to ~ from 키워드를 이용한 와일드 카드의 상/하한 제한
public static void peekBox(Box<? super Integer> to, Box<? extends Number> from) {...}
6. 아래가 에러가 나는 이유를 설명하시오.
public static void inBox(Box<? super Toy> box, Toy n) { box.set(n); // 넣는 것! OK! Toy myToy = box.get(); // 꺼내는 것! Error! }
: 5-2.와 같이 와일드 카드에서는 상속관계의 모호함 때문에 이에 대한 에러가 생길 수 있음을 언급하였다.
또한 이는 다형성에 의한 코드 규칙이 위배가 될 수 있다는 점이 있어 상한 및 제한을 불명확하게 하면 Toy myToy = box.get();와 같은 ‘자식 = 부모’ 관계 또한 될 수도 있다.
7. 아래와 같이 메소드 오버로딩이 되지 않는 이유는?
// 다음 두 메소드는 오버로딩 인정 안됨. public static void outBox(Box<? extends Toy> box) { ... } public static void outBox(Box<? extends Robot> box) { ... }
: 5-2.와 같이 와일드 카드는 Toy와 Robot을 상속(extends) 받더라도 둘 사이의 관련성이 모호하기 때문에 오버로딩이 인정되지 않는다. 따라서 Toy와 Robot을 T로 간소화하여 좀 더 확실화 할 수 있다.
public static <T> void outBox(Box<? extends T> box) { ... } // Toy와 Robot을 리턴 타입과 같이 T로 간소화
8. 아래의 결과가 나오도록 프로그래밍을 완성하시오.
public static void main(String[] args) { Box<Integer> box1 = new Box<>(); box1.set(24); Box<String> box2 = new Box<>(); box2.set("Poly"); if(compBox(box1, 25)) System.out.println("상자 안에 25 저장"); if(compBox(box2, "Moly")) System.out.println("상자 안에 Moly 저장"); System.out.println(box1.get()); System.out.println(box2.get()); }
> 24 > Poly
8-1. 메인 클래스(compBox 메소드 추가)
public class BoxStore {
public static void main(String[] args) {
Box03<Integer> box1 = new Box03<>();
box1.set(24);
Box03<String> box2 = new Box03<>();
box2.set("Poly");
if(compBox(box1, 25))
System.out.println("상자 안에 25 저장");
if(compBox(box2, "Moly"))
System.out.println("상자 안에 Moly 저장");
System.out.println(box1.get());
System.out.println(box2.get());
}
// 해당 메소드의 두 번째 매개변수는 제네릭 타입으로 지정할 수도 있다.(경우의 수가 많아 오버로딩의 횟수가 많을 경우)
private static boolean compBox(Box03<Integer> box, int var) {
if (box.get() == var) {
return true;
} else {
return false;
}
}
private static boolean compBox(Box03<String> box, String str) {
if (box.get() == str) {
return true;
} else {
return false;
}
}
}
8-2. Box 클래스
public class Box03<T> {
private T ob;
public T get() {
return ob;
}
public void set(T ob) {
this.ob = ob;
}
}
9. 콜렉션 프레임워크란?
9-1. 콜렉션 프레임워크의 정의
: 자료구조 및 알고리즘을 구현해 놓은 라이브러리로 제네릭 기반에 의해 만들어졌다.
9-2. 콜렉션 프레임워크의 분류
- Set< E >
- List< E >: 인스턴스의 저장 순서를 유지하고 동일 인스턴스의 중복 저장을 허용할 수 있다.
- ArrayList< E >: 배열 기반 자료구조로 배열을 이용하여 인스턴스에 저장한다.
- LinkedList< E >: 리스트 기반 자료구조로 리스트를 구성하여 인스턴스에 저장한다.
- Queue< E >
- Map<K, V>
'WebDev > 본과정' 카테고리의 다른 글
Set, Queue, Map 자료구조와 정렬 및 탐색 (0) | 2021.05.14 |
---|---|
List와 Set (0) | 2021.05.13 |
Java의 기본 클래스 및 제네릭 개요 (0) | 2021.05.13 |
Clone과 Wrapper 클래스 (0) | 2021.05.13 |
예외처리와 JVM 및 Object 클래스 (0) | 2021.05.13 |
최근댓글