import java.util.*;
public class Generics {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
list.add("String") // 에러!
}
}
ArrayList 지네릭 클래스가 Integer로 타입이 설정되어 있으므로 다른 타입이 들어올 수 없다
import java.util.*;
public class Generics {
public static void main(String[] args) {
ArrayList<Product> list = new ArrayList<Tv>(); // 에러!
}
}
class Product{}
class Tv extends Product{}
class Audio extends Product{}
자식 클래스의 타입이어도 들어올 수 없다는 점.
ArrayList<Product> list = new ArrayList<Product>();
list.add(new Tv());
list.add(new Audio());
다만 생성된 리스트 안에 자식 클래스인 Tv객체와 Audio객체를 넣을 수는 있음
Iterator ( ) 에도 지네릭스가 들어가는데,
class Player{
String name = "";
int age;
Player(String name, int age) {
this.name = name;
this.age = age;
}
}
class Foward extends Player{
int skillpoint;
int game;
Foward (String name, int age, int skillpoint, int game) {
super(name,age);
this.skillpoint = skillpoint;
this.game = game;
}
}
부모 클래스 Player와 자식 클래스 Foward를 생성,
import java.util.*;
public class Generics {
public static void main(String[] args) {
ArrayList<Player> list = new ArrayList<Player>();
list.add(new Foward("Gabriel Jesus",28,9,30));
list.add(new Foward("Bukayo Saka", 24,8,44));
list.add(new Foward("Leandro Trosaar", 29,7,19));
Iterator<Player> it = list.iterator();
while (it.hasNext()) {
Foward f = (Foward) it.next();
System.out.println(f.skillpoint);
}
}
}
Iterator( )로 skillpoint를 뽑아낼 수 있었다.
여기서 Iterator( )는 Player라는 지네릭 타입을 적용하고 실제 list 안에는 Foward 타입을 넣었는데 이 경우, Foward f 는 (Foward)로 형변환을 해야지만 Foward 객체 내 인스턴스 변수들의 정보를 가져올 수 있었다.
Iterator<Player> it = list.iterator();
while (it.hasNext()) {
Player p = it.next();
System.out.println(p.name);
이런 식으로 형변환 없이 Player p를 사용할 때는 Player 클래스의 인스턴스 변수인 name과 age만 읽어올 수 있다.
다형성이 적용된 예라고 볼 수 있다.
타입 매개 변수에 지정할 수 있는 타입의 종류를 제한하는 법
지네릭 타입에 extends를 사용하면 특정 타입의 자손들만 대입할 수 있게 제한 가능
이때 클래스가 아니라 인터페이스를 구현해야한다는 제약이 필요하면 implements가 아닌 extends를 사용
interface playable{}
class player implements playable {
public String toString() { return "Player";}
}
class foward1 extends player {
public String toString() { return "Foward";}
}
class defender1 extends player {
public String toString() { return "Defender";}
}
toString 을 통해 각 클래스의 이름이 반환되도록 설정하여 클래스를 설정
class playerList<T extends player> extends List<T>{}
class List<T> {
ArrayList<T> list = new ArrayList<T>();
void add(T position) { list.add(position);}
T get(int i) {return list.get(i);}
int size() {return list.size();}
public String toString() { return list.toString();}
}
타입 매개변수 T가 있는 List 클래스 생성 후
player와 그 자식 클래스까지 타입 매개 변수로 가질 수 있는 playerList클래스를 List 클래스의 자식 클래스로 설정
class Generics2 {
public static void main(String[] args) {
playerList<player> p = new playerList<player>();
playerList<foward1> p1 = new playerList<foward1>();
p.add(new player());
p.add(new defender1());
p1.add(new foward1());
p1.add(new foward1());
System.out.println("playerList = " + p);
System.out.println("fowardList = " + p1);
이 후 player 타입 매개 변수를 지정하는 ArrayList p와 foward1 타입 매개 변수를 지정하는 ArrayList p1을 각각 생성
이 때 p1은 타입 매개 변수가 foward1이므로 player 혹은 defender1을 add메서드의 position에 넣게 될 경우 에러가 발생한다.
playerList = [Player, Defender]
fowardList = [Foward, Foward]
만들고자 했던 배열리스트와 동일한 모습으로 프린트할 수 있었다.
이처럼 타입 매개 변수 T에 특정 타입과 그 자식 클래스를 포함하여 지정하게 되면 T에 들어갈 수 있는 타입의 종류를 제한할 수 있다.
'Java > Java 문법 연습' 카테고리의 다른 글
열거형 연습 (0) | 2023.05.30 |
---|---|
제네릭스 연습 2 (2) | 2023.05.30 |
컬렉션 프레임워크 연습 (1) | 2023.05.26 |
객체지향 연습 (1) | 2023.05.21 |
배열 연습 (0) | 2023.05.12 |