foxspecial

导航

java 泛型详解

public class Base<T>{
    Class classType=T.class;
    public Base(){
     //想在这里 得到T的类对象 赋值给 classType
}

getClass().getName())

 T.getClass()或者T.class都是非法的,因为T是泛型变量。


由于一个类的类型是什么是在编译期处理的,故不能在运行时直接在Base里得到T的实际类型。


有一种变通的实现方式:


import java.lang.reflect.Array;


import java.lang.reflect.ParameterizedType;


import java.lang.reflect.Type;




public class Generic extends Base<String> {


 public static void main(String[] args) {


  Generic c = new Generic();


  System.out.println(c.array);


 }


 


 Object array ;


 public Generic() {


  array = Array.newInstance(getGenericType(0), 100);


 }


}




class Base<T> {


 public Class getGenericType(int index) {


  Type genType = getClass().getGenericSuperclass();


  if (!(genType instanceof ParameterizedType)) {


   return Object.class;


  }


  Type[] params = ((ParameterizedType) genType).getActualTypeArguments();


  if (index >= params.length || index < 0) {


   throw new RuntimeException("Index outof bounds");


  }


  if (!(params[index] instanceof Class)) {


   return Object.class;


  }


  return (Class) params[index];


 }


}


其中Base<T>是泛型类,在父类中声明getGenericType,子类继承具体的Base<String>,那么在子类中就可以通过getGenericType(0)获取到String的class.

  

举个例子,譬如List.toArray
<T> T[] toArray(T[] a)
当你运行的时候写成list.toArray(new String[0])-->此时的T就是String类型,
当你写成list.toArray(new Integer[0]))--->此时的T就是Integer类型。

范型T并不特指某一特定类型,所以不能用T t = new T()

泛型类的定义可以看看collections的定义,很多泛型的接口函数

例如:   public static void swap(List<?> list, int i, int j) {

        final List l = list;

        l.set(i, l.set(j, l.get(i)));

}

 

   public static void shuffle(List<?> list) {

        Random rnd = r;

        if (rnd == null)

            r = rnd = new Random();

        shuffle(list, rnd);

    }

 

 

    public static <T> int binarySearch(List<? extends T> list, T key, Comparator<? super T> c) {                     // <t>先定义的

        if (c==null)

            return binarySearch((List) list, key);

 

        if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)

            return Collections.indexedBinarySearch(list, key, c);

        else

            return Collections.iteratorBinarySearch(list, key, c);

    }

 

 

class general {

    public <T> T fun(T t){

        return t;

    }

}

//<T> T 定义和返回值需要一样

 

使用<T>来声明一个类型持有者名称,然后就可以把T当作一个类型代表来声明成员、参数和返回值类型。

当然T仅仅是个名字,这个名字可以自行定义。

class GenericsFoo<T> 声明了一个泛型类,这个T没有任何限制,实际上相当于Object类型,实际上相当于 class GenericsFoo<T extends Object>。

1、如果只指定了<?>,而没有extends,则默认是允许Object及其下的任何Java类了。也就是任意类。

2、通配符泛型不单可以向下限制,如<? extends Collection>,还可以向上限制,如<? super Double>,表示类型只能接受Double及其上层父类类型,如Number、Object类型的实例。

3、泛型类定义可以有多个泛型参数,中间用逗号隔开,还可以定义泛型接口,泛型方法。这些都与泛型类中泛型的使用规则类似

 

Java代码 

  1. public void testUpperBound()  
  2. {  
  3.     List<Timestamp> list = new ArrayList<Timestamp>();  
  4.     Date date = new Date();  
  5.     upperBound(list,date);  
  6. }  

 

//类型加上参数,例如  String <T> t1= new String <T>();

 

 

2种定义方式

 

public class EntityDao2<T,ID> { 
    
    public void add(T t){ 
        //..保存实体的代码 
    } 
    
    public T get(ID id){ 
        //.查询实体的代码 
        return null; 
    } 

}这种形式,是把范型声明放在类中了,就不需每个方法都写强制类型转换。 

 

、--------

public class EntityDao1 { 
    
    public <T> void add(T t){ 
        //查询实体的代码 
    } 
    
    public <T,ID> T get(ID id){ 
        //.保存实体的代码 
        return null; 
    } 

}        范型一般用于方法的参数或者方法的返回值,上面的写法,我们要使范型有效,就须在方法的返回类型前加入强制范型转换。其中,add(T t)的参数用了范型,它的返回值是void型,就在void 前用强制类型转换,即加上<T>,强制转换成范型的形式,这样就不会报错了。而T get(ID id),由于它的参数和返回类型都用了范型,故要在返回类型T前强制转换,即<T,ID>。 

posted on 2013-08-06 16:12  foxspecial  阅读(456)  评论(0编辑  收藏  举报