java獲取泛型信息

  總結一下java中獲取與泛型相關的信息的知識,不如說是使用方法.網上也有不少相似的優秀文章,這裏主要作一個知識的總結.經過反射獲取泛型信息的常見例子:java

//bean
package testProject;

public class Person {
	private String nameString = "233";

	public String getNameString() {
		return nameString;
	}

	public void setNameString(String nameString) {
		this.nameString = nameString;
	}

	@Override
	public String toString() {
		return "Person [nameString=" + nameString + "]";
	}
	
}

//基本dao
public abstract class BaseDao<T> {
	private Class<T> clazz = null;
	{
		Type type = getClass().getGenericSuperclass();
		if( type instanceof ParameterizedType ){
			ParameterizedType pType = (ParameterizedType)type;
			Type claz = pType.getActualTypeArguments()[0];
			if( claz instanceof Class ){
				this.clazz = (Class<T>) claz;
			}
		}
	}
	
	public T getEntity() throws InstantiationException, IllegalAccessException{
		return this.clazz.newInstance();
	}
}

//實現
public class PersonDao extends BaseDao<Person> {
	public static void main(String[] args) throws InstantiationException, IllegalAccessException {
		PersonDao pDao = new PersonDao();
		System.out.println( pDao.getEntity().toString() );
	}
}

//結果:Person [nameString=233]

 在java的java.lang.reflect 包中有一個Type接口.  具體子類以下.api

  通常java中包含泛型信息的地方包括類( class<T> MyClass )方法( public <T> void test(T t){  } )字段( public List<T> list,public T t),繼承的父類中包含( class MyClass1 extends MyClass<String>{} )等.數組

  java將這些泛型信息進行了分類,包括包含泛型信息的類型,不包含泛型信息的類型,泛型數組類型,以及對泛型參數(T,V等泛型參數)信息類等.全部這些分類統一用Type接口做爲抽象ide

class HaveGenericClass<T>{}
class NoGenericClass{}

public class TypeTest<T> {
    private List<String> list;
    private T t;
    private List list1;
    private List<T> list2;
    private HaveGenericClass haveGenericClassWithoutGeneric;
    private HaveGenericClass<String> haveGenericClassWithGeneric;
    private NoGenericClass noGenericClass;
    private int var;
    private List<T>[] listTArr;
    private List<String>[] listStringArr;
    private List[] listArr;
    private T[] tArr;
    private int[] intArr;
    private HaveGenericClass[] haveGenericClassWithoutGenericArr;
    private HaveGenericClass<T>[] haveGenericClassWithGenericArr;
    private HaveGenericClass<String>[] haveGenericClassWithGenericArr2;
    private NoGenericClass[] noGenericClassArr;
    
    private <U> U genericMethod(U u,String s){
        return u;
    }
    public static void main(String[] args) throws NoSuchFieldException, SecurityException, NoSuchMethodException {
        Field[] fields = TypeTest.class.getDeclaredFields();
        for( Field f: fields ){
            Type t = f.getGenericType();
            printType(f.getName(), t);
        }
        Method genericMethod = TypeTest.class.getDeclaredMethod("genericMethod",Object.class,String.class);
        Type[] types = genericMethod.getGenericParameterTypes();
        Parameter[] ps = genericMethod.getParameters();
        for(Parameter p : ps){
            Type type = p.getParameterizedType();
            printType(p.getName(), type);
            System.out.println( p.getType() );
        }
    }
    public static void printType(String name, Type type){
        if( type instanceof Class ){
            System.out.println("the type of " + name + " is : Class");
        }else if( type instanceof ParameterizedType ){
            System.out.println("the type of " + name + " is : ParameterizedType");
        }else if( type instanceof GenericArrayType ){
            System.out.println("the type of " + name + " is : GenericArrayType");
        }else if( type instanceof TypeVariable ){
            System.out.println("the type of " + name + " is : TypeVariable");
        }
        
    }
}
運行結果以下:

the type of list is : ParameterizedType
the type of t is : TypeVariable
the type of list1 is : Class
the type of list2 is : ParameterizedType
the type of haveGenericClassWithoutGeneric is : Class
the type of haveGenericClassWithGeneric is : ParameterizedType
the type of noGenericClass is : Class
the type of var is : Class
the type of listTArr is : GenericArrayType
the type of listStringArr is : GenericArrayType
the type of listArr is : Class
the type of tArr is : GenericArrayType
the type of intArr is : Class
the type of haveGenericClassWithoutGenericArr is : Class
the type of haveGenericClassWithGenericArr is : GenericArrayType
the type of haveGenericClassWithGenericArr2 is : GenericArrayType
the type of noGenericClassArr is : Class
the type of arg0 is : TypeVariable
class java.lang.Object
the type of arg1 is : Class
class java.lang.String函數

  從上面的測試中能夠看到,帶有泛型信息的類型能夠劃分到ParameterizedType類型,相似( List<String>,List<T>等).包含泛型信息的數組則能夠劃分到GenericArrayType分類,其他不包含泛型信息的類型能夠劃分到Class類型(能夠認爲不包含泛型的類型也是一種參數化類型(參數化類型 舉個例子就是 class person<T>{ }這樣子),只不過這種參數化類型的泛型信息爲零(沒有泛型信息的參數化類型)),所以Class類也實現Type接口.下面就介紹有一下這4個類的方法和如何獲取(僅限我所知道的).測試

  1.ParameterizedTypethis

public interface ParameterizedType extends Type {
   //獲取<>中的實際類型
    Type[] getActualTypeArguments();
   //獲取<>前的實際類型
    Type getRawType();
  //若是這個類是某個類的所屬,返回這個所屬的類,不然返回null
    Type getOwnerType();
}

  Type[] getActualTypeArguments(); spa

  獲取<>中的實際類型,該方法只脫去最外層的<>..net

class People<U,V,T>{}

public class TypeTest<T> {
    private People<String,List<String>,T> People;
    

    public static void main(String[] args) throws NoSuchFieldException, SecurityException, NoSuchMethodException {
        Type t = TypeTest.class.getDeclaredField("People").getGenericType();
        ParameterizedType pt = (ParameterizedType)t;
        Type[] types = pt.getActualTypeArguments();
        for( int i = 0; i < types.length; i++ ){
            printType(types[i].toString(), types[i]);
        }
    }
    public static void printType(String name, Type type){
        if( type instanceof Class ){
            System.out.println("the type of " + name + " is : Class");
        }else if( type instanceof ParameterizedType ){
            System.out.println("the type of " + name + " is : ParameterizedType");
        }else if( type instanceof GenericArrayType ){
            System.out.println("the type of " + name + " is : GenericArrayType");
        }else if( type instanceof TypeVariable ){
            System.out.println("the type of " + name + " is : TypeVariable");
        }
        
    }
}

執行結果爲3d

the type of class java.lang.String is : Class
the type of java.util.List<java.lang.String> is : ParameterizedType
the type of T is : TypeVariable

能夠看到第二個泛型參數的類型是ParameterizedType,也真是List<String>所對應的類型.另外第三個泛型參數的類型爲TypeVariable,泛型參數(T,V等泛型參數)信息類(我是這麼解釋和理解的)以後會提到.

  2.getRawType()

  獲取聲明泛型的實際的類或接口,也就是<>前面的那個值

  3.getOwnerType()

  若是該類是內部類,那麼該方法能夠獲取外部類,不然返回null, 舉個例子

public class TypeTest<T> {
    private People<String,List<String>,T> People;
    private class Inner<U>{}
    private Inner<String> inner;
    public static void main(String[] args) throws NoSuchFieldException, SecurityException, NoSuchMethodException {
        Type t = TypeTest.class.getDeclaredField("inner").getGenericType();
        ParameterizedType pt = (ParameterizedType)t;
        Type t1 = pt.getOwnerType();
        if( t1 instanceof ParameterizedType ){
            ParameterizedType pt1 = (ParameterizedType)t1;
            System.out.println( pt1.getRawType() );
        }
    }
}

結果:

class testProject.TypeTest

  2.GenericArrayType

  泛型數組類型,相似(List<String>[] T[]等).

  

public interface GenericArrayType extends Type {
   
    Type getGenericComponentType();
}

返回泛型數組中元素的Type類型,即List<String>[] 中的 List<String>(ParameterizedTypeImpl),T[] 中的T(TypeVariableImpl),List<String>[][]中的List<String>[]();

  

public class TypeTest<T> {
    private List<String>[] lists;
    private T[] ts;
    private List<String>[][] listss;
    public static void main(String[] args) throws NoSuchFieldException, SecurityException, NoSuchMethodException {
        Type lists = ((GenericArrayType)TypeTest.class.getDeclaredField("lists").getGenericType()).getGenericComponentType();
        Type ts = ((GenericArrayType)TypeTest.class.getDeclaredField("ts").getGenericType()).getGenericComponentType();
        Type listss = ((GenericArrayType)TypeTest.class.getDeclaredField("listss").getGenericType()).getGenericComponentType();
        printType("lists", lists);
        printType("ts",ts );
        printType("listss",listss );
    }
    public static void printType(String name, Type type){
        if( type instanceof Class ){
            System.out.println("the type of " + name + " is : Class");
        }else if( type instanceof ParameterizedType ){
            System.out.println("the type of " + name + " is : ParameterizedType");
        }else if( type instanceof GenericArrayType ){
            System.out.println("the type of " + name + " is : GenericArrayType");
        }else if( type instanceof TypeVariable ){
            System.out.println("the type of " + name + " is : TypeVariable");
        }
        
    }
}

執行結果以下:

the type of lists is : ParameterizedType
the type of ts is : TypeVariable
the type of listss is : GenericArrayType

3.TypeVariable  

  泛型的類型變量,能夠認爲是List<T>中的T,Map<K,V>中的K,V等

  3.1 getBounds()

  獲取類型變量上限,若是沒有上限(即 class Person<T>{},這裏的類型變量T 沒有上限),那麼上限爲Object

public class TypeTest<T extends String & Comparable<String>> {//繼承String,實現接口Comparable<String>,能夠用&鏈接多個接口
    private List<String>[] lists;
    private T[] ts;
    private List<String>[][] listss;
    public static void main(String[] args) throws NoSuchFieldException, SecurityException, NoSuchMethodException {
        TypeVariable tv[] = TypeTest.class.getTypeParameters();
        Type[] ts = tv[0].getBounds();
        for( Type t : ts ){
            System.out.println( t );
        }
    }
}

執行結果以下: 

class java.lang.String
java.lang.Comparable<java.lang.String>

  3.2 getGenericDeclaration()

   獲取聲明該類型變量的類好比( TypeTest<T> 中的TypeTest )

   

public class TypeTest<T> {
    private List<String>[] lists;
    private List<String>[][] listss;
    public static void main(String[] args) throws NoSuchFieldException, SecurityException, NoSuchMethodException {
        TypeVariable tv[] = TypeTest.class.getTypeParameters();
        System.out.println( tv[0].getGenericDeclaration() );
    }
}

執行結果:

class testProject.TypeTest

  3.3 getName()

  獲取類型變量在源碼中定義的名稱

  

public class TypeTest<T> {
    private List<String>[] lists;
    private List<String>[][] listss;
    public static void main(String[] args) throws NoSuchFieldException, SecurityException, NoSuchMethodException {
        TypeVariable tv[] = TypeTest.class.getTypeParameters();
        System.out.println( tv[0].getName() );
    }
}

執行結果:

T

//補充一點

  泛型的聲明包括在類上方法上或者構造函數上,並不能再字段上聲明泛型.

  在類上聲明:

    class Person<T>{

      private T t; //字段可使用聲明的泛型

    }

  在構造函數上聲明:

    class TypeTest{

      public <U> TypeTest(){}

    }

  在方法上聲明:

    class TypeTest{

      public <T> void test(T t){}

    }

但不能直接在字段上聲明, 好比

    class Person{

      private T t;//錯誤

    }

這樣的使用方法不正確.

由此及彼,在獲取泛型變量的方式上,java提供了一個GenericDeclaration接口

public interface GenericDeclaration{
  TypeVariable<?>[]    getTypeParameters();
}

用於獲取泛型變量,

而實現該接口的繼承體現以下

其中並不包含Field類.

4.Class

  Class描述類的字節碼信息(即.class文件的信息),包括所描述的類的字段信息,方法信息,註解信息,也包括與泛型有關的信息. 下面只介紹和泛型有關的方法.

  

public final class Class<T> extends Object
implements Serializable,GenericDeclaration,Type,AnnotatedElement

  4.1 getTypeParameters

  TypeVariable<?>[] getTypeParameters()

  返回類上的泛型信息( 好比Person<T,U>{},則返回TypeVariable數值標識泛型變量T,U ,若是沒有泛型信息則數組長度爲零)

  

class People<T,V,S>{
    
}
class Chinese extends People<String,Integer,Double>{
    
}
public class TypeTest<T> {
    public <U> TypeTest(){
        
    }
    private List<String>[] lists;
    private List<String>[][] listss;
    public static void main(String[] args) throws NoSuchFieldException, SecurityException, NoSuchMethodException {
        TypeVariable[] tv = People.class.getTypeParameters();
        System.out.println( tv.length );
        for( TypeVariable t : tv ){
            System.out.println( t );
        }
        TypeVariable[] tv1 = Chinese.class.getTypeParameters();
        System.out.println( tv1.length );
        for( TypeVariable t : tv1 ){
            System.out.println( t );
        }
    }
}

執行結果以下:

3
T
V
S
0

   4.2 getGenericSuperClass();

返回該類的父類的泛型類型 好比( class Chinese extendis People<String,Integer,Double>{},返回的是People<String,Integer,Double>,若是沒有父類,返回的是Objec的Class實例 )

  4.3 getGenericInterfaces();

返回該類的實現的接口們的泛型類型 好比(class Chinese extends People<String,Integer,Double> implements SpeakChinese<String>,UseChopsticks<Double>{},返回的是SpeakChinese<String>,UseChopsticks<Double>,若是沒有實現的接口,返回的Type數組長度爲0)

  代碼以下:

  

interface Walk<R>{}
interface SpeakChinese<H>{}
interface UseChopsticks<M>{}
class People<T,V,S> implements Walk<Short>{
    
}
class Chinese extends People<String,Integer,Double> implements SpeakChinese<String>,UseChopsticks<Double>{
    
}
class Mars extends People<String,Double,List<String>>{
    
}
public class TypeTest<T> {
    public <U> TypeTest(){
        
    }
    public static void main(String[] args) throws NoSuchFieldException, SecurityException, NoSuchMethodException {
        printType(People.class.getGenericSuperclass().toString(), People.class.getGenericSuperclass());
        printType(Chinese.class.getGenericSuperclass().toString(), Chinese.class.getGenericSuperclass());
        Type[] types = Chinese.class.getGenericInterfaces();
        System.out.println( types.length );
        for(Type t: types){
            printType(t.toString(), t);
        }
        Type[] types1 = Mars.class.getGenericInterfaces();
        System.out.println( types1.length );
        for( Type t : types1 ){
            printType( t.toString(),t );
        }
    }
    public static void printType(String name, Type type){
        if( type instanceof Class ){
            System.out.println("the type of " + name + " is : Class");
        }else if( type instanceof ParameterizedType ){
            System.out.println("the type of " + name + " is : ParameterizedType");
        }else if( type instanceof GenericArrayType ){
            System.out.println("the type of " + name + " is : GenericArrayType");
        }else if( type instanceof TypeVariable ){
            System.out.println("the type of " + name + " is : TypeVariable");
        }
        
    }
}

執行結果以下:

  

the type of class java.lang.Object is : Class
the type of testProject.People<java.lang.String, java.lang.Integer, java.lang.Double> is : ParameterizedType
2
the type of testProject.SpeakChinese<java.lang.String> is : ParameterizedType
the type of testProject.UseChopsticks<java.lang.Double> is : ParameterizedType
0

以上就是4種類型的介紹.

另外 還有一個接口繼承自Type接口

   WildcardType

用於描述包含通配符的泛型變量的信息. 好比List<? extends String> 或者 List<? super Integer>等

public interface WildcardType extends Type{
    Type[]    getLowerBounds();
    Type[]    getUpperBounds(); 
}

  getLowerBounds()

  獲取泛型變量的下界,

  getUpperBounds()

  獲取泛型變量的上界.

  

public class TypeTest<T> {
    private List<? extends String> upperBoundsList;
    private List<? super Integer> lowerBoundsList;
    
    
    public static void main(String[] args) throws NoSuchFieldException, SecurityException, NoSuchMethodException {
        Field upperBoundsList = TypeTest.class.getDeclaredField("upperBoundsList");
        ParameterizedType pt = (ParameterizedType)upperBoundsList.getGenericType();
        Type[] types = pt.getActualTypeArguments();
        System.out.println( ((WildcardType)types[0]).getUpperBounds()[0] );
        
        
        Field lowerBoundsList = TypeTest.class.getDeclaredField("lowerBoundsList");
        ParameterizedType pt1 = (ParameterizedType)lowerBoundsList.getGenericType();
        Type[] types1 = pt1.getActualTypeArguments();
        System.out.println( ((WildcardType)types1[0]).getLowerBounds()[0] );
    }
}

執行結果以下:

class java.lang.String
class java.lang.Integer

 

/*---------------------------------------------------------------------------------------------------------------------------------------------------------------*/

以上爲本人查閱資料參考網上文章所寫,

不能保證徹底正確,

也並不是面面俱到.

表述方式並非偏向於專業化(若有疑惑的地方可留言),若有錯誤,望指正.

 

參考文檔:

  http://tool.oschina.net/apidocs/apidoc?api=jdk_7u4

  http://www.jianshu.com/p/e8eeff12c306

相關文章
相關標籤/搜索