您的位置:首页 > 编程语言 > Java开发

JavaSE学习笔记--泛型

2011-10-12 17:26 435 查看
泛型:

泛型是java jdk1.5出现的新特性之一。

泛型是给编译看的,当传入的实参类型不符时,会在编译期报错。而反射可以绕过编译器。

ArrayList<E>类定义和ArrayList<Integer>类引用中涉及如下术语:

整个ArrayList<E>称为泛型类型

ArrayList<E>中的E称为类型变量或类型参数

整个ArrayList<Integer>称为参数化的类型

ArrayList<Integer>中的Integer称为类型参数的实例或实际类型参数

ArrayList<Integer>中的<>念做typeof

ArrayList称为原始类型

参数化类型与原始类型的兼容性:

如下面的两个都是可以的,但是编译时会出现一个警告。

Collection<String> c = new Vector();

Collection c = new Vctor<String>();

参数化类型不考虑类型参数的继承关系:

Collection<String> c = new Vector<Object>(); -->(错)

Collection<Object> c = new Vector<String>(); -->(错)

在创建数组实例时,数组的元素不能使用参数化的类型,例如,下面语句有错误:

Vector<Integer> vectorList[] = new Vector<Integer>[10];

思考一下:下面的代码会报错吗?

Vector v1 = new Vector<String>();

Vector<Object> v = v1;

上面的不会报错。

泛型中的通配符: ?

在使用通配符泛型类型作为一个方法的参数列表时,此方法体中就不能再使用和类型有关的方法。只能使用与参数类型不管的方法,否侧的话会报错。

如下:

public static void printCollection(Collection<?> collection){

//collection.add(1); (错的,不可以。因为1使用了指定的类型)

collection.size(); //可以

for(Object obj : collection){

System.out.println(obj);

} //可以

collection = new HashSet<Date>(); //可以

}(较有效)

但是此时可以使用“通配符的方法”来克服这个弊端:<T>

如下:

public static void printCollection(Collection<T> collection, T obj){

collection.add(obj); //这时,是可以的

collection.size(); //可以

for(Object obj : collection){

System.out.println(obj);

} //可以

collection = new HashSet<Date>(); //可以



通配符的扩展

限制通配符的上边界:

正确: Vector<? extends Number> x = new Vector<Integer>();

错误: Vector<? extends Number> x = new Vector<String>();

限制通配符的下边界:

正确: Vector<? super Integer> x = new Vector<Number>();

错误: Vector<? super Integer> x = new Vector<Byte>();

Float x1 = add(3.5,3); ( 错 )。

此时的编译器提示信息“Type nismatch: cannot convert from Number&Comparable<?> to Float”。

所以需要实现Comparble的Number,所以只能是Number类。所以只能改成下边这样。

Number x1 = add(3.5,3);

但是问题出现了,你会发现Number类并没有实现Comparable接口,而是只实现了Serializable接口。不知道这个是怎么解释的呢?

类型推断具有传播性,通过下边的例子就可以看出来了:

copy1(new Vector<String>(), new String[10]);

copy2(new Date[10],new String[10]); //都取他们的交集类,即Object类

copy1(new Vector<Date>(),new String[10]); //此时会报错,因为此时Date被泛型修饰无法再提升到父类Object

public static <T> void copy1(Collection<T> dest, T[] src){

for(int x=0; x<src.length; x++){

dest.add(src[x]);

}

---------------------- <a href="http://edu.csdn.net/heima" target="blank">android培训</a>、<a href="http://edu.csdn.net/heima" target="blank">java培训</a>、期待与您交流!
----------------------

}

public static <T> void copy2(T[] dest, T src){

for(T t : dest){

t = src;

}

}

自定义泛型类(类级别的泛型):

其目的就是当我的类中有多个方法用到的泛型都是同一个类型,

而我们有想让这两个类型相同,就可以给这个类定义上这个泛型。这也是泛型类的由来。

注意静态方法中不能使用泛型。

class Person<E>

{

public static void update(E obj){}

} (报错)

这是需要把他独立出来,单独使用“方法级别的泛型”

class Person<E>

{

public static <E> void update(E obj){}

} (对)

对于泛型,java在编译之后就会去类型化。下边的两个方法不是重载。

public static void applyVector(Vector<Date> v1){

}

public static void applyVector(Vector<Integer> v1){

}

通过反射获取泛型的实际类型参数:(高级)

其思路是这样的,我们无法通过一个变量的数据是无法知道自己是什么类型的。

只能通过把这个变量作为一个参数传递给方法,通过泛型方法来知道参数列表中的泛型类型的。

代码如下:

//Vector<Date> v1 = new Vector<Date>();

Method applyMethod = GenericTest.class.getMethod("applyVector", Vector.class);

Type[] types = applyMethod.getGenericParameterTypes();

ParameterizedType pType = (ParameterizedType)types[0];

System.out.println(pType.getRawType());

System.out.println(pType.getActualTypeArguments()[0]);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: