HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
🌚
[New] 우기팀
/
득윤
득윤
/
❓
Java Generic
/
7️⃣
제네릭의 제한사항
7️⃣

제네릭의 제한사항

제네릭의 제한사항 Restrictions on Generics


1. primitive types 로 제네릭 타입을 인스턴스화 할 수 없다.

List<int> intList; //not allowed! -> List<Integer> integerList; //allowed!
원시 타입을 제네릭에 사용하고 싶다면 래퍼 클래스를 활용해야 한다.(Wrapper Class)
Primitive type
Wrapper class
boolean
Boolean
byte
Byte
char
Character
float
Float
int
Integer
long
Long
short
Short
double
Double

2. 타입 파라미터의 인스턴스를 인스턴스화 할 수 없다.

public static <E> void append(List<E> list) { E elem = new E(); // compile-time error list.add(elem); }
 
제네릭 메서드 append 에서 타입 파라미터 E 의 인스턴스를 new 연산자를 통해 생성할 수 없다.
대안으로 메서드 파라미터로 타입 파라미터의 클래스 정보 Class<E> 를 전달 받아 리플렉션 기술을 활용할 수 있다.
public static <E> void append(List<E> list, Class<E> cls) throws Exception { E elem = cls.newInstance(); // OK list.add(elem); }
 

3. 타입 파라미터의 타입으로 스태틱 필드를 정의할 수 없다.

마찬가지로 스태틱 메서드에서도 제네릭 타입의 타입 파라미터를 활용할 수 없다. (당연히 제네릭 메서드의 타입 파라미터는 활용 할 수 있음)
class MobileDevice<T> { static T os; // compile-time error // ... }
‘MobileDevice.this' cannot be referenced from a static context
이는 스태틱의 의미를 생각해보면 당연한 제약이다.

4. Parameterized Types에 캐스팅이나 instanceof 연산자를 적용할 수 없다.

instanceof
public static <E> void rtti(List<E> list) { if (list instanceof ArrayList<Integer>) { // compile-time error // ... } }
Illegal generic type for instanceof
컴파일 과정에서 컴파일러는 제네릭의 타입 정보를 모두 제거하기 때문에 (Type Erasure) 전달받은 list 인자가 ArrayList 인지는 구분할 수 있지만 ArrayList<Integer> 인지 ArrayList<String>인지 구분할 수 없다.
 
제네릭 타입을 포함한 강력한 타입체킹에 대한 정보는 Super Type Token이라는 키워드로 찾아보자
@See Also) 토비의 봄 TV 2회 - 수퍼 타입 토큰
 
Super Type Token을 도입하지 않고 간단하게 list 인자가 ArrayList 인지만 구분하는 가장 좋은 방법은 unbounded wildcard 를 사용하는 것이다.
public static void rtti(List<?> list) { if (list instanceof ArrayList<?>) { // OK; instanceof requires a reifiable type // ... } }
 
캐스팅
List<Integer> li = new ArrayList<>(); List<Number> ln = (List<Number>) li; // compile-time error
List<String> l1 = ...; ArrayList<String> l2 = (ArrayList<String>)l1; // OK

5. 제네릭 타입의 배열을 생성할 수 없음

List<Integer>[] arrayOfLists = new List<Integer>[2]; // compile-time error
 

  1. 제네릭 타입을 예외 처리에 활용하는 것은 제한됨
 
  • 제네릭 클래스는 Throwable 클래스를 상속할 수 없음
    • class MathException<T> extends Exception { } // compile-time error
  • 타입 파라미터가 Throwable을 상속했다고 해도 이를 catch 할 수 없음
  • 하지만 타입 파라미터가 Throwable 을 상속했다면 throws할 수는 있음

 
  1. 메서드 오버로딩은 타입 이레이져 적용 이후를 기준으로 함
즉 제네릭 타입을 인자로 받거나, 제네릭 메서드를 사용하며 메서드 내에서 타입 파라미터를 정의 하더라도 이를 모두 제거한 메서드 시그니처만을 기준으로 오버로딩을 판단함
public class Example { public void print(Set<String> strSet) { } //compile-time error public void print(Set<Integer> intSet) { } //compile-time error }