2018-6-2 Basic Generic
제네릭의 기본문법
- 다중 매개변수 기반 제네릭 클래스의 정의
package yoon;
class DBox<L, R> {
private L left; // 왼쪽 수납공간
private R right;
public void set(L o, R r) {
left = o;
right = r;
}
gi
@Override
public String toString() {
return left + " & " + right;
}
}
public class MultiTypeParam {
public static void main(String [] args) {
DBox<String, Integer> box = new DBox<String, Integer>();
box.set("Apple", 25);
System.out.println(box);
}
}
//result
Apple & 25
타입매개변수의 규칙
- 한 문자로 이름을 짓는다.
- 대문자로 이름을 짓는다.
- 기본자료형의 이름은 타입인자로 쓸 수 없다.
- E : Element
- K : Key
- N : Number
- T : Type
- V : Value
- 위와 같이 사용을 하는게 자바의 컨벤션이다.
Box<int> box = new Box<int>();
// 타입 인자로 기본 자료형이 올 수 없으므로 컴파일 오류가 발생
package yoon;
public class PrimitivesAndGeneric {
public static void main(String [] args) {
Box2<Integer> iBox = new Box2<Integer>();
iBox.set(125); // 오토박싱 진행
int num = iBox.get();
System.out.println(num);
}
}
//result
125
타입인자의생략: 다이아몬드기호
- Box
aBox = new Box (); - Box
aBox = new Box<>(); - 위의 두 문장은 같은 의미이다. 참조 변수의 선언을 통해서 <> 안에 Apple이 생략이 되었다고 컴파일러가 판단을 한다.
package yoon;
public class BoxInBox {
public static void main(String [] args) {
Box2<String> sBox = new Box2<>();
sBox.set("I am so happy.");
Box2<Box2<String>> wBox = new Box2();
wBox.set(sBox);
Box2<Box2<Box2<String>>> zBox = new Box2();
zBox.set(wBox);
System.out.println(zBox.get().get().get());
}
}
//result
I am so happy.
- 위 코드를 통해 Box
과 같은 '매개변수화 타입'이 '타입인자'로 사용될 수 있다는것을 알 수 있다.
타입인자의 제한
- class Box
{... } : 인스턴스 생성 시 타입인자로 Number 또는 이를 상속하는 클래스만 올 수 있다.
package yoon;
class Box<T extends Number> {
private T ob;
public void set(T o) {
ob = o;
}
public T get() {
return ob;
}
}
public class BoundedBox {
public static void main(String [] args) {
Box2<Integer> iBox = new Box2<>(); // Integer는 Number를 상속
iBox.set(24);
Box2<Double> dBox = new Box2<>(); // Double은 Number를 상속
dBox.set(5.97);
System.out.println(iBox.get());
System.out.println(dBox.get());
}
}
//result
24
5.97
제네릭 클래스의 타입인자를 인터페이스로 제한하기
package yoon;
interface Eatable {
public String eat();
}
class Apple2 implements Eatable {
@Override
public String toString() {
return "I am an apple.";
}
@Override
public String eat() {
return "It's tastes so good";
}
}
class Box3<T extends Eatable> {
T ob;
public void set(T o) {
ob = o;
}
public T get() {
System.out.println(ob.eat()); // Eatable로 제한해서 eat호출 가능
return ob;
}
}
public class BoundedInterfaceBox {
public static void main(String [] args) {
Box3<Apple2> box = new Box3<>();
box.set(new Apple2()); // 사과 저장
Apple2 ap = box.get(); // 사과 꺼내기
System.out.println(ap);
}
}
//result
It's tastes so good
I am an apple.
- class Box<T extends Number & Eatable> { … } : Number를 상속하면서 동시에 Eatable인터페이스를 구현하는 클래스만이 타입인자로 올 수 있게 동시에 제한을 할 수 있다.
제네릭 메소드의 정의
- public static
Box makeBox(T o) { ... } - 메소드의 이름은 makeBox이고 반환형은 Box
이다. - static과 Box
사이의 는 T가 타입 매개변수임을 알려준다.
package yoon;
class BoxFactory {
public static <T> Box2<T> makeBox(T o) {
Box2<T> box = new Box2<>();
box.set(o);
return box;
}
}
public class GenericMethodBoxMaker {
public static void main(String [] args) {
Box2<String> sBox = BoxFactory.makeBox("Sweet");
System.out.println(sBox.get());
Box2<Double> dBox = BoxFactory.makeBox(7.59);
System.out.println(dBox.get());
}
}
//result
Sweet
7.59
Written on June 2, 2018