GenericDeclarationインタフェースの研究



ここ数日classクラスのコードを見て、汎用型について少し理解しました.ここで皆さんと共有します.
 
まず、非常に簡単な汎用型を見てみましょう.
 
public class TestA<K extends List & Serilizable, V> {
  ...
}

 このクラスではを汎用変数と呼ぶ.
 
そしてK extends List & Serilizableとは、Kという汎用型には上界があり、リストおよびSerilizableを継承するクラスまたはインタフェースでなければならないことを意味する.
 
 
そう言ってclassクラスを見てみましょう.classクラスが継承する汎用的なインタフェースにはGenericDecalarationとTypeがあります.
 
 
GenericDecalarationインタフェースは、どのクラスのオブジェクトが反射メカニズムによって汎用宣言を取得できるかを説明し、Cassの3つの実装クラスがあります. Constructor, Method.
なぜObjectクラスがないのか不思議に思うかもしれませんが、それはObjectクラスに
public final native Class getClass();方法.
このメソッドを呼び出すことで、Classタイプのオブジェクトを返すことができます.
次の例を例に挙げます.
 
public class Test {
	public static void main(String[] args) {
		Test t = new Test();
		Class<? extends Test> c = t.getClass();
		System.out.println(c.getName());         //  Test
	}
}

 Testクラスを定義し、インスタンス化オブジェクトtを生成し、getClass法によりtのランタイムクラスオブジェクトcを得た.これはcがClassタイプである.コンソールに出力しようとしたところ、Testというカスタムクラスの名前が表示されました.
 
 
 
したがって,各ObjectクラスのサブクラスはgetClassによって対応するランタイムクラスオブジェクトを得ることができる.ClassクラスがGenericDecalarationインタフェースを実現すると、すべてのObjectのサブクラスがGenericDecalarationインタフェースを実現したのとほぼ同じになります.
 
 
ではGenericDecalarationインタフェースを実現するには何の役に立つのでしょうか.GenericDecalarationインタフェースには
public TypeVariable[] getTypeParameters();方法
このメソッドが返す汎用変数配列は汎用宣言の内容を表し,TypeVariableタイプは汎用変数を定義する.
次の例を例に挙げます.
 
public class Test<K extends List & Serializable, V> {
	public static void main(String[] args) {
		Test t = new Test();
		TypeVariable[] tvarg = t.getClass().getTypeParameters();
		System.out.println("tvarg.lenght=" + tvarg.length);       //tvarg.lenght=2
	}
}

 getTypeParameters法により長さ2の配列が返され,それぞれが
 

汎用変数の
KとV(extends) List & Serializableは修飾に属するべきです)
 
 
次に、汎用変数TypeVariableインタフェースを分析します.
TypeVariableには全部で3つの方法があります
Type[] getBounds();
D getGenericDeclaration();
String getName();
 
 
Type[] getBounds();現在のタイプの境界を返すことです
先ほどの例を例にK extends List & Serializable、そのkの境界はListとSerializableであるべきです
次の例で試してみます
public class Test<K extends List & Serializable, V> {
	public static void main(String[] args) {
		TypeVariable[] tvarg = new Test().getClass().getTypeParameters();
		Type[] typearg = tvarg[0].getBounds();
		System.out.println("typearg.lenght=" + typearg.length);
		for (int i = 0; i < typearg.length; i++) {
			System.out.println(typearg[i].toString());
		}
	}
}

 コンソールがtypearg.lenght=2を先に出力しているのを見て、2つの上境界があることを示します.次に、2つの境界のタイプをそれぞれ出力します.
D getGenericDeclaration();メソッドは,どのクラスに汎用的な宣言が行われたかを返す.を返しますが、コードに宣言されたクラスを持つランタイムクラスオブジェクトが返されます.ClassタイプがGenericDeclarationインタフェースを実現していることは理解できます.宣言されたコードを見て、このClassに探して、ヒントと見なすことができます.)
以下の例を例にとると
public class Test<K extends List & Serializable, V> {
	public static void main(String[] args) {
		TypeVariable[] tvarg = new Test().getClass().getTypeParameters();
		GenericDeclaration gd0 = tvarg[0].getGenericDeclaration();
		GenericDeclaration gd1 = tvarg[1].getGenericDeclaration();
		System.out.println("gd0=" + gd0.toString());
		System.out.println("gd1=" + gd1.toString());
	}
}

 コンソールでは、この汎用型がTestというクラスで宣言されていることを直接示しています.
最後のString getName();メソッドは汎用変数の名前を返します.その例を例に挙げると、KとVが続きます.
 
public class Test<K extends List & Serializable, V> {
	public static void main(String[] args) {
		TypeVariable[] tvarg = new Test().getClass().getTypeParameters();
		System.out.println("tvarg0=" + tvarg[0].getName());
		System.out.println("tvarg1=" + tvarg[1].getName());
	}
}

 これらの方法により,反射機構を用いてタイプの汎用宣言を動的に取得できるようになった.