지네릭스, 제네릭스 (Generics)
이번 글에서는 지네릭스에 대해 알아보겠습니다. 사실 이전에 컬렉션 프레임워크에서 지네릭스를 한 번 언급했던 적이 있습니다. 추후에 설명하겠다고 하고 넘어왔었는데요. 바로 이번 글에서 설명드립니다.
제네릭이라고도 불리는 지네릭스는 jdk 1.5부터 도입되었습니다. 타입을 미리 지정하지 않고 컴파일할 때 체크할 수 있도록 하는 기능입니다. 미리 타입을 지정해 두면 타입을 형변환하거나 체크해야 하는 번거로움이 있습니다. 지네릭스를 사용하면 이와 같은 부담에서 벗어날 수 있습니다. 지네릭스는 클래스와 메서드에 선언할 수 있습니다. 어떻게 선언하고 사용하는지 살펴봅시다.
1. 지네릭 클래스
지네릭스는 대부분 Type의 첫 글자 T를 사용해 표시하지만 다른 기호를 사용해도 상관없습니다.
일반 클래스 Generic
class Generic {
Object variable;
void setVariable(Object variable) { this.variable = variable; }
Object getVariabe() { return variable; }
}
지금까지 봐왔던 일반적인 클래스입니다. 변수, 메서드 매개변수, 반환값의 타입이 Object로 고정되어 있습니다.
지네릭 클래스로 변경한 클래스 Generic
class Generic<T> {
T variable;
void setVariable(T variable) { this.variable = variable; }
T getVariabe() { return variable; }
}
Object였던 타입이 T로 변경되었습니다.
❗ 지네릭스 제약 조건
타입 변수 T는 인스턴스 변수로 간주됩니다.
따라서 static 멤버에는 사용할 수 없으며 지네릭 타입의 배열 생성도 불가능합니다.
지네릭스 클래스의 객체 생성
T를 대체할 클래스를 지정해 지네릭스 클래스 객체를 생성합니다.
Generic<Example> generic = new Generic<Example>();
class Generic<Example> {
Example variable;
void setVariable(Example variable) { this.variable = variable; }
Example getVariabe() { return variable; }
}
다형성
이전에 공부했던 다형성을 기억하시나요? 하위 클래스의 인스턴스가 상위 클래스의 참조변수로 선언될 수 있었던 특징이 있었습니다.
class Vehicle {
...
}
class Car extends Vehicle {
...
}
class Truck extends Car{
...
}
// Vehicle > Car > Truck
Vehicle vehicle = new Vehicle(); // 가능
Car car = new Car(); // 가능
Truck truck = new Trcuk(); // 가능
Car carTruck = new Trcuk(); // 가능
Vehicle vehicleTruck = new Truck(); // 가능
Truck truckCar = new Car(); // 불가능
지네릭에서는 이러한 다형성에 제한이 있습니다.
Generic<Car> car = new Generic<Car>(); O
Generic<Car> car = new Generic<>(); 으로 생략 가능
Generic<Car> car = new Generic<Truck>(); X
우선, 대입된 타입이 상속관계일지라도 다형성이 성립되지 않습니다. 참조변수와 생성자에 대입된 타입이 일치해야 합니다.
class Generic<T> {
...
}
class Generic2<T> extends Generic<T> {
...
}
Generic<Car> car = new Generic2 <Car>(); O
지네릭 클래스 자체가 상속관계에 있고 대입된 타입이 같은 것은 다형성이 성립됩니다.
대입할 타입의 제한
T extends ~ 를 통해 대입할 클래스를 특정 클래스를 상속받는 클래스 혹은 특정 인터페이스를 구현하는 클래스로 제한할 수 있습니다. 특정 클래스를 상속받으면서 특정 인터페이스를 구현하는 클래스로 제한할 경우 & 기호를 사용합니다.
class Generic <T extends ExmapleClass> {
...
}
class Generic <T extends ExampleInterface> {
...
}
class Generic <T extends ExampleClass & ExampleInterface> {
...
}
와일드카드
타입 변수 T는 static멤버와 일반 클래스에서는 사용이 불가능합니다. 이러한 한계점을 해결하고자 와일드카드를 사용합니다. 타입이 명확하지 않은 T는 컴파일 시 에러를 발생시키지만 '?'로 대체된 와일드카드는 에러가 발생하지 않습니다.
<? extends T> | T와 그 하위 클래스들로 제한 |
<? super T> | T와 그 상위 클래스들로 제한 |
<?> | 모든 타입 |
형변환
지네릭 타입 > 원시 타입 (지네릭이 제거된 클래스 타입) O
원시 타입 > 지네릭 타입 O
대입된 타입이 다른 지네릭 타입 간의 형변환 X
2. 지네릭 메서드
<T>를 반환 타입 앞에 선언합니다. static 메서드에도 지네릭 타입을 선언하고 사용할 수 있습니다.
static <T> void method () {};
지네릭 메서드 호출
메서드명 앞에 대입할 타입을 지정해 호출해야 합니다. 대입된 타입을 컴파일러가 추정할 수 있을 때는 생략이 가능합니다.
.<ExampleClass>method();
자바를 처음 공부할 때 가장 이해하기 어려웠던 부분이 지네릭스였습니다. 이 짧은 포스팅으로는 전부 이해하기 어려운 것이 사실입니다. 그저 공부에 도움이 되셨으면 좋겠다는 마음으로 올립니다. 다음 글은 열거형 클래스에 대해 설명드리겠습니다. 항상 읽어주셔서 감사합니다.
'개발공부 > Java : 자바' 카테고리의 다른 글
자바 쉽게 배우기 20 - 스레드 (0) | 2023.09.15 |
---|---|
자바 쉽게 배우기 19 - 열거형 (Enum) (0) | 2023.02.21 |
자바 쉽게 배우기 17 - Arrays (0) | 2023.02.14 |
자바 쉽게 배우기 16 - 컬렉션 프레임워크(3) : Map, Iterator (0) | 2023.02.10 |
자바 쉽게 배우기 15 - 컬렉션 프레임워크(2) : Set, Queue (0) | 2023.02.08 |