본문 바로가기

Java

[Java] 지네릭스란?

지네릭스(Generics) 란?

1. 컴파일시 타입을 체크해 주는 기능(compile-time type check) - JDK1.5

// TV 객체만 저장할 수 있는 ArrayList를 생성
    ArrayList<Tv> tvList = new ArrayList<Tv>();
    
    tvList.add(new Tv());
    tvList.add(new Audio()); // 컴파일 에러! Tv 외에 다른 타입은 저장불가
}

 

2. 객체의 타입 안전성을 높이고 형변환의 번거로움을 줄여줌.

ArrayList tvList = new ArrayList();
tvList.add(new Tv());

Tv tv = (Tv) tvList.get(0); // Object 타입 변환(형변환 필요)

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

Tv tv = tvList.get(0); // 형변환 불필요, 컴파일러가 자동형변환

 

 

 

지네릭스 장점

  1. 타입 안전성을 제공한다.(ClassCastException 형변환 에러)
  2. 타입체크와 형변환을 생략할 수 있으므로 코드가 간결해진다.

 

ArrayList는 Object를 매개변수로 받을 수 있기 때문에 모든 종류의 객체를 인수로 받을 수 있었다.

하지만 지네릭스가 도입된 후 타입을 지정한 후 잘못 들어왔을 시에 컴파일 오류를 내주고 있다.

이는 "실행시 발생에러를 어떻게 컴파일러로 끌어올까? "하는 고민 끝에 나온 결과물이다.

ArrayList list = new ArrayList();
list.add(10);
list.add(20);
list.add("30");

Integer i = (Integer)list.get(2); // 형변환 에러, 런타임 오류
System.out.println(i);

ArrayList<Integer> list = new ArrayList<Integer>();
list.add(10);
list.add(20);
list.add("30"); // 컴파일 오류, 지네릭스 덕분에 타입 체크가 강화됨

Integer i = (Integer)list.get(2); // 형변환 에러, 런타임 오류
System.out.println(i);

 

 

 

타입 변수

지네릭 클래스를 작성할 떄, Object 타입 대신 타입 변수(E)를 선언해서 사용.

 

 

타입 변수에 대입하기

  • 객체를 생성시, 타입변수(E) 대신 실제 타입(Tv)를 대입
  • 타입 변수 대신 실제 타입이 지정되면, 형변환 생략가능!
// 타입 변수 E 대신에 실제 타입 Tv를 대입
ArrayList<Tv> tvList = new ArrayList<Tv>();

 

 

 

지네릭스 용어

Box<String> b = new Box<String>();

 

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

T: 타입 변수 또는 타입 매개변수.(T는 타입 문자)

Box: 원시 타입(raw type)

 

 

지네릭 타입과 다형성

참조 변수와 생성자이 대입된 타입은 일치해야 한다.

class Product{ }
class Tv extends Product{ }
class Audio extends Product{ }
ArrayList<Tv> tvList = new ArrayList<Tv>(); // OK. 일치
ArrayList<Product> tvList = new ArrayList<Tv>(); // 에러. 불일치

 

 

지네릭 클래스 간의 다형성은 성립(여전히 대입된 타입은 일치해야 한다)

List<Tv> list = new ArrayList<Tv>();
List<Tv> list = new LinkedList<Tv>();

 

매개변수의 다형성도 성립

ArrayList<Product> List = new ArrayList<Product>(); 
list.add(new Product());
list.add(new Tv()); // OK, Product의 자손
list.add(new Audio()); // OK, Product의 자손
boolean add(E e){...} // 기존
boolean add(Product e){...} // 변경 후, 자손 객체 쌉가능
Product p = list.get(0);
Tv t = (Tv)list.get(1); // list.get의 반환타입이 Product로 바뀌었기 떄문에 Tv 타입으로 받아야 한다.

 

public class Ex3 {

    public static void main(String[] args) {
        ArrayList<Product> productList = new ArrayList<Product>();
        ArrayList<Tv> tvList = new ArrayList<Tv>();
        //ArrayList<Product> tvList1 = new ArrayList<Tv>(); // 에러.
        //List<Tv> tvList2 = new ArrayList<Tv>(); // OK. 다형성

        productList.add(new Tv()); // public boolean add(Product e){... }
        productList.add(new Audio()); // public boolean add(Product e){... }

        tvList.add(new Tv());
        tvList.add(new Tv());

        printAll(productList);
        //printAll(tvList); // 컴파일 에러가 발생한다.
        printAll2(tvList);
    }
    public static void printAll(ArrayList<Product> list) {
        for (Product p : list) {
            System.out.println(p);
        }
    }
    public static void printAll2(ArrayList<Tv> list) {
        for (Tv t : list) {
            System.out.println(t);
        }
    }
}
class Product{ }
class Tv extends Product{ }
class Audio extends Product{ }
ex.generics.Tv@1d81eb93
ex.generics.Audio@7291c18f
ex.generics.Tv@34a245ab
ex.generics.Tv@7cc355be

'Java' 카테고리의 다른 글

[Java] 지네릭 클래스의 제약  (0) 2024.05.10
[Java] Iterator<E>, Map<K, V>  (0) 2024.05.09
[Java] Collections 컬렉션을 위한 메서드  (0) 2024.05.08
[Java] HashMap 키와 값  (0) 2024.05.08
[Java] TreeSet 범위 탐색, 정렬  (0) 2024.05.08