목차
- 제네릭
- 제네릭 클래스 사용
2-1. 타입 변수 선언 <T>
2-2. 타입 결정 및 인스턴스 생성
2-3. 타입 제한 extends - 와일드카드
1. 제네릭
- 제네릭(generic)의 사전적인 의미는 일반적인, 포괄적인, 통칭의 것이다.
- 자바에서 제네릭이란 데이터 타입의 일반화을 말한다.
- 제네릭은 클래스나 메소드에서 사용할 내부 데이터 타입을 특정화하지 않다가, 컴파일 시에 지정한다.
- 제네릭을 활용하면 형변환 및 타입 검사에 들어가는 코드들을 생략할 수 있다. instanceof로 비교하거나 다운캐스팅 작성하는 과정이 불필요해진 것이다.
- 이러한 제네릭은 JDK 1.5버전부터 추가된 문법이다.
✅ 제네릭에 대해 이해할 수 있다.
✅ 제네릭의 목적에 대해 이해할 수 있다.
✅ 제네릭 클래스에 대해 이해할 수 있다.
2. 제네릭 클래스 사용
2-1. 타입 변수 선언 <T>
public class GenericTest <T> {}
- 제네릭 설정은 클래스 선언부 마지막에 다이아몬드 연산자 <>를 이용하여 작성하게 된다.
- 다이아몬드 연산자 <> 내부에 작성하는 영문자는 관례상 대문자로 쓰이고 있다. 여기서 다이아몬드 연산자 내부에 작성한 T를 타입 변수라고 부른다.
- 자료형 대신 쓰인 타입변수명 역시 반드시 T는 아니어도 되지만, 관례적으로 Type을 뜻하는 대문자 T 사용한다.
public class GenericTest <T, R, Y> {}
- 또한 여러 개의 타입 변수를 작성할 때는 ,를 이용하여 여러 개 기술할 수도 있다.
private T value;
public void setValue(T value) {
this.value = value;
}
public T getValue() {
return this.value;
}
- 제네릭 클래스 내 필드, 설정자(setter), 접근자(getter) 작성 시에도 구체적인 타입 대신 타입 변수 T를 이용한다.
❗ T 대신 Object를 써도 성립하는 코드는 맞다.
하지만 그렇게 되면 실행용 Application.class에서 작성해둔 정수, 문자열, 실수 등 모든 인자 값들 또한 Object를 따르게 된다.
일례로 Integer 값에 String을 넣더라도 어차피 Object로 읽혀 의도하지 않은 값으로 반환될 수 있어 일일이 instanceof로 확인 및 다운캐스팅 해야 하는 경우들이 생겨나고 마는 것이다.
2-2. 타입 결정 및 인스턴스 생성
- 작성한 제네릭 클래스를 이용할 시에는 실제 적용할 타입을 <타입 변수 자리>에 맞춰 넣어준다.
- 즉 컴파일 시점에서 타입이 결정되는 것이다.
GenericTest<Double> gtC = new GenericTest<>();
gtC.setValue(0.5);
System.out.println(gtC.getValue());
System.out.println(gtC.getValue() instanceof Double);
======================================
0.5
true
- 타입 선언 시 타입 변수가 작성되면 타입 추론이 가능해진다. 따라서 JDK 1.7버전부터는 생성자 쪽의 타입을 생략하고 사용할 수 있다.
- 단, 자리를 지워서는 안 되고 빈 다이아몬드 연산자로 남겨두어야 한다.
- 그 이전까지는 아래 방식을 고수해왔다.
A. Integer 타입의 인스턴스 생성
GenericTest<Integer> gtA = new GenericTest<Integer>();
gtA.setValue(10); *오토박싱 가능하므로 그냥 정수 작성*
System.out.println(gtA.getValue());
System.out.println(gtA.getValue() instanceof Integer);
======================================
10
true
- 메소드 인자 및 리턴값 모두 Integer 타입으로 선언되었음을 알 수 있다.
B. String 인스턴스 새성
GenericTest<String> gtB = new GenericTest<String>();
gtB.setValue("홍길동");
System.out.println(gtB.getValue());
System.out.println(gtB.getValue() instanceof String);
======================================
홍길동
true
2-3. 타입 제한 extends
public class Mammal implements Animal {}
public class Rabbit extends Mammal {}
public class Bunny extends Rabbit {}
public class DrunkenBunny extends Bunny {}
- 제네릭 클래스에 extends 키워드를 사용해 해당 클래스 포함 그 클래스를 상속 받는 클래스들만 취급하도록 만들 수 있다.
✅ 제네릭 클래스를 적용하여 사용할 수 있다.
3. 와일드카드
<?>
제한 없음
public void anyType(RabbitFarm<?> farm) {
farm.getAnimal().cry();
}
- 토끼 농장에 있는 토끼가 어떤 토끼든 상관 없다.
<? extends 타입명>
상한 제한
- Type과 Type의 후손을 이용해 생성한 객체만 매개변수로 사용 가능하다.
public void extendsType(RabbitFarm<? extends Bunny> farm) {
farm.getAnimal().cry();
}
- 토끼 농장의 토끼는 Bunny이거나 그 후손 타입으로 만들어진 클래스만 매개변수로 사용 가능하다.
<? super 타입명>
하한 제한
- Type과 Type의 부모를 이용해 생성한 객체만 매개변수로 사용 가능하다.
public void superType(RabbitFarm<? super Bunny> farm) {
farm.getAnimal().cry();
}
- 토끼 농장의 토끼는 Bunny이거나 그 부모 타입으로 만들어진 클래스만 매개변수로 사용 가능하다.
✅ 와일드카드에 대해 이해할 수 있다.
✅ 와일드카드를 적용하여 사용할 수 있다.
'Java' 카테고리의 다른 글
[자바의 정석] Ch 6. 객체 지향 프로그래밍 강의 메모 (0) | 2022.01.10 |
---|---|
[자바의 정석] Ch 6. OOP I 연습문제 풀이 (0) | 2022.01.09 |
[JAVA] 10-2. Wrapper | 파싱(parsing) | Date | Calendar (0) | 2022.01.07 |
[JAVA] 10-1. API | Object | String | StringBuilder (0) | 2022.01.06 |
[JAVA/수업 과제 practice] 다형성 Lv. 1~2 (0) | 2022.01.06 |