一)泛型的作用
相对于依赖程序员来记住对象类型、执行类型转换——这会导致[b]程序运行时[/b]才发现错误,很难调试和解决。 泛型的主要好处就是让编译器保留参数的类型信息,执行类型检查,执行类型转换操作:[b]编译器保证[/b]了这些类型转换的绝对无误。而编译器能够帮助程序员在编译时强制进行大量的类型检查,发现其中的错误。并且Java泛型是一种便捷语法,能节省你某些Java类型转换(casting)上的操作。
二)泛型的声明
泛型的声明可细分为四种: 泛型类声明,泛型接口声明,泛型方法声明,泛型构造器声明
1)[b]泛型类和接口声明[/b]
两者非常类似:
声明完以后,在该类/接口里就可使用泛型标记如下:
2)[b]泛型方法和构造器的声明[/b]
3)[b]实例:[/b]
三)限制类型和通配符
1)[b]限制类型[/b]
如果有类声明限制类型如下:
那么:
这个故事告诉我们两点:
1' 泛型中CollectionGenFoo<A>与CollectionGenFoo<B>没有任何继承,父子或相等的关系,无论A和B是什么关系
2' <T extends Collection>限定的是T类型是实现Collection接口的类型,或者T是继承了XX类的类型。
2)[b]通配符[/b]
[b]<?>[/b] 允许Object及其下的任何Java类。也就是任意类。看似有点多余,但记住哦A<?>和A<T>永远不等啊!这很有用
[b]<? extends T>[/b] 向下限制,只接受T及其子类。一下是个例子:
[b]<? super T>[/b] 向上限制,只接受T及其父类。
四)注意事项
1) PECS法则,”Producer Extends, Consumer Super”,不细说了,详见《effective java》
2) 一个static方法,无法访问泛型类的类型参数,所以,若要static方法需要使用泛型能力,[b]必须使其成为泛型方法[/b]。
3) 一个不错的例子
声明:
错误的使用,报错,因为E无法确定,需显示指明:
正确的写法:
相对于依赖程序员来记住对象类型、执行类型转换——这会导致[b]程序运行时[/b]才发现错误,很难调试和解决。 泛型的主要好处就是让编译器保留参数的类型信息,执行类型检查,执行类型转换操作:[b]编译器保证[/b]了这些类型转换的绝对无误。而编译器能够帮助程序员在编译时强制进行大量的类型检查,发现其中的错误。并且Java泛型是一种便捷语法,能节省你某些Java类型转换(casting)上的操作。
二)泛型的声明
泛型的声明可细分为四种: 泛型类声明,泛型接口声明,泛型方法声明,泛型构造器声明
1)[b]泛型类和接口声明[/b]
两者非常类似:
public class GenericsFoo<T> { ...}
public interface GenericsIFoo<T> { ...}
public interface List<T> extends Collection<T> { ...}
声明完以后,在该类/接口里就可使用泛型标记如下:
T get(int index);
2)[b]泛型方法和构造器的声明[/b]
public static <T> T getFirst(List<T> list) { ...}
<X> GenericsFoo(X x) {...}
3)[b]实例:[/b]
class MyClass<X> {
<T> MyClass(T t) { }
}
public class Test{
public static void main(String args[]){
Integer i = 0;
MyClass<String> mc = new MyClass<String>(i);
}
}
三)限制类型和通配符
1)[b]限制类型[/b]
如果有类声明限制类型如下:
public class CollectionGenFoo<T extends Collection> {...}
那么:
//正确:
CollectionGenFoo<ArrayList> listFoo = null;
listFoo = new CollectionGenFoo<ArrayList>(new ArrayList());
//出错了,不让这么干。
CollectionGenFoo<Collection> listFoo = null;
listFoo=new CollectionGenFoo<ArrayList>(new ArrayList());
这个故事告诉我们两点:
1' 泛型中CollectionGenFoo<A>与CollectionGenFoo<B>没有任何继承,父子或相等的关系,无论A和B是什么关系
2' <T extends Collection>限定的是T类型是实现Collection接口的类型,或者T是继承了XX类的类型。
2)[b]通配符[/b]
[b]<?>[/b] 允许Object及其下的任何Java类。也就是任意类。看似有点多余,但记住哦A<?>和A<T>永远不等啊!这很有用
[b]<? extends T>[/b] 向下限制,只接受T及其子类。一下是个例子:
//现在不会出错了
CollectionGenFoo<? extends Collection> listFoo1 = null;
listFoo=new CollectionGenFoo<ArrayList>(new ArrayList());
[b]<? super T>[/b] 向上限制,只接受T及其父类。
四)注意事项
1) PECS法则,”Producer Extends, Consumer Super”,不细说了,详见《effective java》
2) 一个static方法,无法访问泛型类的类型参数,所以,若要static方法需要使用泛型能力,[b]必须使其成为泛型方法[/b]。
3) 一个不错的例子
声明:
public static <E> Set<E> union(Set<? extends E> s1, Set<? extends E> s2)
错误的使用,报错,因为E无法确定,需显示指明:
Set<Integer> integers = ...;
Set<Double> doubles = ...;
Set<Number> numbers = union(intergers,doubles);
正确的写法:
Set<Number> numbers = Union.<Number>union(integers,doubles);