: 데이터 형식에 의존없이 여러 다른 데이터 타입을 가질 수 있는 기술로 재사용성을 높일 수 있다.
- 하나의 클래스만 작성해도 여러 타입의 필드 값을 가진 클래스로 변형해서 다룰 수 있는 구현의 편리함이 있다.
- 컴파일 시 미리 타입 검사를 하여 객체의 타입 안정성을 높이고, 반환 값에 대한 타입 변환 및 타입 검사에 들어가는 코드도 생략할 수 있다.
public class GenericTest<T> {
private T value;
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
public class Application {
public static void main(String[] args) {
/* 타입을 Integer로 하여 인스턴스 생성 */
GenericTest<Integer> gt1 = new GenericTest<>();
gt1.setValue(10);
// gt1.setValue("Hello World!");
Integer num = gt1.getValue();
/* 타입을 String으로 하여 인스턴스 생성 */
GenericTest<String> gt2 = new GenericTest<>();
gt2.setValue("Hello");
// gt2.setValue(10);
String str = gt2.getValue();
/* 제네릭 없이 인스턴스 생성 */
GenericTest gt3 = new GenericTest();
gt3.setValue("Hello");
gt3.setValue(10);
Integer num2 = (Integer) gt3.getValue();
}
}
와일드 카드
: 제네릭 클래스의 인스턴스를 유연하게 활용하기 위한 문법으로, 메소드의 매개변수로 받을 시 타입을 원하는 만큼으로 제한하여 불특정한 제네릭 클래스 타입을 조금 더 활용할 수 있다.
- <?>: 모든 타입을 허용하는 와일드 카드
- <? extends T>: T 타입 또는 T의 하위 타입을 허용하는 와일드 카드
- <? super T>: T 타입 또는 T의 상위 타입을 허용하는 와일드 카드
public interface Animal {
}
/* 포유류도 동물이므로 Animal 인터페이스 구현 */
public class Mammal implements Animal {
}
/* 토끼는 포유류이다. */
public class Rabbit extends Mammal {
public void cry() {
System.out.println("토끼가 울음 소리를 냅니다 끼끾");
}
}
/* 바니도 토끼이다. */
public class Bunny extends Rabbit {
@Override
public void cry() {
System.out.println("바니바니 바니바니 당근 당근");
}
}
/* 드렁큰 바니도 바니이다. */
public class DrunkenBunny extends Bunny {
@Override
public void cry() {
System.out.println("봐니봐니 봐니봐니 당근 당근@!#$@%");
}
}
/* 파충류도 동물이므로 Animal 을 구현 */
public class Reptile implements Animal {
}
/* 뱀은 파충류이다. */
public class Snake extends Reptile {
}
public class RabbitFarm <T extends Rabbit> {
private T rabbit;
public RabbitFarm() {}
public RabbitFarm(T rabbit) {
this.rabbit = rabbit;
}
public T getRabbit() {
return rabbit;
}
public void setRabbit(T rabbit) {
this.rabbit = rabbit;
}
}
public class Application1 {
public static void main(String[] args) {
/* extends 키워드를 이용하여 특정 타입만 사용하도록 제네릭 범위를 제한할 수 있다. */
/* Rabbit의 상위 타입이거나 관련 없는 타입으로 인스턴스 생성하는 것은 불가능*/
// RabbitFarm<Animal> farm1 = new RabbitFarm<>();
// RabbitFarm<Mammal> farm2 = new RabbitFarm<>();
// RabbitFarm<Snake> farm3 = new RabbitFarm<>();
/* Rabbit 타입이거나 Rabbit의 후손 타입으로 인스턴스 생성이 가능하다. */
RabbitFarm<Rabbit> farm1 = new RabbitFarm<>();
RabbitFarm<Bunny> farm2 = new RabbitFarm<>();
RabbitFarm<DrunkenBunny> farm3 = new RabbitFarm<>();
farm1.setRabbit(new Rabbit());
farm1.getRabbit().cry();
farm2.setRabbit(new Bunny());
farm2.getRabbit().cry();
farm3.setRabbit(new DrunkenBunny());
farm3.getRabbit().cry();
}
}
public class MethodFarm {
/* 메소드 매개변수로 전달 받는 타입 제한 */
public <T> void animalType(T t1, T t2) {}
public <T extends Mammal> void mammalType(T t) {}
public <T extends Reptile> void reptileType(T t) {}
}
public class Application2 {
public static void main(String[] args) {
/* 메소드 매개변수 제네릭 제약을 사용할 수 있다. */
MethodFarm methodFarm = new MethodFarm();
/* 별도의 제약 없음 */
methodFarm.animalType(new Bunny(), new Snake());
/* extends Mammal */
// methodFarm.mammalType(new Snake());
methodFarm.mammalType(new Bunny());
/* extends Reptile */
methodFarm.reptileType(new Snake());
// methodFarm.reptileType(new Bunny());
}
}
public class WildCardFarm {
public void anyType(RabbitFarm<?> farm) {
farm.getRabbit().cry();
}
public void extendType(RabbitFarm<? extends Bunny> farm) {
farm.getRabbit().cry();
}
public void superType(RabbitFarm<? super Bunny> farm) {
farm.getRabbit().cry();
}
}
public class Application3 {
public static void main(String[] args) {
WildCardFarm wf = new WildCardFarm();
/* 1. 매개변수 타입 제한이 없는 경우 => 어떤 토끼를 가진 토끼 농장이던 인자로 전달 가능 */
wf.anyType(new RabbitFarm<>(new Rabbit()));
wf.anyType(new RabbitFarm<>(new Bunny()));
wf.anyType(new RabbitFarm<>(new DrunkenBunny()));
/* 2. 매개변수 타입이 바니이거나 바니 후손 토끼를 가진 토끼 농장만 인자로 전달 가능 */
// wf.extendType(new RabbitFarm<>(new Rabbit()));
wf.extendType(new RabbitFarm<>(new Bunny()));
wf.extendType(new RabbitFarm<>(new DrunkenBunny()));
/* 3. 매개변수 타입이 바니이거나 바니 상위 타입 토끼를 가진 토끼 농장만 인자로 전달 가능 */
wf.superType(new RabbitFarm<>(new Rabbit()));
wf.superType(new RabbitFarm<>(new Bunny()));
// wf.superType(new RabbitFarm<DrunkenBunny>(new DrunkenBunny()));
/* RabbitFarm<DrunkenBunny> drunkenBunnyRabbitFarm = new RabbitFarm<>(new DrunkenBunny());
wf.superType(drunkenBunnyRabbitFarm);
RabbitFarm<Bunny> bunnyRabbitFarm = new RabbitFarm<>(new DrunkenBunny());
wf.superType(bunnyRabbitFarm);*/
}
}
'Java' 카테고리의 다른 글
[Java] 13. Collection (1) List - ArrayList (0) | 2024.08.22 |
---|---|
[Java] 13. Collection (0) | 2024.08.22 |
[Java] 11. 입출력 (0) | 2024.08.21 |
[Java] 10. 예외처리 (1) (0) | 2024.08.21 |
[Java] 배열의 값을 출력하기(반복문, Arrays.toString()) (0) | 2024.08.11 |