Coding/Java

Java Generic(제네릭)

heyoon2j 2020. 9. 17. 14:50

■ Java Generic(제네릭)

- 대상 객체의 타입을 입력받아서 사용하는 형식

- 미리 사용할 수 있는 타입을 명시해서 컴파일 타임에 체크 가능

  • 입력을 Object로 입력받아, Casting을 런타임에 instanceof로 객체로 체크를 할 수 있지만, 비효율적으로 코드를 작성하게 된다.
  • 제네릭을 사용할 경우 이러한 과정없이 간결하게 코드를 작성할 수 있다.

1. 제네릭 클래스 (Generic Class)

• 클래스 선언 시, 설정되지 않은 타입을 타입 파라미터로 표현

 

class GenericFoo<T> {   // T: 타입 파라미터
    String name;
    T memberVar;

    GenericFoo(String name, T memberVar){
        this.name = name;
        this.memberVar = memberVar;
    }
}    

 

• 제네릭 인터페이스도 제네릭 클래스와 동일하게 표현

interface GenericInterface<T> { 
      ...
}

 

• 여러 개의 타입 파라미터를 사용할 수 있다

class HashMap<K, V> {
      ...
}

 

• 제네릭 클래스와 static 관계

- new 연산자instanceof를 사용할 수 없다.

class GenericBar<T> {
    // static T classVar;             // not possible, 클래스 영역이기 때문에, 객체 생성 이전에 메모리에 상주해야 되므로
    // static void method(T var){ }   // not possible, T가 객체를 생성해야 정해지므로, 호출이 불가능하다

    // T memberVar = new T();   // not possible
    // 안정성 문제 때문에(T가 어떤 것이 올지 모름) 위험하다.
    // new 연산자의 경우, 컴파일 단계에서 타입을 이용해서 Heap 영역에 충분한 공간이 있는지 확인을 하게 되늗데
    // 여기서는 그렇게 하지 못하기 때문에 에러가 발생한다.
    // Reference: https://yaboong.github.io/java/2019/01/19/java-generics-1/
    /*
    {
        Object obj = new Object();
        if(obj instanceof T){   // not Possible, T가 될 수 있는 값이 너무 많기 때문에

        }
    }
    */
}    

 


2. 제네릭 상속 (Generic Inheritance)

 

class GFoo<T> {
      ...
}

interface IGFoo<D>{
      ...
}  

// 추가적인 타입 파라미터도 사용할 수 있다.
class GIGFoo<N, T, D> extends GFoo<T> implements IGFoo<D>{
      ...
}

// 부모 클래스, 인터페이스들에 동일한 타입 파라미터를 넘겨줄 수 있다.
class IGIFooTwo<T> extends GFoo<T> implements IGFoo<T>{
      ...
}

 


3. 제네릭 메소드 (Generic Method)

- 메소드 앞에 타입 파라미터를 써준다.

- 제네릭 클래스와 다르게 static generic method가 가능한 이유는 함수 호출 시에는 타입이 결정되기 때문이다.

class GenericMethod<P> {
    public static <T> T staticMethod(T t){
        return t;
    }

    public static int method(P x){		// Error
        return x;
    }

    public <T> T method(T x){
        return x;
    }
}

 


4. 타입 제한

• extends 키워드를 사용하여 부모 클래스를 제한

 - &를 이용하여 동시 제약을 할 수 있다.

// 타입 제한을 하지 않으면 extends Object와 동일하다.
class GenericNoTypeLimit<T extends Object>{}

// 제한한 클래스의 상위 클래스를 사용할 수 없다. Number와 Cloneable 하위 클래스
class GenericTypeLimitation<T extends Number & Cloneable>{

}

 

• 와일드카드

  • <?> (== <? extends Object>) 서로 동일
  • <? extends T> : 와일드카드의 상한을 제한, T Class와 하위 클래스 가능
  • <? super T> : 와일드 카드의 하한을 제한, T Class와 상위 클래스 가능
class WildFoo {
      ...    
}

class WildBar extends WildFoo{
      ...
}

class WildGeneric<T> {
          
}

class WildCar {
    public <T extends Object> void method1_2(WildGeneric<T> x) {}   // T와 ? 차이는 super 쓰냐 못 쓰냐이다.
    public void method1(WildGeneric<?> x) {}
    public void method1_eq(WildGeneric<? extends Object> x) {}      // Object가 상한 -> 모든 객체
    public void method2(WildGeneric<? extends WildFoo> x) {}        // WildFoo, WildBar
    public void method3(WildGeneric<? super WildBar> x) {}          // Object, WildFoo, WildBar
}

 

 

 

'Coding > Java' 카테고리의 다른 글

Java Inner Class(내부 클래스)  (0) 2020.09.18
Java Handling Exception(예외 처리)  (0) 2020.09.17
Java Enumeration(열거형)  (0) 2020.09.17
Java Abstract Class & Interface  (0) 2020.09.17
Java Polymorphism(다형성)  (0) 2020.09.17