希望弄懂:
一. 泛型的好处
二. 表述
三. <R extends T>的作用
四. <? super T>,<? extends T>作为参数类型的作用
五. wildcard嵌套 <? extends|super ? extends|super T>
一. JDK1.5 引入了泛型,好处:
1. 编译时,类型检查
2. 避免类型转换
例如,
ArrayList list = new ArrayList();
list.add("str1")
System.out.prinntln((String)list.get(0)).length());
JDK1.4的写法
缺陷:
1. 没有类型保证,如果list.add(new Object()); 那么(String)list.get(0); 就会ClassCastException
2. 没有使用list中的元素都要强制转换
在使用泛型,就方便多了
ArrayList<String> list = new ArrayList<String>();
list.add("str1");
System.out.println(list.get(0).length());
JDK1.5写法
对于JDK1.7或以上,还进一步简化:
ArrayList<String> list = new ArrayList<>();
JDK1.7写法
后面会自动添加类型;
二. 几种表述:
1. 泛型静态函数
public class C {
public static <T> T foo(T v) {
return null;
}
}
//用法:
String ret = C.foo("str");
2. 泛型类
public class C<T> {
public T foo(T v) {
return null;
}
}
//用法:
C<String> instance = new C<String>();
String ret = instance.foo("str");
3. 泛型成员函数
public class C {
public <T> T foo(T v) {
return null;
}
}
//用法:
C instance = new C();
String ret = instance.foo("str");
4. 泛型类的泛型成员函数
public class C<R> {
public <T> T foo(T v1, R v2) {
return null;
}
}
//用法:
C<String> instance = new C<String>();
Integer ret = instance.foo(1, "str");
5. 泛型类的泛型静态函数
public class C<R> {
public static <T> T foo(T v1) {
return null;
}
}
// (R的泛型没意义)
Integer ret = C.foo(1);
6. public class C<T> { public static T foo(T v) {return null;} } 不能编译
三. ,<R extends T>的作用
作为方法的类型,
extends提供R的上限,如<R extends Number>,R可以是Number,Integer,Double等继承Numberl类,起到限制作用。
没有<R super T>,如<R super Number>,R可以是Number, Serializable,由于子类都可以放到父类上,相当于Number,所以没意义的
如
public class C {
public static <R extends Number> T foo(R v) {
return v;
}
}
Integer ret = C.foo(1);
作为类的类型,也是类似的
如
public class C<R extends Number> {
public R foo(R v) {
return v;
}
}
C<Integer> instance = new C<Integer>();
Integer ret = instance.bar(1);
那么,采用<R extends Number>的好处有哪些呢:
1. v能知道是Number或子类,能提早使用Number的方法,v.intValue();
2. 现在具体化的范围,如C<String>编译错误
至于class C<R super Number> 同样不支持。
四. <? super T>,<? extends T>作为参数类型的作用
先说一下,泛型删除
<?>代表没类型,如果作为参数类型,就只能接收null值;如果作为返回类型,就只能返回Object;一般这类,只能用没有泛型的函数,或者说,不关心其类型
如
public class C<T> {
public T foo(T v) {
return v;
}
public String bar(int i) {
return "" + i;
}
}
C<?> instance = new C<?>();
Object ret = instance.foo(null); // 这个用法没实际作用
String sRet = instance.bar(1); // 主要调用没有类型部分
既然C<?>不用考虑T的类型,那么具体化也可以,如 C<?> instance = new C<String>();
这样设计,创建者能根据自己需要设置类型,而使用者就不用关系类型
如果需要使用数据类型,就可以使用
C<? super Number> 或 C<? extends Number>
C<? super Number> 适合传入类型,返回没类型,容器能向下兼容
如
C<? super Number> instance = new C<Object>();
Object ret = instance.foo(new Integer(0)); // 接受Number的参数;但返回值Object,一般用于,修改数据。
C<? extends Number> 适合返回类型,而且不能传入参数,容器能向上兼容
如
C<? extends Number> instance = new C<Integer>();
Number ret = instance.foo(null); // 不接收参数,但返回Number,一般用于,获取数据。
五. wildcard嵌套 <? extends|super ? extends|super T>
这部分其实没什么意义,可以看成<? super T>和<? extends T>,仅仅为了语言的完整性
以下用例子说明:
public class C<T> {
public C<? super T> foo(C<? super T> v) {
return v;
}
public C<? extends T> bar(C<? extends T> v) {
return v;
}
}
C<? super Number> s = null;
C<? extends Number> e = null;
C<? super Number> sInstance = new C<Object>();
C<? super Number> ret1 = sInstance.foo(null);
C<?> ret2 = sInstance.bar(e);
C<? extends Number> eInstance = new C<Integer>();
C<?> ret3 = eInstance.foo(s);
C<? extends Number> ret4 = eInstance.bar(null);
View Code
归纳如下:
<? super ? super T> 参数类型:null,返回值<? super T>
<? extends ? super T> 参数类型:<? extends T>,返回值<?>
<? super ? extends T> 参数类型<? super T>,返回值<?>
<? extends ? extends T> 参数类型为null, 返回值<? extends T>