본문 바로가기
개발언어/Java : 자바

자바 쉽게 배우기 18 - 지네릭스

by 개발자D 2023. 2. 20.

지네릭스

지네릭스, 제네릭스 (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) 쉽게 배우기 19 - 열거형 (Enum)

jdk 1.5부터 추가된 열거형은 관련된 여러 상수를 한 데 모아 정의할 때 사용하는 타입입니다. 자바의 열거형 타입을 사용하면 상수의 값 비교 시 타입까지 비교합니다. 또한 열거형의 상수 값을

devdharu.tistory.com