Q. 왜 제네릭을 사용해야 할까?
- 제네릭은 클래스와 인터페이스, 그리고 메소드를 정의할 때 타입(type)을 파라미터(parameter)로 사용할 수 있도록 한다.
타입 파라미터는 코드 작성 시 구체적인 타입으로 대체되어 다양한 코드를 생성하도록 해준다.
제네릭을 사용하는 코드가 비제네릭 코드에 비해 가지는 이점?
1. 컴파일 시 강한 타입 체크를 할 수 있다.
: 자바 컴파일러는 코드에서 잘못 사용된 타입 때문에 발생하는 문제점을 제거하기 위해 제네릭 코드에 대해 강한 타입 체클르 한다.
실행 시 타입 에러가 나는 것보다는 컴파일 시에 미ㅣ 타입을 강하게 체크해서 에러를 사전에 방지하는 것이 좋다.
2. 타입 변환(casting)을 제거한다.
: 비제네릭 코드는 불필요한 타입 변환을 하기 때문에 프로그램 성능에 악영향을 미친다.
제네릭 코드는 타입을 국한하기 때문에 타입 변환을 할 필요가 없어 프로그램 성능이 향상된다.
제네릭 타입(class<T>, interface<T>)
- 제네릭 타입은 타입을 파라미터로 가지는 클래스와 인터페이스를 말한다.
- 타입 파라미터는 변수명과 동일한 규칙에 따라 작성할 수 있지만, 일반적으로 대문자 알파벳 한글자로 표현한다.
- 제네릭 타입을 실제 코드에서 사용하려면 타입 파라미터에 구체적인 타입을 지정해주어야 한다.
멀티 타입 파라미터(class<K, V, ...>, interface<K, V, ...>)
- 제네릭 타입은 두 개 이상의 멀티 타입 파라미터를 사용할 수 있는데, 이 경우 각 타입 파라미터를 콤마로 구분한다.
제네릭 메소드(<T, R> R method(T t))
- 제네릭 메소드는 매개 타입과 리턴 타입으로 타입 파라미터를 갖는 메소드를 말한다.
- 제네릭 메소드를 선언하는 방법은 리턴 타입 앞에 <> 기호를 추가하고 타입 파라미터를 기술하고 리턴 타입과 매개 타입으로 파라미터를 사용한다.
public <타입 파라미터, ...>; 리턴타입 메소드명(매개변수, ....) { ... }
public <T> Box<T> boxing(T t) { ... }
리턴타입 변수 = <구체적인 타입> 메소드명(매개값); // 명시적으로 구체적 타입을 지정
리턴타입 변수 = 메소드명(매개값); // 매개값을 보고 구체적 타입을 추정
Box<Integer> box = <Integer>boxing(100); // 타입 파라미터를 명시적으로 지정
Box<Integer> box = boxing(100); // 타입 파라미터를 Integer로
|
제한된 타입 파라미터(<T extends 최상위타입>)
- 타입 파라미터에 지정되는 구체적인 타입을 제한할 필요가 종종 있다. 예를 들어 숫자를 연산하는 제네릭 메소드는 매개값으로 Number 타입 또는 하위 클래스 타입(Byte, Short, Integer, Long, Double)의 인스턴스만 가져야 한다.
- 제한된 타입 파라미터를 선언하려면 타입 파라미터 뒤에 extends 키워드를 붙이고 상위 타입을 명시하면 된다.
- 타입 파라미터에 지정되는 구체적인 타입은 상위타입이거나 상위 타입의 하위 또는 구현 클래스만 가능하다.
- 주의할 점은 메소드의 중괄호 {} 안에서 타입 파라미터 변수로 사용 가능한 것은 상위 타입의 멤버(필드, 메소드)로 제한된다.
public <T extends 상위타입> 리턴타입 메소드(매개변수, ...) { ... }
|
public<T extends Number> int compare(T t1, T t2){
double v1 = t1.doubleValue(); // Number의 doubleValue() 메소드 사용
double v2 = t2.doubleValue(); // Number의 doubleValue() 메소드 사용
return Double.compare(v1, v2);
}
|
와일드카드 타입 (<?>, <? extends ...>, <? super ... >)
- 코드에서 ?를 일반적으로 와일드카드(wildcard)라고 부른다.
- 제네릭 타입을 매개값이나 리턴 타입으로 사용할 떄 구체적인 타입 대신에 와일드카드를 다음과 같이 3가지 형태로 사용할 수 있다.
‣ 제네릭타입<?> : Unbounded Wildcards(제한 없음)
타입 파라미터를 대치하는 구체적인 타입으로 모든 클래스나 인터페이스 타입이 올 수 있다.
‣ 제네릭타입<? extends 상위타입> : Upper Bounded Wildcards (상위 클래스 제한)
타입 파라미터를 대치하는 구체적인 타입으로 상위 타입이나 하위 타입만 올 수 있다.
‣ 제네릭타입<? super 하위타입> : Lower Bounded Wildcards (하위 클래스 제한)
타입 파라미터를 대치하는 구체적인 타입으로 하위 타입이나 상위 타입이 올 수 있다.
・ Course<?>
: 수강생은 모든 타입(Person, Worker, Student, HighStudent)이 될 수 있다.
・ Course<? extends Student>
: 수강생은 Student와 HighStudent만 될 수 있다.
・ Course<? extends Student>
: 수강생은 Worker와 Person만 될 수 있다.
제네릭 타입의 상속과 구현
- 제네릭 타입도 다른 타입과 마찬가지로 부모 클래스가 될 수 있다.
- 자식 제네릭 타입은 추가적으로 타입 파라미터를 가질 수 있다.
public Class ChildProduct<T, M, C> extends Product<T, M> { ... }
|
cs |
'Java > Basic' 카테고리의 다른 글
[Java] 변수(Variable) (0) | 2020.03.14 |
---|---|
[Java] 클래스(Class)와 객체(Object) (0) | 2020.03.10 |
[Java] JVM(Java Virtual Machine) (0) | 2020.03.08 |
[Java] 람다식(Lambda Expressions) (0) | 2020.02.29 |
[Java] 멀티스레드(Multi Thread) (1) | 2020.01.06 |