本篇记录了Java泛型的部分要点,内容主要参考《effective java》中泛型一章,文章将提纲挈领列举Joshua Bloch对Java泛型的使用建议。
文章目录
一、新代码中不要用原始类型(rawtype)
原因不赘述了。只是有几点需要注意:
1、List与List< Object>
- List : 逃避了类型检查
- List< Object>:告知编译器,它能够持有任何类型的对象
- 泛型有子类型化(subTyping)的规则,List< String> 是原生态类型List 类型的一个子类型,但不是参数化类型List < Object>的子类型
- 可将List< String> 传给List 类型的参数,但是不能将List< String> 传给List< Object> 类型的参数,所以List是失去了类型检查,而List< Object>并没有。
下面来看几个对应的demo:
// demo 1 :测试类型List 与List<String>
public static void main(String[] args) {
List<String> stringList = new ArrayList<>();
unsafeAdd(stringList, 1L);
//java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.String
String s = stringList.get(0);
}
// 躲过了类型检查
private static void unsafeAdd(List stringList, Object o) {
stringList.add(o);
}
// demo2: 测试List<String> 与List<Object>的关系
public static void main(String[] args) {
List<String> stringList = new ArrayList<>();
// List<string> 并不是 List<Object> 的子类型,所以此处编译不通过
unsafeAdd(stringList, 1L);
}
// 躲过了类型检查
private static void unsafeAdd(List<Object> stringList, Object o) {
stringList.add(o);
}
2、Set与Set< ?> 、Set< Object>
Set< ?>:
如果不确定或者不关心实际的类型参数,可以无限制通配符.Set< ?>读作“某个类型的集合”,表示可以持有任意一种类型的集合。
Set< Object>:
可以持有任意类型的集合。
demo1:
static void add(Set<?> set, Object o) {
// Error:(34, 12) java: 对于add(java.lang.Object), 找不到合适的方法
// 方法 java.util.Set.add(capture#1, 共 ?)不适用
// (参数不匹配; java.lang.Object无法转换为capture#1)
set.add(o);
}
demo2:
static Object get(Set<?> set) {
Object next = set.iterator().next();
return next;
}
可见Set< ?> 里,是无法放入任何元素的(不讨论null),而且拿出来的元素都是Object类型。
可见Set< ?> 里,是无法放入任何元素的(不讨论null),而且拿出来的元素都是Object类型。
可见Set< ?> 里,是无法放入任何元素的(不讨论null),而且拿出来的元素都是Object类型。
重要的事情,我们说三遍!
3、必须使用raw type 的场合
- 在类字面量中必须使用raw type ,即List.class
- 使用instanceOf 操作符时必须使用raw type
/*利用泛型来使用instanceOf 的推荐方法,一旦返现这collection是 List,就必须转为
* List<?> ,而不是List。这是受检转换,不会导致编译时警告*/
static void instance(Collection collection) {
if (collection instanceof List) {
List<?> list = (List<?>) collection;
}
}
4、标准的泛型术语
泛型这块的各种翻译极易混淆,需要注意:
List< String> --> 参数化类型–> parameterized type
String --> 实际参数类型 --> Actual type parameter
List< E> -->泛型 -->generic type
List< ?> --> 无限制通配符类型–>Unbounded wildcard type
List< ? extends Number> -->有限制通配符类型 -->Bounded wildcard type
List --> 原型 --> raw type
< T extends Number> -->有限制类型参数
<T extends Comparable< T>> --> Recursive type bound --> 递归类型限制
static < E> List< E> asList(E[] a) --> generic method --> 泛型方法