본문 바로가기
Java/Java 문법 연습

제네릭스 연습 1

by 구너드 2023. 5. 29.
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