///////
Search
♟️

Generics

김준호_0930

제네릭(Generics)

제네릭스는 다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에 컴파일 시의 타입 체크를 해주는 기능이다.
객체의 타입을 컴파일 시에 체크하기 때문에 객체의 타입 안정성을 높이고 형변환의 번거로움이 줄어든다.
// Tv객체만 저장할 수 있는 ArrayList를 생성 ArrayList<Tv> tvList = new ArrayList<Tv>(); tvList.add(new Tv());// OK tvList.add(new Audio());// 컴파일 에러. Tv 외에 다른 타입은 저장불가
Java
복사
이미 어떤 타입의 객체들이 저장되어 있는지 알고 있기 때문에 저장된 객체를 꺼낼 때는 형변환할 필요가 없어서 편리하다.

제네릭의 장점

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

타입변수

선언에서 클래스 이름 옆의 ‘<>’안에 있는 E를 ‘타입 변수(type variable)’라고 하며, 일반적으로는 ‘Type’의 첫 글자를 따서 T를 사용한다.
타입 변수로 반드시 T를 사용해야 하는 것은 아니며, T가 아닌 다른 것을 사용해도 된다.
public class ArrayList<E> extends AbstractList<E> {// 일부 생략private transient E[] elementData; public boolean add(E o) {/* 내용생략 */ } public E get(int index) {/* 내용생략 */ } ... }
Java
복사
타입 변수가 여러 개인 경우에는 Map<K, V>와 같이 콤마’,’를 구분자로 나열하면 된다. K는 Key(키)를 의미하고, V는 Value(값)을 의미한다. 이들은 기호의 종류만 다를 뿐 ‘임의의 참조형 타입’을 의미한다.

제네릭이 도입되기 이전 ArrayList의 소스

public class ArrayList extends AbstractList {// 일부 생략private transient Object[] elementData; public boolean add(Object o) {/* 내용 생략 */ } public Object get(int index) {/* 내용 생략 */ } }
Java
복사
기존에는 다양한 종류의 타입을 다루는 메서드의 매개변수나 리턴타입으로 Object타입의 참조변수를 많이 사용했고, 그로 인해 형변환이 불가피했지만, 이젠 Object타입 대신 원하는 타입을 지정하기만 하면 되는 것이다.

제네릭이 도입되기 이전 코드의 문제점

1.
제네릭을 사용하기 이전에는 Object를 사용하여 모든 객체를 받아들였기 때문에 값을 사용하기 위해서 형변환이 필요했다.
2.
프로그래머의 실수가 컴파일 과정에서 발견되지 않음.
코드

타입변수 대입

지네릭 클래스를 생성할 때는 다음과 같이 참조변수와 생성자에 타입 변수 E 대신에 Product와 같은 실제 타입을 지정해주어야 한다.
// 타입 변수 E 대신에 실제 타입 Product를 대입 ArrayList<Product> tvList = new ArrayList<Product>();
Java
복사
이때, 타입 변수 E 대신 지정된 타입 Product를 ‘대입된 타입(parameterized type)’이라고 한다.
public class ArrayList<E> extends AbstactList<e> {// 일부생략private transient E[] elementData; public boolean add(E o) {/* 내용 생략 */ } public E get(int index) {/* 내용 생략 */ } ... }
Java
복사
타입이 대입되고 나면, ArrayList의 선언에 포함된 타입 변수 E가 아래와 같이 지정된 타입으로 바뀐다고 생각하면 된다.
public class ArrayList extends AbstractList {// 일부 생략private transient Tv[] elementData; public boolean add(Tv o) {/* 내용 생략 */ } public Tv get(int index) {/* 내용 생략 */ }// Object가 아닌 Tv를 반환 ... }
Java
복사
위 코드의 get()이 Object가 아닌 Product를 반환하게 되므로 형변환이 필요 없게 된다.

제네릭 용어

Box<T> 지네릭 클래스. ‘T의 Box’또는 ‘T Box’라고 읽는다. T 타입 변수 또는 타입 매개변수.(T는 타입 문자) Box 원시 타입(raw type)
타입 문자 T는 메서드의 매개변수와 유사한 면이 있기 때문에, 지네릭 클래스의 Box<T>의 타입 변수 또는 타입 매개변수라고 한다.
아래와 같이 타입 매개변수에 타입을 지정하는 것을 ‘지네릭 타입 호출’이라고 하고, 지정된 타입 ‘String’을 ‘매개변수화된 타입(parameterized type)’이라고 한다.

제네릭과 다형성

제네릭 클래스의 객체를 생성할 때, 참조변수에 지정해준 지네릭 타입과 생성자에 지정해준 지네릭 타입은 일치해야 한다.
ArrayList<Tv> list = new ArrayList<Tv>(); // OK. 일치 ArrayList<product> list = new ArrayList<Tv>(); // 에러. 불일치 ... class Product {} class Tv extends Produce {} class Audio extends Produce {}
Java
복사
제네릭 타입이 아닌 클래스의 타입 간에 다형성을 적용하는 것은 가능하다. 이 경우에도 제네릭 타입은 일치해야한다.
List<Tv> list = new ArrayList<Tv>(); // OK. ArrayList가 List를 구현 List<Tv> list = new LinkedList<Tv>(); // OK. LinkedList가 List를 구현
Java
복사

박수진_0930

제네릭 이전 코드

Code
Explain

이전 코드의 문제점

Code

제네릭

인스턴스 생성 시 결정되는 자료형의 정보를 T로 대체한다.
타입 매개변수 (Type Parameter) Box<T>에서 T
타입 인자 (Type Argument) Box<Apple>에서 Apple
매개변수화 타입 (Parameterized Type) Box<Apple>
Code
Explain

제네릭 클래스의 타입 인자 제한하기

class Box<T extends Number>
Code
Explain