0%

200813 TIL

Generics

  • 대상 객체의 타입을 입력 받아서 사용하는 방식
  • 미리 사용할 수 있는 타입을 명시해서 컴파일 타임에 체크 가능
    • 입력을 Object로 할 수도 있으나, runtime에 instanceof 로 객체를 체크 해야 함
    • 제네릭을 사용할 경우 이러한 과정 없이 간결하게 코드 작성을 할 수 있다.

Generic Class

  • 클래스를 선언 할때는 설정되지 않은 타입이 있으며 이것을 타입 파라미터로 표현
1
2
3
4
5
6
7
8
9
class GenericFoo<T> { // T: type parameter
String name;
T memberVar;

public GenericFoo(String name, T memberVar) {
this.name = name;
this.memberVar = memberVar;
}
}
  • 여러개의 타입 파라미터 또한 가능
1
2
3
class HashMap<K,V> {

}
  • 인터페이스도 generic이 가능하다.
1
2
3
interface GenericInterface<T> {

}
  • Geneirc type 사용시 유의점

    • 문법적으로 문제가 있는 경우

      1
      2
      3
      4
      class Generic<T> {
      static T classVar; // -> T는 객체를 생성할 때 결정 되기 때문에 complie time에 T를 알 수 없다.
      static void mehtod(T varl) { } // 마찬가지 이유로 complie time에 T를 알 수 없음
      }
    • 문법적으로는 문제가 없을 것 같으나, 안정성 문제로 금지됨 -> 암기 요소

      1. Type parameter 의 instance를 생성하는 것은 불가능하다.
      2. Generic type parameter 에 대한 instance checking은 불가능하다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Generic<T> {
    T memberVar = new T(); // -> 안정성 문제 때문에 불가능
    {
    Object obj = new Object();
    if (obj instanceof T) { // not possible instance 체크 불가능

    }
    }
    }

Inheritance of Generic Type

  • 타입 파라미터는 부모 제네릭 타입 파라미터를 모두 채워줘야 함
  • 추가적인 타입 파라미터도 사용할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
class GFoo<T> {

}

interface IGFoo<D> {

}

class IGIFooTwo<K, T, D> extents GFoo<T> implements IGFoo<D> {

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

}
  • 타입 제한을 하지 않으면 extends Object와 동일하다.
1
class GenericNoTypeLimit<T extends Object> {}
  • extends를 이용해서 부모 클래스를 제한 할 수 있다.
1
2
                                                // interface upper limit
class GenericTypeLimitation<T extends Number & Clonable> {}

Generic Method

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class GenericMethod {
public static <T> T staticMethod(T t) {
return t;
}
public int method(int x) {
return x;
}
public <T> T method(int x) {
return x;
}
public <T> T method(T x) {
return x;
}
}

Wild Card

  • Wild Card ? 는 method 의 입력 타입에 Generic 이 쓰일 경우, Generic 의 타입 변수를 제한 할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class WildFoo {

}

class WildBar extends WildFoo {

}

class WildGeneric<T> {

}

class WildCard {
public <T> void method(WildGeneric<T> x) {}
public void mehtod1(WildGeneric<?> x) {} // T, ?의 차이점: super 키워드를 사용하여 상한을 정할 수 있다.
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, 하한
}

Dynamic Binding: JIT Complie

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class GenericMethod {
public static <T> T staticMethod(T t) {
return t;
}
public int method(int x) {
return x;
}
public <T> T method(int x) {
return x;
}
public <T> T method(T x) {
return x;
}
}

public class Generics {
public static void main(String[] args) {
// Dynamic binding: behavior of method defined on runtim with JIT complication
GenericMethod.staticMethod("abcde");
GenericMethod.staticMethod(12345);
}
}

Wrapper Class

  • 기본형 타입을 객체로 쓰기 위해 있는 클래스
  • 기본형 타입이 허용되지 않는 문법에 기본형 타입을 쓰기 위해서 제공
1
2
3
4
5
public static Integer add(Integer x, Integer y) {
return x + y;
// 자동으로 기본 자료형으로 변형 및 계산
// 반환시 다시 Autoboxing이 이루어짐
}
  • 여러가지 선언 방법들
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Integer integer = new Integer(10);
Interger integer1 = Integer.valueOf(10);

Charactor character = new Character('d');
Charactor character1 = Character.value('f');

// Autoboxing
Integer integer2 = 4;

// 문자열 <-> 기본자료형
int x = Integer.parseInt("100");
int y = new Integer("100");
int z = Integer.valueOf("200");

int m = new Integer(10); // 기본 자료형이 필요한 자리에 Wrapper class가 있을 경우 unboxing이 일어난다