자바 제너릭

J/Java 2014. 3. 16. 22:14

public static <T, U> T[] copyOf()의 해석

아래의 소스는 java.util.Arrays 클래스의 메소드 중 하나.

<T, U> T[]의 의미는 무엇인가? T라는 클래스가 존재한다면 무슨 용도인가?

 

제너릭의 정의

JDK 5.0에서는 GENERIC이 포함되어 실행전 컴파일 단계에서 특정 Collection에 프로그래머가 원하는 객체 타입을 명시하여 명시된 객체가 아니면 절대 저장이 안되게 할 수 있습니다.

Generic Type은 꺽쇠(<>) 사이에 컴파일 할 당시 사용될 객체를 적어 놓으면 객체를 저장할 때 제너릭 타입으로 저장됩니다.

API에서 전달되는 객체가 현 객체 내에서 하나의 자료형으로 쓰일 때는 <T>로 유도하며 전달되는 객체가 현 객체 내에서 하나의 요소로 자리 잡을 때는 <E>, 그리고 Key값으로 사용될 때는 <K>로, Value값으로 사용 될 때는 <V>로 표현하고 있습니다.

 

ex) public class GenericClass<T>{

T[] v;

public void set(T[] n){ v = n; }

public void print(){ for(T s : v){ out.println(s); }}

}

 

public class GenericTest{

public static void main(String[] args){

GenericClass<String> t = new GenericClass<String>();

String[] s = {"가", "나", "다"};

t.set(s);

t.print();

}

}

 

public static <T, U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType){

T[] copy = ((Object)newType == (Object)Object[].class)?

(T[])new Object[newLength] : (T[])Array.newInstance(newType.getComponentType(), newLength);

System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));

return copy;

}

 

제너릭스의 범위 설정

Generic

 

제네릭스 <E>는 모든 형태를 받을 수 있지만, 의도적으로 상속 관계를 기준으로 들어올 수 있는 클래스 범위를 지정 할 수 있다.

super는 하한선이고

extends는 상한선이다.

<T extends Comparable<T>>이와 같이 제네릭스의 영역을 설정하면

T로 들어올 수 있는 값은 extends(하한선)에 의해

Comparable<T> 클래스이거나 그 자식(상속받은) 클래스이어야 한다.

<T super Vector> 이와 같은 제네릭스를 설정하면

T로 들어올 수 있는 값은 super (상한선)에 의해 Vector 클래스이거나 그 조상 클래스이어야 한다.

(조상 클래스가 들어왔는데 Vector가 조상클래스의 자손인지 확인하는 방법은 아마 instanceof )

 

이와 같이 범위 제한은, 클래스 앞 부분 혹은 메소드 앞 부분에 정의한다.

// 메소드 앞부분에 정의

static <T extends Comparable<T>> void swap(T[] array, int a, int b){

T temp = array[a]; array[a] = array[b]; array[b] = temp;

}

 

// 클래스 앞 부분 정의

class Demo<T super Study>

 

private A[] element  = A[aSize]; 라고 선언

그러나 5.0 이상에서는 "generic array creation" 이라는 에러로 처리.

이유는 자바 소드 코드의 제네릭 자료형이 컴파일 시 까지만 존재하고 실제 컴파일 된 바이트 코드에는 존재하지 않기 때문에 실행시간에 해당하는 제네릭 자료형의 인스턴스를 만드는 것을 원칙적으로 불가능.

그래서 제네릭 자료형의 배열도 생성할 수 없다.

 

제네릭스 와일드 카드 ?라는 말에서 알 수 있듯이 어떠한 값도 맏을 수 있는 제네릭 자료형을 의미한다.

와일드 카드는 "?" 문자로 표시.

예를 들면 List<?> list  = new ArrayList<String>(); 에서 list 인스턴스 변수는 String 값과 Integer 값 모두를 받을 수 있다.

상속 계층 구조상의 경계도 지정이 가능하단다. 이를 위해 super, extends 라는 두 예약어를 사용한다.

 

List<? extends Number> List<? super Integer>

extends를 사용하는 와일드 카드는 흔히 와일드 카드의 하한을 지정한다고 하는 데.

그 말은 extends 다음에 나오는 클래스를 포함하여 그 자식 클래스들이 제네릭 자료형으로 올 수 있음을 나타낸다.

super를 사용하는 와일드 카드는 그 반대로 와일드 카드의 상한을 지정하는 데, 그의미는 super 다음에 나오는 클래스를 포함하여 그 부모 클래스들이 제네릭 자료형으로 올 수 있음을 나타낸다.

 

 

설정

트랙백

댓글