foxspecial

导航

泛值类型

午夜不眠的小狗|四级

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

评论|0

2010-04-29 08:13记忆邮心|四级

T.getClass()或 T.class,或class.forName(T.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:47  foxspecial  阅读(374)  评论(0编辑  收藏  举报