다음과 같이 Box 클래스를 선언하려고 함. 내용물로 content 필드를 선언하려고 할때, 타입을 무엇으로 해야할까?
public Class Box {
public ? content;
}
Box는 다양한 내용물을 저장해야 하므로 특정 클래스 타입으로 선언할 수 없음. 그래서 다음과 같이 Object 타입으로 선언 함.
public class Box {
public Object content;
}
Object 타입은 모든 클래스의 최상위 부모 클래스임. 그렇기 때문에 모든 객체는 부모 타입인 Object로 자동 타입 변환이 되므로 content 필드에는 어떤 객체든 대입이 가능함.
Box box = new Box();
box.content = 모든 객체;
문제는 Box 안의 내용물을 얻을 때임. content는 Object 타입이므로 어떤 객체가 대입되어 있는지 확실하지 않음. 이때 대입된 내용물의 타입을 안다면 강제 타입 변환을 거쳐 얻을 수 있음.
String content = (String) box.content;
어떤 내용물이 저장되어 있는지 모른다면 instanceof 연산자로 타입을 조사할 수는 있지만 모든 종류의 클래스를 대상으로 조사할 수는 없음. 따라서 Object 타입으로 content 필드를 선언하는 것은 좋은 방법은 아님.
Box를 생성하기 전에 우리는 어떤 내용물을 넣을지 이미 알고 있음. 따라서 Box를 생성할 때 저장할 내용물의 타입을 미리 알려주면 Box는 content에 무엇이 대입되고, 읽을 때 어떤 타입으로 제공할지를 알게 됨. 이것이 제네릭임.

다음은 Box 클래스에서 결정되지 않은 content의 타입을 T라는 타입 파라미터로 정의한 것임.
public class Box <T> {
public T content;
}
<T>는 T가 타입 파라미터임을 뜻하는 기호로, 타입이 필요한 자리에 T를 사용할 수 있음을 알려주는 역할을 함. 여기에서 Box 클래스는 T를 content 필드의 타입으로 사용함. 즉, Box 클래스는 T가 무엇인지 모르지만, Box 객체가 생성될 시점에 다른 타입으로 대체된다는 것을 알고 있음.
만약 Box의 내용물로 String을 저장하고 싶다면 다음과 같이 Box를 생성할 때 타입 파라미터 T 대신 String으로 대체하면 됨.
Box<Strring> box = new Box<String>();
box.content = "안녕하세요.";
String content = box.content; //강제 타입 변환 필요 없이 "안녕하세요"를 바로 얻을 수 있음.
Box의 내용물로 100을 저장하고 싶다면 다음과 같이 Box를 생성할 때 타입 파라미터 T 대신 Integer로 대체하면 됨. Integer는 정수값을 표현하는 클래스 타입임.
Box<Integer> box = new Box<Integer>();
box.content = 100;
int content = box.content; //강제 타입 변환 필요 없이 100을 바로 얻을 수 있음.
사실 <T>에서 타입 파라미터로 쓰이는 T는 단지 이름일 뿐이기 떄문에 T 대신 A부터 Z까지 어떤 알파벳을 사용해도 됨. 주의할 점은 타입 ㅍ ㅏ라미터를 대체하는 타입은 클래스 및 인터페이스라는 것임.