Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- XLF
- 금리인하
- 금리인상
- javascript
- 알고리즘
- 주식
- 백준
- 프로그래머스
- 접근제어자
- 제태크
- 잉여현금흐름
- 인플레이션
- StringBuffer
- 자바
- object
- S&P500
- 배당성장
- 기업분석
- 다형성
- Java
- etf
- 미국주식
- 현금흐름표
- 무디스
- mco
- 그리디 알고리즘
- 주린이
- FCF
- 오버라이딩
- 객체지향
Archives
- Today
- Total
오늘의하루
[Java]제한된 Generic 클래스 본문
extends를 이용해 타입을 제한 하기
class Test<T>{}
이 경우에는 모든 타입이 저장가능하다.
class Fruit{}
class Apple extends Fruit{}
class FruitBox<T extends Fruit>{}
FruitBox<Fruit> Test = new FruitBox<Fruit>(); // OK
FruitBox<Apple> Test = new FruitBox<Apple>(); // OK
FruitBox<Toy> Test = new FruitBox<Toy>(); // Error!
이 경우에는 Fruit를 포함해서 Fruit의 자식 타입만 사용할수 있게 된다.
인터페이스의 경우에도 extends를 사용한다.
interface Eatable{ }
class FruitBox<T extends Eatable>{ }
class FruitBox<T extends Fruit & Eatable> { }
- Fruit를 포함한 자식 타입이거나 Eatable를 구현한 클래스 타입만 가능하다.
Generic의 제약
타입 변수에 대입은 인스턴스 별로 다르게 가능하다.
Box<Apple> appleBox = new Box<Apple>(); // OK
제약사항
static 멤버에는 타입 변수를 사용할 수 없다.
class Box<T>{
static T item; // Error!
static int compare(T t1, T t2); // Error!
}
예제
public class MyClass {
public static void main(String args[]) {
FruitBox<Fruit> fruitBox = new FruitBox<Fruit>();
FruitBox<Apple> appleBox = new FruitBox<Apple>();
FruitBox<Grape> grapeBox = new FruitBox<Grape>();
Box<Toy> toyBox = new Box<Toy>();
fruitBox.add(new Fruit());
fruitBox.add(new Apple());
fruitBox.add(new Grape());
appleBox.add(new Apple());
grapeBox.add(new Grape());
System.out.println(fruitBox);
}
}
interface Eatable{}
class Fruit implements Eatable{public String toString(){return "Fruit";}}
class Apple extends Fruit{public String toString(){return "Apple";}}
class Grape extends Fruit{public String toString(){return "Grape";}}
class Toy{public String toString(){return "Toy";}}
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();}
}
class FruitBox<T extends Fruit & Eatable> extends Box<T>{}
배열을 생성할 때 타입 변수 사용 불가하지만 타입 변수로 배열 선언은 가능하다.
class Box<T>{
T[] itemArr; // OK 타입 변수로 배열을 선언할 수 있다.
T[] toArray(){
T[] tmpArr = new T[itemArr.length]; // Error! 타입 변수로 배열을 생성할 수 없다.
}
}
- 간단하게 new 연산자 뒤에는 확정된 타입만 올수 있다.
와일드 카드 <?>
하나의 참조 변수로 대입된 타입이 다른 객체를 참조 가능하다.
- 단, 와일드 카드에서는 <? enxtends T & E>와 같이 "&"를 사용할 수 없다.
class Product{}
class Tv extends Product{}
class Audio extends Product{}
ArrayList<? extends Product> list = new ArrayList<Tv>(); // OK
ArrayList<? extends Product> list = new ArrayList<Audio>(); // OK
ArrayList<Product> list = new ArrayList<Tv>(); // Error! 타입 불일치
와일드 카드에 대해 좀더 알아보기
구분 | 내용 |
<? extends T> | 상한 제한(T를 포함해서 T의 자식 타입들만 가능) |
<? super T> | 하한 제한(T를 포함해서 T의 부모 타입들만 가능) |
<?> | 모든 타입 가능 == < ? extneds Object > |
매개변수로 와일드 카드 사용
static Juice makeJuice(FruitBox<? extends Fruit> box{
String tmp = "";
for(Fruit f : box.getList()){
tmp = tmp + f + " ";
}
return new Juice(tmp);
}
예제
public class MyClass {
public static void main(String args[]) {
// FruitBox<? extends Fruit> appleBox = new FruitBox<Apple>(); // OK Fruit를 포함한 자식 타입 가능
FruitBox<Fruit> fruitBox = new FruitBox<Fruit>();
FruitBox<Apple> appleBox = new FruitBox<Apple>();
fruitBox.add(new Apple());
fruitBox.add(new Grape());
appleBox.add(new Apple());
appleBox.add(new Apple());
System.out.println(Juicer.makeJuice(fruitBox));
System.out.println(Juicer.makeJuice(appleBox));
}
}
class Fruit{public String toString(){return "Fruit";}}
class Apple extends Fruit{public String toString(){return "Apple";}}
class Grape extends Fruit{public String toString(){return "Grape";}}
class Box<T>{
ArrayList<T> list = new ArrayList<T>();
void add(T item){list.add(item);}
T get(int i){return list.get(i);}
ArrayList<T> getList(){return list;}
int size(){return list.size();}
public String toString(){return list.toString();}
}
class FruitBox<T extends Fruit> extends Box<T>{}
class Juice{
String name;
Juice(String name){
this.name = name + "Juice";
}
public String toString(){return name;}
}
class Juicer{
static Juice makeJuice(FruitBox<? extends Fruit> box){
String tmp = "";
for(Fruit f : box.getList()){
tmp = tmp + f + " ";
}
return new Juice(tmp);
}
}
Generic 메서드
제네릭 타입이 선언된 메서드이며 타입 변수는 메서드 내에서만 유효하다.
static <T> void sort(List<T> list, Comparator<? super T> c)
- 클래스의 타입 매개변수 <T>와 타입 매개변수 <T>는 별개이다.
class Test<T>{
static <T> void sort(List <T> list, Comparator<? super T> c){
....
}
}
메서드를 호출할 때 마다 타입을 대입해야한다.
static <T extneds Fruit> Juice makeJuice(FruitBox<T> box){
String tmp = "";
for(Fruit f : box.getList()){
tmp = tmp + f + " ";
}
return new Juice(tmp);
}
System.out.println(Juicer.<Fruit>makeJuice(fruitBox));
System.out.println(Juicer.<Fruit>makeJuice(appleBox));
메서드 호출할 때 타입을 생략하지 않을 때는 클래스 이름 생략 불가하다.
System.out.println(<Fruit>makeJuice(fruitBox)); // Error! 클래스 이름 생략 불가
System.out.println(this.<Fruit>makeJuice(fruitBox)); // OK
System.out.println(Juicer.makeJuice(fruitBox)); // OK
'JAVA' 카테고리의 다른 글
[Java Note] 객체지향 개념 기초 요약본 (0) | 2022.08.29 |
---|---|
[Java] 제네릭(Generics) 정의 선언 사용 제한 메서드 형변환 (0) | 2022.08.26 |
Java로 만든 RPG 게임 (0) | 2022.08.23 |
Java로 만든 스케줄 관리 프로그램 (0) | 2022.08.23 |
Collections & Collection class 정리 (0) | 2022.08.23 |
Comments