티스토리 뷰
1.1 지네릭스란?
다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에 Compile 시 타입 체크를 해주는 기능!
지네릭스의 장점
1. 타입의 안정성을 제공
2. 타입체크와 형변환을 생략할 수 있으므로 코드가 간결해짐
1.2 지네릭 클래스의 선언
class Box(
Object item;
void setItem(Object item) { this.item = item; }
Object getItem() { return item; }
)
위 클래스를 지네릭 클래스로 변경하면 다음과 같이 클래스 옆에 '<T>'를 붙이고, 'Object'를 모두 'T'로 바꾼다.
class Box<T> { // 지네릭 타입 T를 선언
T item;
void setItem(T item) { this.item = item; }
T getItem() { return item; }
}
Box<T> : 타입 변수(Type Variable) T는 'Type'의 첫 글자
ArrayList<E> : 타입 변수(Type Variable) E는 'Element'의 첫 글자
Map<K, V> : 타입 변수가 여러개인 경우 콤마(,) 로 구분, K는 'Key'(키)를 의미하고 V는 'Value'(값)을 의미
* 상황에 맞게 사용!
* 예시
Box<String> b = new Box<String>(); // 타입 T 대신, 실제 타입을 지정
b.setItem(new Object()); // 에러. String 이외의 타입은 지정할 수 없음!!
b.setItem("ABC"); // OK. String 타입이므로 지정 가능!!
String item = (String) b.getItem(); // 형변환 불필요
/**
* 지네릭 클래스 Box<T> 정의
*/
class Box {
String item;
void setItem(String item) { this.item = item; }
String getItem() { return item; }
}
1.3 지네릭 클래스의 객체 생성과 사용
1) 참조변수와 생성자에 대입된 타입이 불일치 시 에러 발생
Box<Grape> grapeBox = new Box<Apple>; // 에러 발생. 대입된 타입 다름
2) 두 타입이 상속 관계에 있어도 에러 발생
Box<Fruit> appleBox = new Box<Apple>(); // 에러 발생. 대입된 타입 다름
3) 두 지네릭 클래스의 타입이 상속관계이고, 대입된 타입이 같으면 가능
Box<Apple> appleBox = new FruitBox<Apple>(); // OK. 다형성
* 예시 코드
package Generic;
import java.util.ArrayList;
class Fruit {
public String toString() { return "Fruit"; }
}
class Apple extends Fruit { // Fruit 상속
public String toString() { return "Apple"; }
}
class Grape extends Fruit { // Fruit 상속
public String toString() { return "Graple"; }
}
class Toy {
public String toString() { return "Toy"; }
}
public class FruitBoxEx1 {
public static void main(String[] args){
Box<Fruit> fruitBox = new Box<Fruit>();
Box<Apple> appleBox = new Box<Apple>();
Box<Toy> toyBox = new Box<Toy>();
// Box<Grape> grapeBox = new Box<Apple>(); // 에러. 타입 불일치!
fruitBox.add(new Fruit());
fruitBox.add(new Apple()); // OK. void add(Fruit item) Apple은 Fruit의 자식
appleBox.add(new Apple());
appleBox.add(new Apple());
// appleBox.add(new Fruit()); // 에러. only Apple 만
// appleBox.add(new Toy()); // 에러. Box<Apple>에는 Apple만 담을 수 있음
toyBox.add(new Toy());
// toyBox.add(new Apple()); // 에러, Box<Toy>에는 Apple을 담을 수 없음.
System.out.println(fruitBox);
System.out.println(appleBox);
System.out.println(toyBox);
}
}
class Box<T> {
ArrayList<T> list = new ArrayList<T>();
void add(T item) { list.add(item); }
T get(int i) { return list.get(i); }
int size() { return list.size(); }
public String toString() { return list.toString(); }
}
실행결과
[Fruit, Apple]
[Apple, Apple]
[Toy]
1.4 제한된 지네릭 클래스
타입 매개변수 T에 지정할 수 있는 타입의 종류를 제한하는 방법
class FruitBox<T extends Fruit> { // Fruit의 자손만 타입으로 지정 가능!!
ArrayList<T> list = new ArrayList<T>();
}
class sample{
public static void main(String[] args){
FruitBox<Fruit> fruitBox = new FruitBox<Fruit>();
fruitBox.add(new Apple()); // OK. Apple은 Fruit의 자손
fruitBox.add(new Graple()); // OK. Grape는 Fruitdml 자손
}
}
인터페이스를 구현해야한다면 이 때도 "extends"를 사용. Not "implemnet"
Fruit의 자손이면서, Eatable 인터페이스도 구현할 경우 " & " 기호 사용
interface Eatable {}
class FruitBox<T extends Fruit & Eatable> { ... }
1.5 와일드 카드
지네릭 클래스에서 static 메서드에는 타입 매개변수 T를 매개변수에 사용할 수 없음.
static 메서드의 경우 특정 타입을 지정해줘야하는데.
아래와 같이 FruitBox<Apple> 타입 객체는 makeJuice() 매개변수가 될 수 없으므로, 여러 가지 타입의 매개변수를 갖는 makeJuice()를 만들어야함.
static Juice makeJuice(FruitBox<Fruit> box) {
String tmp = "";
for(Fruit f : box.getList()) tmp += f + " ";
return new Juice(tmp);
}
static Juci makeJuice(FruitBox<Apple> box) {
String tmp = "";
for(Fruit f : box.getList()) tmp += f + " ";
return new Juice(tmp);
}
하지만, 위와 같이 오버로딩하면 컴파일 에러가 발생! ➣ 지네릭 타입이 다른 타입 만으로는 오버로딩 성립 안함
이를 해결하기 위한(static 메서드에서 여러 지네릭 타입 사용) 기능이 바로 와일드 카드!!
<? extends T> 와일드카드의 상한제한. T와 그 자손들만 가능
<? super T> 와일드카드의 하한제한. T와 그 조상들만 가능
<?> 모든 타입 가능. <? extends Object>와 동일
*<? extends T> 예시
static Juice makeJuice(FruitBox<? extends Fruit> box) {
String tmp = "";
for(Fruit f : box.getList()) tmp += f + " ";
return new Juice(tmp);
}
* <? super T> 예시
static <T> void sort(List<T> list, Comparator<? super Apple> c)
comparator<? super Apple> 의미 : comparator 타입 매개변수로 Apple과 그 조상이 가능
Comparator<? super Apple> : Comparator<Apple>, Comparator<Fruit>, Comparator<Object> 가능
Comparator<? super Grape> : Comparator<Grape>, Comparator<Fruit>, Comparator<Object> 가능
'Java' 카테고리의 다른 글
[Stream API] 스트림 만들기 (0) | 2023.10.28 |
---|---|
[Stream API] 스트림이란? (0) | 2023.10.28 |
[Java] 자바 언어의 특징 (0) | 2023.07.24 |
[Java] BufferedReader / BufferedWriter 정리 (0) | 2023.02.22 |
[Java] 접근제어자 혹은 접근제한자 (0) | 2022.11.20 |
- Total
- Today
- Yesterday
- Spring
- 자바
- springboot
- dxdy
- 재기동
- NLU
- Comparable
- 유데미
- 글또
- 나만의챗봇
- RASA
- 회고록
- thymeleaf
- 전자정부프레임워크
- script
- BFS
- 백준
- 코딩테스트
- 코드트리
- 항해99
- 객체정렬
- 취리코
- 챗봇
- 취업리부트코스
- Java
- Comparator
- 개발자취준
- JWT
- BufferedWriter
- BufferedReader
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |