13.1 제네릭 프로그래밍
: 다양한 종류의 데이터를 처리할 수 있는 클래스와 메소드를 작성하는 기법.
*Object 타입의 변수를 사용하는 것보다 안전하고 사용하기 쉽다.
ex) ArrayList 클래스
ArrayList는 어떤 종류의 객체도 저장할 수 있는 배열이다.
제네릭 : 클래스를 정의할 때, 클래스 안에서 사용되는 자료형(타입)을 구체적으로 명시하지 않고 기호로 적어놓는 것.
< 이전의 방법 >
-객체를 Object 타입으로 받아서 처리하는 방법

-> Box 클래스는 여러가지 다양한 타입의 데이터를 저장할 수 있다.

데이터를 Object 참조 변수로 받아서 저장하기 때문에,
모든 객체는 궁극적으로 Object의 자손이다.
따라서 다형성에 의하여 Object 참조 변수는 어떤 객체든지 참조할 수 있는 것이다.
1) 데이터를 꺼낼 때마다 (2), (4)와 같이 항상 형변환을 하여야 한다.
2) 문자열을 저장하고서도 부주의하게 Integer 객체로 형변환을 할 수 있다.
-> 실행 도중에 오류 발생
=> 위 문제들을 모두 해결할 수 있다.
제네릭 클래스는 타입을 변수로 표시한다.
(=타입 매개 변수)
-> 타입 매개 변수는 객체 생성 시에 프로그래머에 의해 결정된다.
"public class Box" -> "public class Box"
class Box<T> {
private T data;
public void set(T data) { this.data = data; };
public T get() { return data; };
}
타입 매개 변수의 값은 객체를 생성할 때 구체적으로 결정된다.
ex)
Box<String> b = new Box<String>();
b.set("Hello World!"); // 문자열 저장
String s = b.get();
다이아몬드
-제네릭 클래스의 생성자를 호출할 때, 타입 인수를 구체적으로 주지 않아도 된다.
(컴파일러는 문맥에서 타입을 추측한다.)
<> < == 다이아몬드
Box<String> Box = new Box<>();
-일반 클래스의 메소드에서도 타입 매개 변수를 사용하여 제네릭 메소드를 정의할 수 있다.
**이 경우엔 타입 매개 변수의 범위가 메소드 내부로 제한된다.
public class MyArrayAlg {
public static <T> T getLast(T[] a) {
return a[a.length -1];
}
}
=> 타입 매개 변수는 반드시 메소드의 수식자와 반환형 사이에 위치되어야 한다.
*제네릭 메소드를 호출하기 위해서는
실제 타입을 꺾쇠 안에 적어주어도 되지만, 그냥 일반 메소드처럼 호출하여도 된다.

주의사항


1. Object는 모든 객체를 담을 수 있지만,
다시 꺼낼 때는 "형변환"이 필요함.
2.
Box<Rectangle> box = new Box<>();
box.set(new Rectangle(10, 20, 30, 40));
class Box<T> {
private T item;
public void set(T item) { this.item = item; }
public T get() { return item; }
}
class Point<T> {
private T x;
private T y;
public Point(T x, T y) {
this.x = x;
this.y = y;
}
public T getX() { return x; }
public T getY() { return y; }
}
public <T> void sub(T d) {
System.out.println("값: " + d);
}