다수의 데이터를 쉽고 효과적으로 처리할 수 있는 표준화된 방법을 제공하는 클래스의 집합


참고: Vector, Stack, Hashtable, Properties와 같은 클래스들은 컬렉션 프레임워크가 만들어지기 이전부터 존재하던 것이기 때문에 컬렉션 프레임워크의 명명법을 따르지 않는다. 기존의 컬렉션 클래스들은 호환을 위해 설계를 변경해 남겨두었지만 가능하면 사용하지 않는 것이 좋다.
데이터 타입(date type)을 일반화한다(generalize)는 것을 의미
-> 즉, 의도하지 않은 타입의 객체가 저장되는 것을 막음으로써 저장된 객체를 꺼내올 때 원래의 타입과 다른 타입으로 잘못 형변환되어 발생하는 오류를 줄임
MyGenerics 클래스
public class MyGenerics {
Object item;
public void setItem(Object item) { this.item = item; }
public Object getItem() { return item; }
}
MyGenerics 클래스을 제네릭 클래스로 변경
public class MyGenerics<T> {
T item;
public void setItem(T item) { this.item = item; }
public T getItem() { return item; }
}
MyGenerics<String> g = new MyGenerics<String>(); // 실제 타입 지정
g.setItem(new Object()); // error
g.setItem("Hello World"); // ok
String item = g.getItem(); // 형변환 필요x
참고: 자바에서 타입 변수 자리에 사용할 실제 타입을 명시할 때 기본 타입을 바로 사용할 수 없다. 따라서 Integer, Charactor와 같이 Wrapper 클래스를 사용해야 한다.
참고: Java SE 7부터 인스턴스 생성 시 타입을 추정할 수 있는 경우에는 타입을 생락할 수 있다.
MyGenerics<String> g = new MyGenerics<>(); // Java SE 7부터 가능
Class MyGenerics<T>{}
import java.util.*;
class LandAnimal {
public void crying() { System.out.println("육지동물"); }
}
class Cat extends LandAnimal {
public void crying() { System.out.println("냐옹냐옹"); }
}
class Dog extends LandAnimal {
public void crying() { System.out.println("멍멍"); }
}
class Sparrow {
public void crying() { System.out.println("짹짹"); }
}
class AnimalList<T> {
ArrayList<T> al = new ArrayList<>();
void add(T animal) { al.add(animal); }
T get(int index) { return al.get(index); }
boolean remove(T animal) { return al.remove(animal); }
int size() { return al.size(); }
}
public class MyGenerics {
public static void main(String[] args) {
AnimalList<LandAnimal> landAnimal = new AnimalList<>();
landAnimal.add(new LandAnimal());
landAnimal.add(new Cat());
landAnimal.add(new Dog());
// landAnimal.add(new Sparrow()); // 오류가 발생함.
for (int i = 0; i < landAnimal.size() ; i++) {
landAnimal.get(i).crying();
}
}
}
// 실행결과
// 육지동물
// 냐옹냐옹
// 멍멍
타입 문자로 사용할 타입을 명시하면 한 종류의 타입만 저장할 수 있도록 제한할 수 있지만, 여전히 모든 종류의 타입을 지정할 수 있다는 것에는 변함이 없다
이처럼 타입 변수 T에 지정할 수 있는 타입의 종류를 제한할 수 있는 방법이 있다
class AnimalList<T extends LandAnimal> { ... }
extends 키워드를 사용하면 타입 변수에 특정 타입만을 사용하도록 제한할 수 있음 implements 키워드가 아닌extends 키워드 사용 class AnimalList<T extends LandAnimal & MyInterface> { ... }
&기호 사용 -> 이러한 동작을 통해 제네릭을 사용하지 않는 코드와의 호환성을 유지
public class MyGenerics<T> {
static T item; // error
public void setItem(T item) { this.item = item; }
public T getItem() { return item; }
}
public class MyGenerics<T> {
T[] items; // ok
T[] tmpArr = new T[items.length]; // error
}
public static <T> void sort( ... ) { ... }
class AnimalList<T> {
...
public static <T> void sort(List<T> list, Comparator<? super T> comp) {
...
}
...
}