답변:
Java의 제네릭은 완전히 컴파일 타임 구조입니다. 컴파일러는 모든 일반적인 용도를 올바른 유형으로 캐스트합니다. 이는 이전 JVM 런타임과의 호환성을 유지하기위한 것입니다.
이:
List<ClassA> list = new ArrayList<ClassA>();
list.add(new ClassA());
ClassA a = list.get(0);
(대략)으로 변합니다.
List list = new ArrayList();
list.add(new ClassA());
ClassA a = (ClassA)list.get(0);
따라서 제네릭으로 사용되는 모든 항목은 Object로 변환 가능해야하며 (이 예제에서는을 get(0)
반환 Object
) 기본 유형은 그렇지 않습니다. 따라서 제네릭에는 사용할 수 없습니다.
언어가 설계 한 후 그들이 년의 언어에 번호를 추가 되었기 때문에 자바에서 제네릭는 ... 적어도 부분적으로 ... 그들이하는 방식으로 작동 1 . 언어 설계자들은 기존 언어 및 Java 클래스 라이브러리와 역 호환되는 디자인을 제안함으로써 제네릭 옵션에 제약 을 받았다 .
다른 프로그래밍 언어 (예 : C ++, C #, Ada)에서는 기본 유형을 제네릭의 매개 변수 유형으로 사용할 수 있습니다. 그러나 이런 일을하는 것의 단점은 그러한 언어의 제네릭 (또는 템플릿 타입) 구현은 일반적으로 각 타입 파라미터 화를위한 제네릭 타입의 별개의 사본을 생성한다는 점입니다.
1-제네릭이 Java 1.0에 포함되지 않은 이유는 시간 압력 때문이었습니다. 그들은 웹 브라우저가 제공하는 새로운 시장 기회를 채우기 위해 Java 언어를 신속하게 출시해야한다고 생각했습니다. 제임스 고슬링은 시간이 있었다면 제네릭을 포함하고 싶었다고 말했다. 이것이 일어난다면 Java 언어는 어떤 사람의 추측 일 것입니다.
자바에서 제네릭은 이전 버전과의 호환성을 위해 "Type erasure"를 사용하여 구현됩니다. 모든 제네릭 형식은 런타임에 Object로 변환됩니다. 예를 들어
public class Container<T> {
private T data;
public T getData() {
return data;
}
}
런타임에 다음과 같이 볼 수 있습니다.
public class Container {
private Object data;
public Object getData() {
return data;
}
}
컴파일러는 형식 안전성을 보장하기 위해 적절한 캐스트를 제공해야합니다.
Container<Integer> val = new Container<Integer>();
Integer data = val.getData()
될 것입니다
Container val = new Container();
Integer data = (Integer) val.getData()
이제 "Object"가 런타임에 유형으로 선택되는 이유는 무엇입니까?
Answer is Object 는 모든 객체의 수퍼 클래스이며 모든 사용자 정의 객체를 나타낼 수 있습니다.
모든 프리미티브 는 " Object " 에서 상속받지 않으므로 일반 유형으로 사용할 수 없습니다.
참고 : 프로젝트 Valhalla는 위의 문제를 해결하려고합니다.
컬렉션은에서 파생 된 유형을 요구하도록 정의됩니다 java.lang.Object
. 기본 유형은 단순히 그렇게하지 않습니다.
당으로 자바 문서 , 제네릭 형식의 변수는 참조 유형이 아닌 기본 유형에 인스턴스를 생성 할 수 있습니다.
이것은 프로젝트 Valhalla 에서 Java 10으로 제공됩니다 .
제네릭이 프리미티브에 대해 지원되지 않은 이유에 대한 훌륭한 설명 이 있습니다 . 그리고 향후 Java 릴리스에서 어떻게 구현 될 것인가 .
모든 참조 인스턴스화에 대해 하나의 클래스를 생성하고 기본 인스턴스화를 지원하지 않는 Java의 현재 지우기 구현. (이것은 동종 변환이며 Java의 제네릭이 참조 유형에 대해서만 범위를 지정할 수 있다는 제한은 참조 유형과 원시 유형에 대한 조작에 다른 바이트 코드를 사용하는 JVM의 바이트 코드 세트와 관련하여 동종 변환의 제한에서 비롯됩니다.) 그러나 Java에서 지워진 제네릭은 동작 매개 변수 (일반적인 방법)와 데이터 파라 메트릭 (제네릭 형식의 원시 및 와일드 카드 인스턴스화)을 모두 제공합니다.
...
일반 유형 변수가 바이트 코드에 통합 될 때 경계에서 지워지는 동종 변환 전략이 선택되었습니다. 이는 클래스가 일반인지 여부에 관계없이 동일한 이름을 가진 단일 클래스로 컴파일되며 멤버 서명이 동일한 것을 의미합니다. 컴파일시 타입 안전이 검증되고 일반 타입 시스템에 의해 런타임이 영향을받지 않습니다. 결과적으로 Object는 사용 가능한 가장 일반적인 유형이며 기본 유형으로 확장되지 않기 때문에 제네릭이 참조 유형에서만 작동 할 수 있다는 제한을가했습니다.