본문 바로가기

카테고리 없음

자바의 정석 지네릭스 정리

자료 출처는 남궁성 책 유튜브

 

지네릭스란?

ArrayList<Tv> tvList = new ArrayList<Tv>();
tvList.add(new Tv());//ok
tvList.add(new Audio());//컴파일 에러
tv라는 탑입으로만 add가 가능하다.

컴파일시 타입을 체크를 해주는 기능

package Generics_study;
import java.util.ArrayList;


public class GenericTest {
    public static void main(String[] args) {
        ArrayList lst = new ArrayList();
        lst.add(10);
        lst.add(20);
        lst.add("30"); //String 을 추가 해도 에러 안남

        //만약에 integer로 받으면??
        Integer i = (Integer)lst.get(2);//컴파일이 가능하다. ->하지만 ClassCastException 발생
        //컴파일러의 한계임 
        System.out.println(lst);
    }
}

 

위의 예제는 컴파일러의 한계를 보여줌 컴파일러는 꺼낼 때 object 타입이라서 실제로 뭔지

컴파일러가 체크를 할 수 없음 즉 runtime 에러 발생

컴파일시 못 잡아내는 에러를 알 수 있기 위한 것이 지네릭스이다.

즉 컴파일러에게 인테저만 저장 할 수 있게 명시를 하도록 바꾼 코드

 

 

package Generics_study;

import java.util.ArrayList;

public class GenericTest {
    public static void main(String[] args) {
        ArrayList<Integer> lst = new ArrayList<Integer>();
        lst.add(10);
        lst.add(20);
        lst.add("30"); //에러 방생

        //만약에 integer로 받으면??
        Integer i = (Integer)lst.get(2);//컴파일이 가능하다. ->하지만 ClassCastException 발생
        //컴파일러의 한계임
        System.out.println(lst);
    }

 

 

 

//여러 종류의 객체를 저장을 하고 싶을 때는?
ArrayList<Object> list = new ArrayList<Object>();
list.add(10);
list.add(20);
list.add("30");
String i = (String)list.get(2); //값을 가져올 수 있다.
System.out.println(i);

 

제네릭은 실행시 발생하는 에러를 안생기게 하기 위해서 컴파일 타임에 프로그램을 수정 할 수 있게 된다.

 

 

타입 변수에 대입하기

객체를 생성시, 타입 변수(E) 대신 실제 타입(TV)를 지정 대입

ArrayList<Tv> tvList = new ArrayList<Tv>();

public class ArrayList<E> extends AbstractList<E> {

private transient E[] elementData;

public boolean add(E o) {}

public E get(int index) {}

} //E에 Tv가 대입이 된다.

 

 

 

ArrayList<Tv> list = new ArrayList<Tv>();//Tv 타입 객체만 저장 가능
list.add(new Tv());
list.add(new Audio());//에러 발생
ArrayList list = new ArrayList();//모든 타입 객체 저장 가능
list.add(new Tv());
list.add(new Audio());//에러 발생

 

지네릭스는 Box<T> 지네릭 클래스 T의 Box 또는 T Box라고 읽는다.

T는 타입 변수 또는 타입 매개변수이다.

Box는 원시 타입

 

 

 

 

arrylist는 list의 자손 클래스이면 
List<Tv>list  = new ArrayList<Tv>(); //다형성은 가능
List<Tv>list = new LinkedList<Tv>();
제네릭안의 타입은 일치해야 한다.

 

 

 

타입의 자손 
class Product {}
class Tv extends Product{}
class Audio extends Product{}
ArrayList<Product> list = new ArrayList<Product>();
list.add(new Product());
list.add(new Tv());
list.add(new Audio()); 자손을 넣으면 괜찮음
ArrayList<Product> productList = new ArrayList<Product>();
//ArrayList<Tv> tvList = new ArrayList<Product>();//<-에러 발생

 

 

class Product{}
class Tv extends Product{}
class Audio extends Product{}



class Product{}
class Tv extends Product{}
class Audio extends Product{}
ArrayList<Tv> tvList = new ArrayList<Tv>();

tvList.add(new Tv());
tvList.add(new Tv());
tvList.add(new Audio());//오디오는 tv의 자손이 아니다! 에러 발생

항상 참조변수 타입하고 생성자 대입 타입이 일치를 해야한다.

 

와일드 카드

하나의 참조 변수로 대입된 타입이 다른 객체를 참조가 가능한데

위의 처럼 extends 하면 그의 자손들만 가능하고

super하면 T와 그 조상들만 가능하다.