看如下一个泛型的例子:
- // Initial attempt to generify Stack = won't compile!
- public class Stack<E> {
- private E[] elements;
- private int size = 0;
- private static final int DEFAULT_INITIAL_CAPACITY = 16;
- public Stack() {
- elements = new E[DEFAULT_INITIAL_CAPACITY];
- }
- public void push(E e) {
- ensureCapacity();
- elements[size++] = e;
- }
- public E pop() {
- if (size == 0)
- throw new EmptyStackException();
- E result = elements[--size];
- elements[size] = null;
- return result;
- }
- public boolean isEmpty() {
- return size == 0;
- }
- private void ensureCapacity() {
- if (elements.length == size)
- elements = Arrays.copyOf(elements, 2 * size + 1);
- }
- }
上面这个泛型栈的例子会存在一个错误,25条说过,E是不可具化的,而数组是可具化的,所以不能用E来使用诸如new E[]这样的数组申请方法,为了解决这个问题,我们可以将new E[]改为new Object[]。至此,又得到了一条警告信息,因为我们要把Object型的数组赋给E型,因为编译器无法确定E的具体类型,所以警告这是不是类型安全的。但是由于elements只有在push中使用,且压进的是E型元素,所以我们可以判断出这是安全的,因此加上强制类型转换(E())new Object[...],这是解决上面错误问题的每一种方法。但是必须确保未受检的转换不会危及到程序的类型安全,相关的数组保存在一个私有域中,永远不会被返回到客户端去,或者传递给任何方法,也就是说存在不稳定的因素,但是是完成在服务端可控的。一旦证明了未受检转换是安全的,就要在尽可能小的范围内禁止警告,在这种情况下,构造器只包含未受检的数组创建,因此可以在整个构造器中禁止这条警告。
消除错误的第二种方法是直接把elements声名为Object类型的,但是,这又会在
- E result = elements[--size];
引入一条错误,同样的,我们可以加入强制类型转换来解决这个问题
- E result = (E)elements[--size];
与第一种情况类似。这也会得到一条警告,同样的,也可证明这种情况下是安全的,所以可以禁止该警告。依据最小化原则,应该直接在此名上加注释来禁止警告。
这两种方法,一般来说禁止数组类型的未受检转换比禁止标题类型更危险,所以建议使用第二种方法。但是在比这个例子更实际的泛型中,或许代码中会有多个地方需要从数组中读取元素,因此第一种方法比第二种方法开销更小一些,这也是第一种方法更常用的原因。这个例子看起来违反了25条(它告诉我们对于泛型列表要优于数组),实际上因为JAVA并不是生来就支持列表,所以有些泛型如ArrayList必须使用数组来实现,有的时候为了提升性能,也会考虑用数组来实现,比如HashMap。
有一些泛型限制了可允许的类型参数值。例如
- class DelayQueue<E extends Delayed> implements BlockingQueue<E>;
类型参数列表要求实际的类型参数E必须是java,util.concurrent.Delayed的一个子类型,它允许DelayQueue实现及其客户端在DelayQueue元素上利用Delayed方法,无需显示的转换,注意,第一个类型都是自身的子类型,因此创建DelayQueue<Delayed>是合法的。
总之,使用泛型比使用需要在客户端代码中进行转化的类型来的更安全。也更容易,在设计新类的时候,要确保它们不需要这种转换就可以使用。这通常意味着要把类做成是泛型的。
相关推荐
但要依据存储要求不同(如读优先还是写优先)选择适合的集合类 型。此外,本章还介绍了 Java 泛型编程。限于篇幅,我们没有详细研究泛型编程技术。如果要深 入了解泛型编程,请查阅相关资料。 习 题 上机实践 1.将...
您应该考虑使用此框架: 创建(丰富)Web应用程序考虑或开始使用 需要一致的用户界面希望少担心UI的可维护性,并希望在尽可能短的时间内构建它想念您使用服务器端语言使用的LINQ(或其他DSL用于对象)和泛型,...
原则如果已经有广泛使用的术语,优先考虑(×属性/◯属性,×模式匹配/◯模式匹配)尽量翻译成日文(×存物/◯存物)如果您无论如何都无法翻译成日语,请尽可能使用片假名,除了关键字代码(×模式/◯模式)转换为...
可移除属性类型和转换至类型脚本,优先考虑转换后代码的兼容性,减少手动修正的代码量,以实现快速迁移。特征: 代理PropTypes到React.Component泛型类型及排除PropTypes 根据初始状态, setState()调用以及this....
java lru leetcode README leetcode题目分类 1.数组 2.Linked List (注意如果是两个Integer类型进行比较要用equals,有赞笔试真题,要学会在原地解决这个...9.深度优先搜索和广度优先搜索 每日一题 10.贪心算法 11.
Bootstrap 是全球最受欢迎的前端组件库,用于开发响应式布局、移动设备优先的 WEB 项目。 Bootstrap 是一套用于 HTML、CSS 和 JS 开发的开源工具集。利用我们提供的 Sass 变量和大量 mixin、响应式栅格系统、可扩展...
4.4.8 考虑使用SoftReference 4.5 小结 第5课 表达式中的陷阱 5.1 关于字符串的陷阱 5.1.1 JVM对字符串的处理 5.1.2 不可变的字符串 5.1.3 字符串比较 5.2 表达式类型的陷阱 5.2.1 表达式类型的自动提升 ...