(1) リフレクション + ジェネリックスに関連するインターフェイスの種類
java.lang.reflect.Type: Java 言語のすべての型に共通の親インターフェイス
java.lang.reflect.ParameterizedType
java.lang.reflect.GenericArrayType
java.lang.reflect.WildcardType
1. 直接サブインターフェースを入力します
4 種類のインターフェイス: ParameterizedType、GenericArrayType、TypeVariable、および WildcardType
ParameterizedType: Collection などのパラメータ化されたタイプを表します。
GenericArrayType: 要素の型がパラメーター化された型または型変数である配列型を表します。
TypeVariable: さまざまなタイプの変数の共通の親インターフェイスです
WildcardType: ?、? extends Number、? super Integer などのワイルドカード タイプの式を表します [ワイルドカードは単語です: 「ワイルドカード」です]
2. 型はサブクラスを直接実装します: Class クラス
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、
ArrayListtextends 数値 > al4、
ArrayList al5){}
その場合、その各パラメータは通常、パラメトリック タイプになります。
{1}。ArrayList> の場合、getActualTypeArguments() を通じて返された後、最も外側の <> が削除された後、残りの型は ArrayList になります。したがって、このパラメーターの戻り値の型は ParameterizedType です。
{2}。ArrayList の場合、getActualTypeArguments() を介して戻った後、最も外側の <> を削除すると、残りの型は E になります。したがって、このパラメーターの戻り値の型は TypeVariable です。
{3}。ArrayList の場合、getActualTypeArguments() を通じて返された後、最も外側の <> が削除された後、残りの型は String になります。したがって、このパラメータの戻り値の型は Class です。
{4}。ArrayListextends Number> の場合、getActualTypeArguments() を介して返された後、最も外側の <> が削除された後、残りの型は ExtendsNumber です。したがって、このパラメータの戻り値の型は WildcardType です。
{5}。ArrayList の場合、getActualTypeArguments() を通じて返された後、最も外側の <> が削除された後、残りの型は E[] になります。したがって、このパラメーターの戻り値の型は GenericArrayType です。
そのため、様々な型の実パラメータが取得できるため、統一するために直接の親クラスの配列Type[]を利用して受信しています。
4. java.lang.reflect.GenericArrayType インターフェース
GenericArrayType インターフェース型の意味
汎用配列型を表します。例: void メソッド(ArrayList[] al){…}
[注意] <> は配列の初期化では使用できません。つまり、<> は新しい配列の後に使用できません。そうしないと、javac が通過しません。ただし、参照変数またはメソッドのパラメーターとしてはまったく問題ありません。
汎用配列内の要素の型を取得します。
ソースコード宣言: Type getGenericComponentType();
[注意] 左から右に[]がいくつ並んでも、このメソッドは右端の[]のみを削除し、残りの内容がこのメソッドの戻り値として使用されます。
戻り値の型が Type なのはなぜですか?
public static E methodV(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();
[注] これはあくまで上限です。その理由は、型変数は、定義時に (複数の) 境界を制限するためにのみ extends を使用できるためです。 Super は使用できません。そうしないとコンパイルが通過しません。同時に、extends は型変数の上限を与えます。
戻り値の型が配列なのはなぜですか?型変数は & によって複数の上限で修飾できるため、複数の上限が存在するため、戻り値の型は配列型 [ ] になります。
たとえば次のような方法です。
public static extends Map&Cloneable&Serializable>EmethodVI(Ee){…}E の最初の上限は Map であり、これは ParameterizedType 型です。
E の 2 番目の上限は Cloneable であり、クラス タイプです。
したがって、統一化のため、戻り値の配列の要素型は Type となります。
6. java.lang.reflect.WildcardType インターフェース
WildcardType インターフェイス タイプの意味
ワイルドカードの種類を表す式。
たとえば、? は void printColl(ArrayListal) で Number を拡張します。
[注意] 上記 API のコメントによると、現時点では、ワイルドカード式は 1 つの上限または下限のみを受け入れます。これは、型変数を定義するときに指定できる複数の上限とは異なります。ただし、API はスケーラビリティを維持するために、ここでの戻り値の型は配列の形式で記述されると述べています。実際、現在返される配列のサイズは 1 です。
ワイルドカード式オブジェクトのジェネリック修飾された上限の型を取得します。
ソースコードステートメント: Type[] getUpperBounds();
[注意] 前述の通り、この段階で返されるType[]の配列のサイズは1です。 Type[ ]と書かれているのは言語アップグレード用の拡張機能です。
たとえば次のような方法です。
{1}。パブリック スタティック voidprintColl(ArrayListextends ArrayList> al){}
ワイルドカード式は次のとおりです: extendsArrayList なので、extends の後に ? の上限が続き、この上限は ParameterizedType タイプです。
{2}。パブリック スタティック voidprintColl(ArrayListextends E> al){}
ワイルドカード式は次のとおりです: ? extends E なので、extends の後に ? の上限が続き、この上限は TypeVariable 型です。
{3}.public static voidprintColl(ArrayListextends E[]> al){}
ワイルドカード式は次のとおりです: ? extends E[] なので、extends の後に ? の上限が続き、この上限は GenericArrayType タイプになります。
{4}.public static voidprintColl(ArrayListextends Number> al){}
ワイルドカード式は次のとおりです: extends Number なので、extends の後に ? の上限が続き、この上限がクラス タイプになります。
最終的には配列の要素の型として 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導入理由】
プログラムのスケーラビリティのために、Type インターフェイスが Class、ParameterizedType、GenericArrayType、TypeVariable、および WildcardType の一般的な親インターフェイスとして最終的に導入されました。このように、Type タイプ パラメータは、上記の 5 つのサブタイプの実パラメータを受け入れるか、戻り値のタイプが Type タイプ パラメータになります。
【Typeインターフェースにメソッドがない理由】
上記からわかるように、Type の出現はポリモーフィズムを通じてプログラムのスケーラビリティを向上させる役割を果たすだけで、それ以外の効果はありません。したがって、Type インターフェイスのソース コードにはメソッドはありません。