728x90

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

->객체타입을 컴파일 시에 체크하여 타입 안정성을 높히며 형변환을 줄일 수 있다.

 

지네릭스 장점

1.타입 안정성을 제공한다.

2.타입체크와 형변환을 생략할 수 있어 코드가 줄어든다.

 

지네릭스 클래스 선언

클래스 옆에 <T>를 붙이면된다.

ex)

class Box<T>{

    T item;

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

    T getItem(){return item;}

}

 

Box<T>에서 T는 타입 변수(type variable)이라 한다. 임의의 참조형 타입을 의미한다. 

Box클래스의 객체를 생성할 때는 참조변수와 생성자에 타입T대신 실제 타입을 지정해주어야한다.

ex)

Box<String> b = new Box<String>();

 

T자리에 String을 넣어줬으므로 Box클래스의 모든 T는 String으로 변환되어 인식된다.

 

지네릭스 용어

class Box<T> {}

Box<T> : 지네릭 클래스. T의 Box 또는 T Box라고 읽는다.

T : 타입변수 또는 타입 매개변수라고 한다.

Box : 원시 타입(raw type)

 

지네릭스 생성

지네릭 클래스를 생성할때는 참조변수와 생성자에 대입된 타입이 일치해야한다.

Box<T>의 경우

ex)

Box<Apple> appleBox = new Box<Apple>();

Box<Apple> appleBox = new Box<Grape>(); // 에러

참조변수의 타입변수와 생성자의 타입변수가 다르면 에러가 발생한다.

 

지네릭스 제한

일반적으로 하나의 종류만 지네릭클래스의 타입변수로 가능하지만 지정타입의 종류에 제한을 걸 수 있다.

extends를 사용하는 방법이다.

지네릭 타입에 extends를 사용할경우 해당 클래스와 자식클래스들까지 가능하다.

Apple클래스와 Grape클래스가 Fruit 클래스의 자손일때

ex)

class FruitBox<T extends Fruit>{

...

}

 

FruitBox<Fruit> fruitBox = new FruitBox<Fruit>();

fruitBox.add(new Apple());

fruitBox.add(new Grape());

위의 예문이 가능하다.

 

인터페이스 또한 제한설정이 가능하다.

Eatable인터페이스가 존재할때

class FruitBox<T extends Fruit & Eatable>{...}의 경우 

FruitBox에는 Fruit의 자손이면서 Eatable을 구현한 클래스만 타입 매개변수 T에 대입될 수 있다.

 

와일드 카드

<? extends T> 와일드 카드의 상한제한 T와 그 자손들만 가능

<? super T> 와일드 카드의 하한제한. T와 그 조상들만 가능

<?> 제한 없음. 모든 타입이 가능. <? extends Object>와 동일하다.

makeJuice 메서드에서 타입변수 와일드카드가 사용되었다. 그렇기 때문에 매개변수로 fruitBox와 appleBox모두 사용이 가능하다.

 

지네릭 메서드

메서드 선언부에 지네릭 타입이 선언된 메서드를 지네릭 메서드라고한다.

메서드에 선언된 제네릭 타입은 지역변수를 선언한 것과 같다. 메서드 내에서만 지역적으로 사용된다.

static Juice makeJuice(FruitBox<? extends Fruit> box){

 ...

}

->

static <T extends Fruit> Juice makeJuice(FruitBox box){ 

...

}

로 지네릭 메서드로 변형가능하다.

지네릭 메서드를 호출할경우 타입변수를 적어주어야한다.

ex)

System.out.println(Juicer.<Fruit>makeJuice(fruitBox));

대부분의 경우 컴파일러가 타입을 추정가능하여 생략해도 되는 경우가 많다.

 

지네릭 타입의 형변환

지네릭 타입과 넌지네릭(non-generic)타입간의 형변환은 항상 가능하다.

그러나 다른 지네릭 타입간 형변환은 불가능하다.

ex)

Box box = null;

Box<Object> objBox = null;

box = (Box)objBox;

objBox = (Box<Object>)box;

 

위의 경우엔 모두 가능하다.

다른 지네릭 타입간의 형변환

ex)

Box<Object> objBox = null;

Box<String> strBox = null;

objBox = (Box<Object>)strBox; //에러

strBox = (Box<String>)objBox; //에러

Box<Object> objBox = new Box<String>(); //에러

위의 경우 에러가 발생한다.

 

다른 지네릭 타입간의 가능한 경우는 와일드 카드인경우이다.

ex)

Box<? extends Object> wBox = new Box<String>();

위의 경우는 가능하다.

 

728x90

'Programming > JAVA' 카테고리의 다른 글

에너테이션(annotation)  (0) 2021.08.11
열거형(Enums)  (0) 2021.08.10
Collection 정리  (0) 2021.08.07
Map  (0) 2021.08.07
HashSet & TreeSet  (0) 2021.08.03

+ Recent posts