희렌버핏

13장 제네릭 본문

카테고리 없음

13장 제네릭

Oliviakim 2019. 2. 24. 16:41

13.1 왜 제네렉을 사용해야 하는가?

- 제네릭 이란 : 타입을 파라미터와해서 컴파일시 구체적인 타입이 결정되도록 하는 것

- 자바 5부터 추가됨

- 컬렉션, 람다식(함수적 인터페이스), 스트림, NIO에서 널리 사용

- 제네릭을 모르면 도큐먼트 해석 불가

- 제네릭 사용 이점

- 컴파일시 강한 타입 체크 : 컴파일시 미리 타입을 강하게 체크해서 에러 사전 방지

- 타입변환 제거 가능

List list = new ArrayList();

list.add("hello"); //Object 타입으로 자동 타입 변환

String str = (String) list.get(0); //String 타입으로 강제 타입 변환


List<String> list = new ArrayList<String>(); //List에 String 타입만 저장하겠다.

list.add("hello"); //string 값만 줘야 되고 string 타입으로 저장된다.

String str = list.get(0);


13.2 제네릭 타입 (class<T>, interface<T>)

- 제네릭 타입이란

- 타입을 파라미터로 가지는 클래스와 인터페이스를 말한다.

- 선언시 클래스 또는 인터페이스 이름 뒤에 "<>" 부호가 붙는다.

- "<>" 사이에는 타입 파라미터가 위치한다.

public class 클래스명<T> {...}

public interface 인터페이스명<T> {...}

- 타입 파라미터

- 일반적으로 대문자 한개로 표현됨

- 개발 코드에서는 타입 파라미터 자리에 구체적인 타입 지정 필요

- 제네릭 타입을 사용할 경우의 효과

비제네릭 : Object 타입을 사용해서 빈번한 타입 변환 발생 -> 성능 저하

public class Box {

private Object object;    //모든 자바 클래스의 최상위 부모 클래스

public void set(Object object) {this.object = object;}    //매개 변수의 클래스 뿐만 아니라 자식 객체도 들어갈 수 있다. 모든 객체를 매개값으로 받아서 필드에 받을 수 있다. 최상위Object로 되어 있기때문에.

public Object get() {return object}    //Object 타입으로 리턴

}

Box box = new Box( );

box.set("hello");    //String 타입을 Object 타입으로 자동 타입 변환해서 저장

String str = (String) box.get();    //Object 타입을 String 타입으로 강제 타입 변환해서 얻음

* 제네릭 : 클래스를 선언할 때 타입 파라미터로 기술. 컴파일시 작성한 타입 파라미터가 구체적인 클래스로 변환된다.

=> 다양한 객체를 받아올 수 있고, 타입 변환도 하지 않아도 된다.

public class Box<T> {

private T t;

public T get() {return t;}

public void set(T t) {this.t = t;}

}

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

box.set("hello"); //String 아닌 것이 들어오면 에러남

String str = box.get();


13.3 멀티 타입 파라미터 (class<K,V,...>, interface<K,V,...>)

- 두개 이상의 타입 파리미터 사용 선언 가능

- class<K, V, ...> {...}

- interface<K,V,...> {...}

public class Product <T,M> {

private T kind;

private M model;


public T getKind() {return this.kind;}

public M getModel() {return this.model;}


public void setKind(T kind) {this.kind = kind;}

public void setModel(M model) {this.model = model;}

}

- 중복된 타입 파라미터를 생략한 다이아몬드(<>) 연산자

Product<Tv, String> product = new Product<> ( );

13.4 제네릭 메소드(<T,R> R method(T t))

- 매개변수 타입리턴 타입으로 타입 파라미터를 갖는 메소드

- 선언 방법

public <타입파라미터,...> 리턴타입 메소드명(매개변수,...) {...}

public <T> Box<T> boxing(T t) {...}

- 제네릭 메소드를 호출하는 두가지 방법

Box <Integer> box = <Integer> boxing(100);    //타입 파라미터를 명시적으로 Integer로 지정

Box <Integer> box = boxing(100);    // 매개값을 보고 타입 파라미터를 Integer로 추정

13.5 제한된 타입 파라미터(<T extends 최상위타입>)

- 타입 파라미터에 구체적인 타입을 제한할 필요가 있을 경우

- 상속 및 구현 관계를 이용해서 타입 제한

public <T extends 상위타입> 리턴타입 메소드 (매개변수, ...) {...}

* 상위 타입은 클래스, 인터페이스 다 됨. 인터페이스는 implements가 아니라 extends를 쓴다.

- 주의

- 중괄호 안에는 파라미터에 지정한 클래스 안에 있는 필드와 메소드만 사용 가능

- 하위 타입에만 있는 필드와 메소드는 사용할 수 없다.

13.6 와일드 카드 타입 (<?>,<? extends ...>, <? super ...>)

- 제네릭 타입을 매개변수나 리턴타입으로 사용할 때 타입 파라미터를 제한할 목적

1. 제네릭타입<?> : Unbounded Wildcards (제한없음)

- 모든 클래스, 인터페이스 타입이 올 수 있음

2. 제네릭타입<? extends 상위타입> : Upper Bounded Wildcards (상위 클래스 제한)

- 상위 타입이거나 하위 타입만 올 수 있다.

3. 제네릭타입<? super 상위타입> : Lower Bounded Wildcards (하위 클래스 제한)

- 지정한 상위 클래스, 자유롭게 올 수 있음 

13.7 제네릭 타입의 상속과 구현

- 제네릭 타입을 부모 클래스로 사용할 경우 : 부모도 동일하게 제네릭, 자식은 추가 파라미터 가질 수 있다.

public class ChildProduct<T,M,C> extends Product<T,M> {...}

- 제네릭 인터페이스를 구현할 경우 : 구현클래스에도 타입 파라미터 기술

pulic class StorageImpl <T> implements Storage<T> {...}