728x90
1. 타입 매개변수 제한
- 클래스에 명확한 타입을 정해 놓고 작성한다.
- 코드 재사용 X
- 코드 안정성 O
- 다형성 시도
- 코드 재사용성 O: 다형성 처리를 통해 클래스를 하나로 처리할 수 있다.
- 코드 안전성 X: 원하는 타입을 반환하기 위해서는 다운 캐스팅을 해야한다.
- 제네릭 도입과 실패
- 제네릭 타입을 선언하면 자바 컴파일러 입장에서는 T에 어떤 타입이 들어오는지 알 수 없다.
=> T는 어떤 타입이든 받을 수 있는 모든 객체의 최종 부모인 Object 타입으로 가정한다. - 제네릭에서 타입 매개변수를 사용하면 어떤 타입이든 들어올 수 있다.
=> 매개변수 타입을 제한 해야한다.
- 제네릭 타입을 선언하면 자바 컴파일러 입장에서는 T에 어떤 타입이 들어오는지 알 수 없다.
- 타입 매개변수 제한
- public class AnimalHospital<T extends Animal>
- 코드 재사용성 O
- 코드 안전성 O: 타입 매개변수 상한(extends)을 사용
2. 제네릭 메서드
1) 제네릭 타입
- 정의: GenericClass<T>
- 타입 인자 전달: 객체를 생성하는 시점
- new GenericClass<String>
2) 제네릭 메서드
- 정의: <T> T genericMethod(T t)
- 타입 인자 전달: 메서드를 호출하는 시점
- GenericMethod.<Integer>genericMethod(i)
3) 인스턴스 메서드, static 메서드
- 제네릭 메서드는 인스턴스 메서드와 static 메서드에 모두 적용할 수 있다.
class Box<T> { // 제네릭 타입
static <V> V staticMethod2(V t) {} // static 메서드에 제네릭 메서드 도입
<Z> Z instanceMethod2 (Z z) {} // 인스턴스 메서드에 제네릭 메서드 도입
}
참고
- 제네릭 타입은 static 메서드에 타입 매개변수를 사용할 수 없다.
class Box<T> {
T instanceMethod(T t) {}
static T staticMethod1(T t) {} // 제네릭 타입의 T 사용 불가능
}
4) 타입 매개변수 제한
- 제네릭 메서드도 제네릭 타입과 같이 타입 매개변수를 제한할 수 있다.
- Integer, Double, Long과 같은 숫자 타입이 Number의 자식이다.
public static <T extends Number> T numberMethod(T t) {}
5) 제네릭 메서드 타입 추론
- < Integer>와 같이 타입 인자를 계속 전달하는 것은 불편하다.
- GenericMethod.<Integer>genericMethod(i) => GenericMethod.genericMethod(i)
Integer result2 = GenericMethod.genericMethod(i);
제네릭 메서드 VS 제네릭 타입
- 인스턴스 변수 animal에 Dog 클래스를 넣고, 인스턴스 메서드 printGeneric의 인자로 Cat 클래스를 넣었다.
=> 제네릭 변수 T는 어떤 클래스를 나타낼까?
=> 제네릭 타입과 메서드 중 어떤 클래스를 가질까? - T와 가장 가까운 쪽의 클래스를 찾는다.
=> 제네릭 메서드가 우선순위를 가진다. - 모호하게 T로 전부 표현하는게 아니라 제네릭 메서드에서 Z 등 다른 이름으로 변환한다.
public class Generic<T extends Animal> {
public T animal;
public <T> T printGeneric<T t> {
System.out.println(t.getClassName().getName());
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog("멍멍이", 100);
Cat cat = new Cat("멍멍이", 100);
Generic<Dog> test = new Generic();
test.set(dog);
Cat returnCat = test.printGeneric(cat);
}
}
3. 와일드 카드
- 와일드카드는 프로그래밍에서 *, ? 와 같이 하나 이상의 문자들을 상징하는 특수 문자를 뜻한다.
- 와일드카드는 이미 만들어진 제네릭 타입을 활용할 때 사용한다.
=> Box<Dog>, Box<Cat> 처럼 타입 인자가 정해진 제네릭 타입을 전달 받아서 활용할 때 사용한다.
=> Box<Object>도 입력될 수 있다.
// 제네릭 메서드
// 타입 추론에 의해 T는 Dog가 된다.
static <T> void printWildCardV1(Box<T> box) {
System.out.println(box.get());
}
// 제네릭 메서트가 아니다. 일반적인 메서드
// 와일드 카드 ?는 모든 타입을 받는다.
static void printWildCardV1(Box<?> box) {
System.out.println(box.get());
}
1) 상한 와일드카드
- 와일드 카드에도 상한 제한을 둘 수 있다.
- ? extends Animal
static <T extends Animal> void printGeneric(Box<T> box) {
T t = box.get();
System.out.println(t.getName());
}
public void printWildCard(Box<? extends Animal> box) {
Animal animal = box.get();
System.out.println(animal.getName());
}
2) 하한 와일드카드
- 와일드 카드에는 하한 제한을 둘 수 있다.
(제네릭은 불가능하다) - ? super Animal
- 인자가 최소한 Animal 보다는 상위 클래스여야 한다.
- Dog, Cat 은 불가능하고 Animla, Object는 가능하다.
static void printWildCard(Box<? super Animal> box) {
}
3) 타입 매개변수가 꼭 필요한 경우
4. 타입 이레이저
정리
- 실무에서는 제니릭을 사용해서 설계하는 일은 드물다.
- 이미 제네릭을 통해 만들어진 프레임워크나 라이브러리들을 가져다 사용하는 경우가 많다.
- 공부한 내용보다 더 어려운 개념들도 있다.
=> 공변(covariant), 반공변(contravariant) 등 - 실무에서 경험을 쌓고 필요하다고 느껴질 때 공부를 해보자..!!
- 제네릭은 컬렉션 프레임워크에서 많이 사용된다.
'온라인 강의 > 김영한의 실전 자바 - 중급 2편' 카테고리의 다른 글
[섹션2] 컬렉션 프레임워크 - ArrayList (0) | 2024.08.04 |
---|---|
[섹션1] 제네릭 1편 (0) | 2024.08.03 |