[Java] 제네릭스

JAVA의 정석

Generics

Generics란?

다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에 컴파일 시의 타입 체크를 해주는 기능.

객체의 타입을 컴파일 시에 체크하기 때문에 타입 안정성을 높이고 형변환의 번거로움이 줄어듬.

Generics 클래스의 선언

class Box{
	Object item;

	void setItem(Object item) {this.item = item;}
	Object getItem() {return item;}
}
class Box<T>{ //제네릭 타입 T를 선언
	T item;

	void setItem(T item) {this.item = item;}
	T getItem() {return item;}
}

이제 제네릭 클래스가 된 Box 클래스의 객체를 생성할 때는 다음과 같이 참조변수와 생성자에 타입 T 대신에 사용될 실제 타입을 지정해주어야 한다.

Box<String> b = new Box<String>();  //타입 T 대신, 실제 타입 String 지정
b.setItem(new Object());            //Error. String으로 설정해 놨으면 String만 가능
b.setItem("ABC");                   //OK
String item = ~~(String)~~ b.getItem(); //형변환 필요 없음

아래와 같이 타입 변수 T에 Object타입을 지정하면, 지정하지 않은 것이 아니라 알고 적은 것이므로 경고는 발생하지 않는다.

Box<Object> b = new Box<Object>();
b.setItem(new Object());            //OK
b.setItem("ABC");                   //OK

하지만 지네릭 클래스를 사용할 때는 반드시 타입을 지정해주자.

용어

Java

제한

  • static멤버에 타입 변수 T를 사용할 수 없음!

  • 제네릭 타입의 배열을 생성하는 것도 안됨!

    • new 연산자는 컴파일 시점에 타입 T가 뭔지 정확히 알아야 함.
    • 꼭 제네릭 배열을 생성해야할 필요가 있을 때는
      • ‘Reflection API’의 newInstance()와 같이 동적으로 객체를 생성하는 메서드 사용
      • Object 배열을 생성해서 복사한 다음 ‘T[]’로 형변환

제네릭 클래스의 객체 생성과 사용

ArrayList를 이용해서 여러 객체를 저장할 수 있도록 한다.

class Box<T>{
	ArrayList<T> list = new ArrayList<T>();

	void add(T item) {list.add(item);}
	T get(int i) {return list.get(i);}
	ArrayList<T> getList() {return list;}
	int size() {return list.size()}
	public String toString() {return list.toString();}
}
  1. 참조변수와 생성자에 대입된 타입(매개변수화된 타입)이 일치해야 한다.
Box<Apple> appleBox = new Box<Apple>(); //OK
Box<Apple> appleBox = new Box<Grape>(); //Error
  1. 상속관계 X
Box<Fruit> appleBox = new Box<Apple>(); // Error

Box<Apple> appleBox = new FruitBox<Apple>(); //제네릭 클래스 타입이 상속관계는 OK

※ JDK 1. 7 부터는 타입 생략 가능 Box appleBox = new Box<>();

  1. 다른 타입 객체 추가 불가. 자손은 가능

제네릭 클래스 제한하기

제네릭 타입에 ‘extends’를 사용하면, 특정 타입의 자손들만 대입할 수 있게 제한할 수 있다.


Tags:

Categories:

Updated:

Leave a comment