제네릭 이전의 코드
class Apple {
public String toString() { return "I am an apple."; }
}
class Orange {
public String toString() { return "I am an orange."; }
}
// 다음 상자는 사과도 오렌지도 담을 수 있다.
class Box { // 무엇이든 저장하고 꺼낼 수 있는 상자
private Object ob;
public void set(Object o) { ob = o; }
public Object get() { return ob; }
}
제네릭 이전의 코드의 사용의 예
public static void main(String[] args) {
Box aBox = new Box(); // 상자 생성
Box oBox = new Box(); // 상자 생성
aBox.set(new Apple()); // 상자에 사과를 담는다.
oBox.set(new Orange()); // 상자에 오렌지를 담는다.
Apple ap = (Apple) aBox.get(); // 상자에서 사과를 꺼낸다.
Orange og = (Orange) oBox.get(); // 상자에서 오렌지를 꺼낸다.
System.out.println(ap);
System.out.println(og);
}
어쩔 수 없이 형 변환의 과정이 수반된다.
그리고 이는 컴파일러의 오류 발견 가능성을 낮추는 결과로 이어진다.
형 변환도 귀찮음....
제네릭 이전 코드가 갖는 문제점 1
프로그래머의 실수가 컴파일 과정에서 발견되지 않는다.
에러는 왠만하면 컴파일 과정에서 발견되는게 고치기 쉬움.
그 다음 실행 결과에서 예외에서 발견하면 그나마 괜찮음.
둘 다 안뜨는 경우 최악!!
public static void main(String[] args) {
Box aBox = new Box();
Box oBox = new Box();
// 아래 두 문장에서는 사과와 오렌지가 아닌 '문자열'을 담았다.
aBox.set("Apple");
oBox.set("Orange");
// 상자에 과일이 담기지 않았는데 과일을 꺼내려 한다.
Apple ap = (Apple) aBox.get();
Orange og = (Orange) oBox.get();
System.out.println(ap);
System.out.println(og);
}
제네릭 이전 코드가 갖는 문제점 2
프로그래머의 실수가 실행 과정에서 조차 발견되지 않을 수 있다. 정말 큰 문제!!!
public static void main(String[] args) {
Box aBox = new Box();
Box oBox = new Box();
// 다음 두 문장은 프로그래머의 실수이다!
aBox.set("Apple");
oBox.set("Orange");
System.out.println(aBox.get());
System.out.println(oBox.get());
}
제네릭 기반의 클래스 정의하기
인스턴스 생성시 결정이 되는 자료형의 정보를 T로 대체한다.
class Box {
private Object ob;
public void set(Object o) {
ob = o;
}
public Object get() {
return ob;
}
}
-> 변경
class Box<T> {
private T ob;
public void set(T o) {
ob = o;
}
public T get() {
return ob;
}
}
제네릭 클래스 기반 인스턴스 생성
class Box<T> {
private T ob;
public void set(T o) {
ob = o;
}
public T get() {
return ob;
}
}
- 타입 매개변수 (Type Parameter) Box<T>에서 T
- 타입 인자 (Type Argument) Box<Apple>에서 Apple
- 매개변수화 타입(Parameterized Type) Box<Apple>
Box<Apple> aBox = new Box<Apple>();
-> T를 Apple로 결정하여 인스턴스 생성
-> 따라서 Apple 또는 Apple을 상속하는 하위 클래스의 인스턴스 저장 가능
Box<Orange> oBox = new Box<Orange>();
-> T를 Orange로 결정하여 인스턴스 생성
-> 따라서 Orange 또는 Orange를 상속하는 하위 클래스의 인스턴스 저장 가능
제네릭 이후의 코드 : 개선된 결과
class Box<T> {
private T ob;
public void set(T o) {
ob = o;
}
public T get() {
return ob;
}
}
public static void main(String[] args) {
Box<Apple> aBox = new Box<Apple>(); // T를 Apple로 결정
Box<Orange> oBox = new Box<Orange>(); // T를 Orange로 결정
aBox.set(new Apple()); // 사과를 상자에 담는다.
oBox.set(new Orange()); // 오렌지를 상자에 담는다.
Apple ap = aBox.get(); // 사과를 꺼내는데 형 변환 하지 않는다.
Orange og = oBox.get(); // 오렌지를 꺼내는데 형 변환 하지 않는다.
System.out.println(ap);
System.out.println(og);
}
실수가 컴파일 오류로 이어진다.
public static void main(String[] args) {
Box<Apple> aBox = new Box<Apple>();
Box<Orange> oBox = new Box<Orange>();
aBox.set("Apple"); // 프로그래머의 실수
oBox.set("Orange"); // 프로그래머의 실수
Apple ap = aBox.get();
Orange og = oBox.get();
System.out.println(ap);
System.out.println(og);
}
'# 02 > Java' 카테고리의 다른 글
[윤성우 열혈자바] 22-1. 제네릭의 심화 문법 (0) | 2019.10.23 |
---|---|
[윤성우 열혈자바] 21-2. 제네릭의 기본 문법 (0) | 2019.10.23 |
[윤성우 열혈자바] 20-4. Arrays 클래스 (0) | 2019.10.23 |
[윤성우 열혈자바] 20-3. Math 클래스와 난수의 생성, 그리고 문자열 토큰의 구분 (0) | 2019.10.23 |
[윤성우 열혈자바] 20-2. BigInteger 클래스와 BigDecimal 클래스 (0) | 2019.10.23 |