제네릭 (Generic)
자바 제네릭(Generic)은 "데이터의 클래스 타입을 내부에서 지정하는 것이 아닌 외부에서 사용자에 의해 지정되는 것"을 의미한다.
ArrayList<String> list1 = new ArrayList<String>();
ArrayList<Integer> list2 = new ArrayList<>();
ArrayList<Double> list3 = new ArrayList<>();
위와 같이 List마다 안에 들어갈 객체들이 각각 다를 경우 제네릭을 통해 다양한 자료구조를 사용할 수 있다.
만약 제네릭이 없었다면 String클래스, Integer 클래스 등 하나하나 타입에 맞게 자료구조를 만들어야 한다. 하지만, 제네릭은 이러한 문제를 해결해 준다.
특징
- 제네릭은 <> 다이아몬드 표기법으로 타입 파라미터를 지정한다.
- 데이터 타입은 클래스 혹은 인터페이스만 가능하다.
- 기본 자료형은 제네릭의 데이터 타입으로 지정할 수 없다.
- int (x) → Integer (o)
- double (x) → Double (o)
장점
- 제네릭을 사용하면 잘못된 타입이 들어올 수 있는 것을 컴파일 단계에서 방지할 수 있다.
- 클래스 외부에서 타입을 지정해 주기 때문에 따로 체크를 하고 형변환을 해줄 필요가 없다. (관리가 편하다)
- 비슷한 기능을 지원하는 경우 코드의 재사용성이 높아진다.
자주 사용되는 타입 인자
- <T> : Type
- <E> : Element
- <K> : Key
- <V> : Value
- <N> : Number
- <R> : Result
Generic 클래스/인터페이스
// 제네릭 클래스
class GenericClass<T> {
private T t;
public void setT(T t) {
this.t = t;
}
public T getT() {
return t;
}
}
// 제네릭 인터페이스
interface GenericInterface<T> {
T sample();
}
class sampleClass extends GenericInterface<String> {
@Override
public String sample() {
return "sample";
}
}
인터페이스나 클래스를 설계할 때 구체적인 타입을 명시하지 않고 타입 파라미터로 넣어두었다가 실제 설계한 클래스나 인터페이스를 사용될 때 new GenericClass<String>(); 과 같은 방법으로 구체적인 타입을 지정해서 사용하면 타입 변환을 최소화하여 사용할 수 있고 재사용성이 높아진다.
static 메서드
제네릭 타입은 객체 생성 시에 정해지는데 static은 객체 생성에 참여하므로 제네릭 타입을 쓸 수 없다.
그래서 static과 반환타입 사이에 제네릭 타입을 붙여준다.
public static <T> void test(T t) {
System.out.println(t.toString);
}
public static <A extends Number> E test(A number1, A number2) {
return Math.max(number1.doubleValue(), number2.doubleValue());
}
제한된 제네릭, 와일드카드
제네릭은 참조 타입이 어떤 것이든 다 가능한데, 만약 특정 범위를 제한해서 사용하고 싶으면 extends, super와 같이 와일드카드를 사용한다.
다음과 같은 클래스들의 상속관계가 있다고 가정해 보자
<? extends 상위타입>
상위타입을 포함한 자식(자손)의 클래스만 가능하다는 뜻이다.
<T extends B> // B,C 가능
<T extends A> // A,B,C,D,E 가능
<T extends E> // E 가능
<? extends B> // B,C 가능
<? extends A> // A,B,C,D,E 가능
<? extends E> // E 가능
<? super 하위타입>
하위 타입을 포함한 부모(조상)의 클래스만 가능하다는 뜻이다.
<T super B> // A,B 가능
<T super A> // A 가능
<T super E> // A,D,E 가능
<? super B> // A,B 가능
<? super A> // A 가능
<? super E> // A,D,E 가능
<?> : 와일드카드
말 그대로 와일드카드로서 타입 파라미터를 대치하는 것으로 모든 클래스나 인터페이스가 가능하다.
<? extends Object>와 같은 의미이며 Object객체는 자바에서의 모든 API 및 사용자 클래스의 최상위 타입이다.
이는 보통 데이터가 아닌 '기능'의 사용에 초점을 맞출 때 주로 사용된다.
실전
Q. 자바의 제네릭에 대해 설명해 주세요.
A. 제네릭은 데이터 타입을 내부에서 지정하는 것이 아닌 외부에서 사용자에 의해 지정되는 것을 말합니다. 다이아몬드 표기법으로 지정하며, 클래스나 인터페이스만 가능합니다. 기본 자료형은 데이터 타입으로 올 수 없기 때문에 int 대신에 Integer와 같은 참조 자료형으로 사용해야 합니다. 제네릭을 사용할 때의 장점으로는 잘못된 타입이 오는 것을 컴파일 과정에서 미리 방지할 수 있고, 따로 형변환을 해주거나 확인을 해주지 않아도 돼서 관리가 편합니다. 또한 타입 파라미터로 여러 타입이 가능하므로 코드의 재사용성 또한 높아집니다.
제네릭의 타입 파라미터는 extends나 super를 통해서 제한된 제네릭으로 사용할 수도 있습니다. 예를 들어 <T extends Number>를 사용하게 되면 Integer나 Double과 같은 자료형만 사용이 가능하며 String이 사용될 경우 오류를 발생합니다.
참조
https://st-lab.tistory.com/153
https://hahahoho5915.tistory.com/69#%EC%A-%-C%EB%--%A-%EB%A-%AD%--%ED%--%B-%EB%-E%--%EC%-A%A-
'멋진 개발자 > Java & Spring' 카테고리의 다른 글
개발자 취준 기록 35 - 추상클래스와 인터페이스의 차이 (0) | 2024.03.30 |
---|---|
개발자 취준 기록 34 - Hash(Table·Map·Set) (0) | 2024.03.28 |
[항해 취업코스] 개발자 취준 기록 19 - Filter, Interceptor, AOP (0) | 2024.03.13 |
[항해 취업코스] 개발자 취준 기록 18 - Spring bean container의 생명주기 (0) | 2024.03.12 |
[항해 취업코스] 개발자 취준 기록 17 - 즉시로딩, 지연로딩 (3) | 2024.03.12 |