(1) 리플렉션 + 제네릭과 관련된 인터페이스 유형.
java.lang.reflect.Type: Java 언어의 모든 유형에 대한 공통 상위 인터페이스
java.lang.reflect.ParameterizedType
java.lang.reflect.GenericArrayType
java.lang.reflect.WildcardType
1. 직접 하위 인터페이스 입력
네 가지 유형의 인터페이스: ParameterizedType, GenericArrayType, TypeVariable 및 WildcardType
ParameterizedType: 컬렉션과 같은 매개변수화된 유형을 나타냅니다.
GenericArrayType: 요소 유형이 매개변수화된 유형 또는 유형 변수인 배열 유형을 나타냅니다.
TypeVariable: 다양한 유형의 변수에 대한 공통 상위 인터페이스입니다.
WildcardType: ?, ? 확장 숫자, ? super Integer와 같은 와일드카드 유형 표현을 나타냅니다. [와일드카드는 단어입니다: "와일드카드"입니다.
2. 유형은 하위 클래스를 직접 구현합니다. 클래스 클래스
3. java.lang.reflect.Type 인터페이스
Type의 모든 유형은 원시 유형(raw 유형) [Class에 해당], 매개변수화된 유형(매개변수화된 유형) [ParameterizedType에 해당], 배열 유형(배열 유형) [GenericArrayType에 해당], 유형 변수(유형 변수) [ TypeVariable 에 해당], 기본 데이터 유형(기본 유형) [여전히 Class에 해당]
4. java.lang.reflect.ParameterizedType 인터페이스
ParameterizedType 인터페이스 유형의 의미
매개변수화된 유형을 나타냅니다. 예: Map과 같은 매개변수화된 유형
매개변수화된 유형<>에서 실제 유형을 가져옵니다.
소스 코드 설명: Type[] getActualTypeArguments();
[참고] <>에 중첩된 <> 수준이 아무리 많아도 이 메서드는 가장 바깥쪽 <>만 제거하고 나머지 내용은 이 메서드의 반환 값으로 사용됩니다.
공개 정적 E 방법IV(
배열목록> al1,
배열목록 al2,
배열목록 al3,
ArrayListextends 번호> al4,
ArrayList al5){}
그러면 각 매개변수는 일반적으로 파라메트릭 유형입니다.
{1}. ArrayList>의 경우 getActualTypeArguments()를 통해 반환된 후 가장 바깥쪽의 <>를 제거한 후 남은 유형은 ArrayList입니다. 따라서 이 매개변수의 반환 유형은 ParameterizedType입니다.
{2}. ArrayList의 경우 getActualTypeArguments()를 통해 반환한 후 가장 바깥쪽 <>을 제거한 후 남은 유형은 E입니다. 따라서 이 매개변수의 반환 유형은 TypeVariable입니다.
{3}. ArrayList의 경우 getActualTypeArguments()를 통해 반환한 후 가장 바깥쪽 <>을 제거한 후 남은 유형은 String입니다. 따라서 이 매개변수의 반환 유형은 Class입니다.
{4}. ArrayListextends Number>의 경우 getActualTypeArguments()를 통해 반환된 후 가장 바깥쪽의 <>를 제거한 후 남은 유형은? 따라서 이 매개변수의 반환 유형은 WildcardType입니다.
{5}. ArrayList의 경우 getActualTypeArguments()를 통해 반환한 후 가장 바깥쪽 <>을 제거한 후 남은 유형은 E[]입니다. 따라서 이 매개변수의 반환 유형은 GenericArrayType입니다.
따라서 다양한 타입의 실제 매개변수를 얻을 수 있으므로 통일성을 위해 직계 부모 클래스 배열인 Type[]을 사용하여 수신한다.
4. java.lang.reflect.GenericArrayType 인터페이스
GenericArrayType 인터페이스 유형의 의미
일반 배열 유형을 나타냅니다. 예: void method(ArrayList[] al){…}
[참고] <>는 배열 초기화에 나타날 수 없습니다. 즉, <>는 새 배열 뒤에 나타날 수 없습니다. 그렇지 않으면 javac가 통과하지 못합니다. 하지만 참조 변수나 메소드의 매개변수로는 전혀 문제가 없습니다.
일반 배열의 요소 유형 가져오기
소스 코드 선언: Type getGenericComponentType();
[참고] 이 메서드는 왼쪽에서 오른쪽으로 몇 개의 []를 병치하더라도 가장 오른쪽의 []만 제거하고 나머지 내용은 이 메서드의 반환 값으로 사용됩니다.
반환 값 유형이 Type인 이유는 무엇입니까?
공개 정적 E 메소드V(String[] p1,E[] p2,ArrayList[] p3,E[][] p4){}{1}. String[]의 경우 getComponentType()을 통해 반환한 후 가장 오른쪽의 []를 제거한 후 남은 유형은 String입니다. 따라서 이 매개변수의 반환 유형은 Class입니다.
{2}. E[]의 경우 getComponentType()을 통해 반환한 후 가장 오른쪽의 []를 제거한 후 남은 유형은 E입니다. 따라서 이 매개변수의 반환 유형은 TypeVariable입니다.
{3}. ArrayList[]의 경우 getComponentType()을 통해 반환한 후 가장 오른쪽의 []를 제거한 후 남은 유형은 ArrayList입니다. 따라서 이 매개변수의 반환 유형은 ParameterizedType입니다.
{4}. E[][]의 경우 getComponentType()을 통해 반환한 후 가장 오른쪽의 []를 제거한 후 남은 유형은 E[]입니다. 따라서 이 매개변수의 반환 유형은 GenericArrayType입니다.
5. java.lang.reflect.GenericArrayType 인터페이스
TypeVariable 인터페이스 유형의 의미
유형 매개변수를 나타내거나 유형 변수라고도 합니다. 예: void method(E e){}의 E는 유형 변수입니다.
유형 변수의 일반 한정 상한 유형을 가져옵니다.
소스 코드 설명: Type[] getActualTypeArguments();
[참고] 이는 단지 상한선일 뿐입니다. 그 이유는 유형 변수가 정의될 때 제한(다중) 경계에만 확장을 사용할 수 있기 때문입니다. Super를 사용할 수 없습니다. 그렇지 않으면 컴파일이 통과되지 않습니다. 동시에, 확장은 유형 변수의 상한을 제공합니다.
반환 유형이 배열인 이유는 무엇입니까? 유형 변수는 &를 사용하여 여러 상한으로 한정될 수 있으므로 상한이 여러 개 있으므로 반환 값 유형은 배열 유형 []입니다.
예를 들어 다음 방법을 사용하세요.
공개 정적 확장 맵& 복제 가능&직렬화 가능> E 메소드VI(E e){...}E의 첫 번째 상위 경계는 ParameterizedType 유형인 Map입니다.
E의 두 번째 상위 경계는 Cloneable이며 Class 유형입니다.
따라서 통일을 위해 반환 값 배열의 요소 유형은 Type
6. java.lang.reflect.WildcardType 인터페이스
WildcardType 인터페이스 유형의 의미
와일드카드 유형을 나타내는 표현식입니다.
예를 들어 void printColl(ArrayListal)은 ?
[참고] 위 API의 설명에 따르면 이 단계에서 와일드카드 표현식은 상한 또는 하한만 허용합니다. 이는 여러 상한을 지정할 수 있는 유형 변수를 정의할 때와 다릅니다. 그런데 API에서는 확장성을 유지하기 위해 여기서 반환값 형식을 배열 형태로 작성한다고 합니다. 실제로 지금 반환되는 배열의 크기는 1입니다.
와일드카드 표현식 객체의 일반 한정 상한 유형을 가져옵니다.
소스 코드 설명: Type[] getUpperBounds();
[참고] 위에서 언급했듯이 이 단계에서 반환되는 Type[]의 배열 크기는 1입니다. Type[ ]으로 작성하는 것은 언어 업그레이드를 위한 확장입니다.
예를 들어 다음 방법을 사용하세요.
{1}. 공개 정적 voidprintColl(ArrayListextends ArrayList> al){}
와일드카드 표현식은 ?extendsArrayList입니다. 따라서 확장 뒤에는 ?의 상위 경계가 오고 이 상위 경계는 ParameterizedType 유형입니다.
{2}. 공개 정적 voidprintColl(ArrayListextends E> al){}
와일드카드 표현식은 다음과 같습니다. ?는 E를 확장하므로 확장 뒤에는 ?의 상한 경계가 오고 이 상한은 TypeVariable 유형입니다.
{3}.public static voidprintColl(ArrayListextends E[]> al){}
와일드카드 표현식은 다음과 같습니다. ?는 E[]를 확장하므로 확장 뒤에는 ?의 상한이 오고 이 상한은 GenericArrayType 유형입니다.
{4}.public static voidprintColl(ArrayListextends Number> al){}
와일드카드 표현식은 다음과 같습니다. ?는 Number를 확장하므로 확장 뒤에는 ?의 상한이 오고 이 상한은 클래스 유형입니다.
마지막으로 배열의 요소 유형을 Type으로 통합했습니다.
7. Type과 해당 하위 인터페이스의 유래
1. 제네릭 출현 이전의 유형
제네릭이 없으면 소위 기본 유형만 있습니다. 이때 모든 기본 유형은 바이트코드 파일 클래스 Class 클래스를 통해 추상화됩니다. Class 클래스의 구체적인 객체는 지정된 기본 유형을 나타냅니다.
2. 제네릭 출현 이후의 유형
제네릭이 등장한 후 데이터 유형이 확장되었습니다. 기본 유형부터 매개변수화된 유형, 유형 변수 유형, 일반 한정 매개변수 유형(와일드카드 + 와일드카드 한정 표현식 포함) 및 일반 배열 유형이 확장되었습니다.
3. 제네릭 관련 타입을 원본 타입과 클래스로 통합할 수 없는 이유
[1]. [일반 삭제 원인]
원래 새로 생성된 유형 + 기본 유형은 각각의 바이트코드 파일 유형 객체로 통합되어야 합니다. 그러나 제네릭은 원래 Java의 구성 요소가 아니었기 때문입니다. 제네릭이 실제로 추가되면 JVM 명령어 세트의 수정이 포함되며 이는 매우 치명적입니다.
[2]. [Java에서 제네릭을 도입하는 방법]
제네릭을 실제로 도입하지 않고 활용하기 위해 Java는 제네릭 삭제 메커니즘을 사용하여 제네릭을 도입합니다. Java의 제네릭은 데이터 보안을 보장하고 강제 유형 변환 문제를 방지하기 위해 컴파일러 javac에서만 사용됩니다. 그러나 컴파일이 완료되면 제네릭과 관련된 모든 유형이 지워집니다.
[3]. [클래스는 제네릭과 관련된 유형을 표현할 수 없습니다.]
따라서 제네릭과 관련된 매개변수 유형, 유형 변수 유형, 제네릭 한정 매개변수 유형(와일드카드 + 와일드카드 한정 표현식 포함), 일반 배열 유형은 모두 원래 형식으로 반환되어 바이트코드 파일에 저장됩니다. 제네릭이 지워진 후 자체 유형과 일치하는 바이트코드 파일이 없습니다. 따라서 제네릭과 관련된 새로 확장된 유형은 Class 클래스로 통합될 수 없습니다.
(4) Java의 제네릭 관련 유형 표현.
이러한 타입을 실제 개발 요구에 맞게 리플렉션을 통해 운용하기 위해 Java에서는 Class 클래스로 분류할 수 없지만 원래 타입과 이름이 같은 타입을 나타내기 위해 ParameterizedType, GenericArrayType, TypeVariable 및 WildcardType을 추가했습니다.
(5) 타입 소개: 제네릭과 프리미티브 타입 관련 타입을 통합한 클래스.
[타입 도입 이유]
프로그램의 확장성을 위해 마침내 Type 인터페이스가 Class, ParameterizedType, GenericArrayType, TypeVariable 및 WildcardType에 대한 일반적인 상위 인터페이스로 도입되었습니다. 이런 방식으로 Type 유형 매개변수는 위의 5개 하위 유형의 실제 매개변수를 허용하거나 반환 값 유형은 Type 유형 매개변수입니다.
[Type 인터페이스에 메소드가 없는 이유]
위에서 알 수 있듯이 Type의 출현은 다형성을 통해 프로그램 확장성을 향상시키는 역할만 할 뿐, 다른 효과는 없습니다. 따라서 Type 인터페이스의 소스 코드에는 메서드가 없습니다.