概述
- Effective Java 读书笔记四泛型
- 请不要在新代码中使用原生态类型
- 消除编译时的非受检警告
- 列表 List 优先于数组
- 优先考虑泛型
- 优先考虑泛型方法
- 利用有限制通配符来提升 API 的灵活性
- 优先考虑类型安全的异构容器
Effective Java 读书笔记(四):泛型
请不要在新代码中使用原生态类型
声明中使用一个或多个类型参数的类或接口,就是泛型类或接口,统称为泛型。每个泛型都有一个相对应的原生态类型,即不带任何实际类型参数的泛型名称,比如 List< E> 的原生态类型是 List。
使用原生态类型,就失掉了泛型在安全性和表达性方面的所有优势。Java 中允许使用原生态类型,只是为了兼容性。安全性和表达下说详细一点儿就是:
1. 缺少了泛型所具有的编译时类型安全特性。
2. 需要进行显式的类型转换。
在实际中可以使用无限制通配符类型 List< ? > 、有限制通配符类型 List< ? extends T> 或 List< Object> 来代替原生态类型。
还有一些地方必须使用原生态类型:
1. 类文字 class literal:List.class 是合法的,List< String>.class 是不合法的。
2. 使用 instanceof 判断类型时。
一些术语总结如下:
术语 | 示例 |
---|---|
参数化的类型 | List< String> |
实际类型参数 | String |
泛型 | List< E> |
形式类型参数 | E |
无限制类型参数 | List< ? > |
原生态类型 | List |
有限制类型参数 | List< E extends Number> |
有限制通配符类型 | List< ? extends Number> |
递归类型限制 | < T extends Comparable< T>> |
泛型方法 | static E List< E> asList(E[] a) |
消除编译时的非受检警告
每一条警告都表示可能在运行时抛出异常,要尽最大努力消除警告。如果无法消除,但可以证明引起警告的代码是类型安全的,那就可以使用 @SuppressWarnings(“unchecked”) 注解禁止该警告。注意,要用注释把禁止警告的原因记录下来。
SuppressWarnings 可以用于任何粒度的代码中:局部变量声明、方法、类,实际中应该在尽可能小的范围内使用 SuppressWarnings 注解。
列表 List 优先于数组
数组和列表有哪些不同呢?
1. 数组是协变的,泛型是不可协变的。
2. 数组是具体化的,能够在运行时检查元素类型约束。而泛型会在编译时进行类型擦除,导致泛型可以与没有使用泛型的代码随意互用。
以上区别导致,数组和泛型不能很好的混合使用,比如不能创建泛型的数组。比如 new List< E>[]、new E[]、new List< String>[] 都是非法的。
像 E、List< E> 和 List< String> 这样的类型应称作不可具体化的类型。不可具体化的类型是指运行时表示法包含的信息比它的编译时表示法包含的信息更少的类型。
优先考虑泛型
public class ArrayList {
transient Object[] elementData; // non-private to simplify nested class access
public Object get(int index) {
return elementData(index);
}
}
假如 ArrayList 写成上面的样子,那就需要使用方自己去做类型转换了,而且缺少先是类型安全,容易放入错误类型的对象。下面的 ArrayList 使用了泛型,不仅类型安全,而且使用更方便,不需要显示类型转换了。
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
transient Object[] elementData; // non-private to simplify nested class access
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
@SuppressWarnings("unchecked")
E elementData(int index) {
return (E) elementData[index];
}
}
优先考虑泛型方法
使用泛型方法的原因和使用泛型类基本一致。
利用有限制通配符来提升 API 的灵活性
- 当参数用于 producer 的时候,使用 extends。
- 当参数用于 consumer 的时候,使用 super。
类型推导规则很复杂,当编译器无法推到出类型参数时,可以显示指定类型参数。
优先考虑类型安全的异构容器
异构容器是指能够容纳不同类型对象的容器,实现异构容器时,优先考虑使用泛型来实现类型安全的异构容器,这对于使用方来说好处多多。
public class Favorites {
private final Map<Class<?>, Object> favorites = new HashMap<>();
public <T> void put( Class<T> key, T value ) {
favorites.put( key, value );
}
public <T> T get( Class<T> key ) {
return key.cast( favorites.get( key ) );
}
}
最后
以上就是聪明黄豆为你收集整理的Effective Java 读书笔记(四):泛型Effective Java 读书笔记(四):泛型的全部内容,希望文章能够帮你解决Effective Java 读书笔记(四):泛型Effective Java 读书笔记(四):泛型所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复