JAVA - Generics

TopOfTheHead·2025년 7월 26일

자바 ( JAVA )

목록 보기
9/28

Generics : <Type>
Generic을 통해 컴파일 시점에서 Data Type이 지정되지 않아도, 런타임 시점에서 동적으로 Data Type을 할당하는 기능
JavaType 지정을 강제하지만, Generic을 통해 동적으로 할당 가능
▶ 서로 다른 Class Type에도 범용적으로 재사용 가능한 코드를 작성하기 위해 사용.
런타임 시점에서 클래스 외부에서 Data Type을 지정 시 클래스 내부에서 Generic을 통해 동적으로 Data Type을 지정받음.

Data Type에 의존하지 않으면서 Class 또는 Interface를 구현할 수 있다.
자료형에 의존하지 않으므로 범용(generic)으로 활용가능.

castingboxing / unboxing에 따른 성능 저하를 방지할 수 있음.

angle bracket ( <> ) 라는 template 활용
<> 안에 아무런 문자가 들어가도 상관 없으나 관습적으로 T를 사용

  • Generic참조형 변수만 선언 가능
    NPE 방지와 동시에 타입 추론참조형만 참조 가능하고, 원시형은 참조가 불가능하므로

  • 런타임 시점에서 Data Type을 강제하여 타입 안정성( type safety )을 제공함으로써 Type 별 캐스팅을 통해 발생할 수 있는 문제점을 제거
    Type이 일치하지않아 발생하는 Data Type 문제로부터 자유롭고 안전함 ex ) List<Integer>

  • 클래스<DataType> 참조변수 = new 클래스<>() 가 가능한 이유?
    컴파일러에 의해 참조변수Data Type참조되었기에 생성자 쪽에서 Data Type을 지정하지 않아도, 컴파일러에 의해 타입추론을 통해 Data Type이 자동으로 지정됨
    ▶ 반대 경우로 클래스<> 참조변수 = new 클래스<T>()의 경우는 참조변수Data Type컴파일러가 확인할 수 없으므로 성립되지 않는다.

  • Object 클래스를 통해 범용성을 확보하지 않는 이유?
    Object 클래스최상위 부모 클래스이므로, 모든 ClassUpcasting 할 수 있으므로, 범용성이 확보되는 특징이 존재.

    。하지만, 타입 확정하지 않으므로, 요구되는 클래스와 전혀 다른 클래스 객체가 전달되어 예외가 발생할 수 있음.
    Generics를 통한 <T>를 통해 타입안정성을 확보할 수 있다.

Generic 정의
메서드 레벨 / 클래스 레벨에서 Generic을 지정할 수 있음.

  • 클래스Generic 정의하기
    클래스명 <T> {}으로 정의

    Generic을 통해 런타임 시점에서 <Type>을 지정하여 타입 확정 후 사용
    ex ) new 클래스<데이터타입>()에서 Data Type을 확정하여 타입안정성 확보
 public class Stack<T>
  {
      T[] data = new T[5];
  }
  public class Program
  {
      static void Main(string[] args)
      {
    // DataType 지정하여 타입안정성 확보
          Stack<Integer> s1 = new Stack<Integer>(); // 정수형 설정.
          Stack<String> s2 = new Stack<String>(); // 문자열 설정.
      }    
  }

Stack<Integer>를 통해 타입 확정

  • 메서드Generic 정의하기
    메서드에서 Generic을 활용하는 경우 반환 type 앞에 <T>를 지정해야함
public static <T> ApiResult<T> of(String code, String message, T data){
		return new ApiResult<>(code,message,data);
	}

<T> : 해당 메서드에서 Generic을 사용을 위해 명시하는 선언부

매개변수를 쉼표로 구분 시 여러개를 지정 가능
class 클래스이름 < 매개변수1, 매개변수2 , .... >
ex ) JpaRepositoy 인터페이스가 존재

class TwoGen<T,V>
{
  T ob1;
  V ob2;
  public TwoGen(T ob1, V ob2)
  {
      this.ob1 = ob1;
      this.ob2 = ob2;
  }
  public T OB1 { get { return ob1; } }
  public V OB2 { get { return ob2; } }
}
internal class Program
{
  static void Main(string[] args)
  {
      TwoGen<int, string> t1 = new TwoGen<int, string>(150,"hello");
      Console.WriteLine(t1.OB1 + t1.OB2) ;
  }
}

Generic type의 명명규칙
place holder에서 정의하는 규칙
▶ 규칙을 지켜야 컴파일이 되거나 하는건 아니지만 통일성을 위해 규칙을 따르는게 좋다.

<E> : 요소 ( Element )
Collection에서 주로 사용
ex ) ArrayList<E>

<K> : Key

<V> : Value

<N> : Number

<T> : Type

<S>,<U>,<V> : 2 , 3 , 4번째에 선언된 Type.

<?> : Type Wildcard

Type Wildcard : <?>
。어떤 타입이든 올 수 있다는 의미의 unknown type
Genericplaceholder에 지정.
List<?> : 모든 typeList를 의미.
List<?> list1 = new ArrayList<String>();

와일드카드 종류

  • Unbounded Wildcard ( <?> ) :
    。아무 타입이나 상관없이 사용 가능.
    ex ) List<?>

  • 상한 제한 Wildcard ( <? extends T> ) :
    T 또는 T의 전체 하위 Class type만 허용
    읽기 전용으로 주로 활용
    ▶ 값을 읽을 수 있어도 구체적인 type을 모르므로 요소 추가는 불가능

    ex ) List<? extends Number> list = new ArrayList<Integer>(); :
    Number의 하위 TypeNumber , Integer , Double , Float를 허용.

  • 하한 제한 Wildcard ( <? super T> ) :
    T 또는 T의 상위 type만 허용
    쓰기 위주로 주로 사용
    ▶ 요소 값 추가가 가능

    ex ) List<? super Integer> list = new ArrayList<Number>(); :
    Integer의 상위 TypeInteger , Number , Object를 허용

    Producer extends, Consumer super 법칙
    <? extends T> : 데이터 읽기용도로 활용

    <? super T> : 데이터 쓰기용도로 활용
    ex ) Comparator<? super T>는 비교용도로 활용하므로 super 사용

profile
공부기록 블로그

0개의 댓글