java1.5发行版本中增加了泛型。在没有泛型之前,从集合中读取到的每一个对象都必须进行装换。如果有人不小心插入了类型错误的对象,在运行时的装换处理器就会出错。有了泛型之后,可以告诉编译器每个集合中接受那些对象类型。编译器自动为你的插入进行转化,并在编译器告知是否插入了类型错误对象。这样可以使程序更加安全,也更加清楚,但是要享有这些优势有一点的难度。

定义
具有一个或者多个类型参数的类或者接口。

泛型类或者接口统称为泛型。

在java1.5版发行之前,没有泛型时,集合声明:

// Now a raw collection type - don't do this!/*** My stamp collection, Contains only Stamp instance.*/private final Collection stamps = ...;

如果不小心将一个coin放进了stamp集合中,这一错误的插入照样得以编译和运行并且不会出现任何错误提示:

// Erroneous insertion of coin into stamp collection
stamps.add(new Coin( ... ));

直到从stamp集合中获取coin时才会收到错误提示。

//Now a raw interator type - don't do this !
for (Iterator i = stamps.iterator(); i.hasNext();) {Stamp s = (Stamp) i.next(); // Throws ClassCastException... // Do something with the stamp
}

出错之后应该尽快发现,最好是编译时就发现。上述例子,直到运行时才发现错误,已经错误了很久。

有了泛型,就可以改进后的类型声明来代替集合中的这种注释,告诉编译器之前的注释中所隐含的信息:


// Parameterized collection type - typesafe
private final Collection<Stamp> stamps = ...;

通过这条声明,编译器直到stamps应该只包括Stamp实例,并给予保证,假设整个代码是利用java 1.5机器之后的编译器进行编译的,所有代码在编译国企成都没有发出任何警告。当stamps利用一个参数化的类型进行声明时,错误的插入会产生一条编译时的错误消息,准确地告诉你那里出错了。

还有一个好处是:从集合中取元素时不需要再进行手动的转换了,编译器会替你插入隐士的转换,并确保他们不会失败,无论你是否使用for-each循环,上述功能都适用。

// for-each loop over a parameterized collection - typesafe
for(Stamp s:stamps){//No cast // Do something with the stamp
}

或者无论是否使用传统的for循环也一样

// for loop with parameterized iterator declaration - typesafe
for(Iterator<Stamp> i=stamps.iterator();i.hasNext;{Stamp s=i.next();//No cast necessary //Do something with the stamp
}

原生态的List和参数化的类型List《Object》之间有什么区别呢?不严格的讲,前者逃避了泛型检查,后者明确告诉编译器,它能够持有任意类型的对象。虽然可以将List《String》传递给类型为List的参数,但是不能将它传给类型为List《Object》的参数。

如果使用像List这样的原生态类型,就会失掉类型安全性,但是如果使用像List《Object》 这样的参数化类型,则不会。

// Use raw type (List) - fails at runtime!
public static void main(String[] args) {List<String> strings = new ArrayList<String>();unsafeAdd(strings, new Integer(42));String s = strings.get(0); // Compiler - generated cast
}private static void unsafeAdd(List list, Object o) {list.add(o);
}

这个程序可以运行,但是因为使用了原生态List,会收到警告。

如果在调用unsafeAdd声明中用参数化类型List代替原生态List,并试着重新编译这段程序,会发现它无法再进行编译。

//Use of raw type for unknow element type - don't do this
static int numElementsInCommon(Set s1,Set s2){int result=0;for(Object o1:s1){if(s2.contains(o1)return result++;}return result;
}

这个倒是可以,但它使用了原生态类型,这是很危险的。从java 1.5发行版本开始,java就提供了一种安全的替代方法,称作:无限制的通配符类型。

如果要使用泛型,但不确定或者不关心实际的类型参数,就可以使用一个问号代替。例:

static int numElementsInCommon(Set<?> s1,Set<?> s2){int result=0;for(Object o1:s1){if(s2.contains(o1)
            return result++;}
        return result;
}

Set与Set《?》区别:
后者是安全的,前者则不安全。

总之,使用原生态类型在运行时会导致异常,因此不要再新代码中使用。

Effective Java 泛型 第23条:请不要在新代码中使用原生态类型相关推荐

  1. Effective Java之请不要在新代码中使用原生态类型(二十三)

    1.泛型与原生态类型的概念 泛型就是带一个或多个类型参数E的类或者接口,而原生态类型是不带任何实际类型的泛型,例如List是原生态类型,List < String >或者List< ...

  2. Effective Java 泛型 第28条:利用有限制通配符来提升API的灵活性

    如第25条所述,参数化类型是 不可变的(invariant).换句话说,对于任何两个截然不同的类型tyle1和type2来说,List< Type1>既不是List< Type2&g ...

  3. Effective Objective-C 2.0 — 第二条:类的头文件中尽量少引入其他头文件

    第二条:类的头文件中尽量少引入其他头文件 使用向前声明(forward declaring) @class EOCEmployer 1, 将引入头文件的实际尽量延后,只在确有需要时才引入,这样就可以减 ...

  4. Java不满足的依赖异常_不要依赖代码中的异常

    因为异常大大地降低性能,所以您不应该将它们用作控制正常程序流程的方式.如果有可能检测到代码中可能导致C# 因为异常大大地降低性能,所以您不应该将它们用作控制正常程序流程的方式.如果有可能检测到代码中可 ...

  5. java多态优化多个if_脑壳疼!代码中那么多“烦人”的if else

    if else 是我们写代码时,使用频率最高的关键词之一,然而有时过多的 if else 会让我们感到脑壳疼. 图片来自 Pexels 例如下面这个伪代码: 是不是很崩溃?虽然他是伪代码,并且看起来也 ...

  6. [Effective JavaScript 笔记]第23条:永远不要修改arguments对象

    arguments对象并不是标准的Array类型的实例.arguments对象不能直接调用Array方法. arguments对象的救星call方法 使得arguments可以品尝到数组方法的美味,知 ...

  7. java泛型循环break continue_循环结构练习(示例代码)

    青鸟迷你游戏平台开发 1.选择游戏 ----- switch选择结构 public class Test { public static void main(String[] args) { Syst ...

  8. java 多线程取一条记录_java多线程从队列中取出数据执行

    天涯尽头无女友 楼上的解释完全正确,不过可以利用s.poll()返回值是否为null,作为跳出条件.下面诗完整代码.packagecom.demo;importjava.util.ArrayList; ...

  9. 运行java提示未签名_java – JNLP:在签名代码中加载未签名的代码

    我们在克服Java webstart的混合代码错误时遇到了困难.总之,我们有我们的主要JNLP文件,我们已经签署了它直接加载的所有代码.我们已将all-permissions选项添加到主JNLP中.它 ...

最新文章

  1. C++核心编程(三)
  2. 洛谷—— P1605 迷宫
  3. nginx反向代理cas-server之2:生成证书,centOS下使用openssl生成CA证书(根证书、server证书、client证书)...
  4. php 接收 oc 图片上传,php yii2接口中图片上传
  5. Pandas常用技巧总结
  6. linux内核支持浮点吗,【转】Linux内核浮点计算支持
  7. java解析dxf文件_浅析JVM方法解析、创建和链接
  8. JAVA进阶开发之(二维数组)
  9. Cookie、Session 和 Token区别
  10. ucGUI 架构介绍
  11. 机会是留给有准备的人
  12. 程序员面试宝典——第6章
  13. 学会这个前端特效520还怕没CP伴侣
  14. ArcGIS API For JavaScript 利用GP服务生成等值线、等值面(一)之生成等值线
  15. 树莓派4B-连接Air720U模块抓取数据日志
  16. 计算机应用基础单选题10an,计算机应用基础10考(附答案).doc
  17. Java语言之父James Gosling
  18. TinyXml 介绍
  19. 小红伞AntiVir专区
  20. Part 13 (1) Fourier级数基本概念与应用

热门文章

  1. contine 和 break — 打工人的幸福周六
  2. 可调电阻封装图_嵌入式硬件电路杂谈(二)贴片电阻选用
  3. 小米平板 粉色版 16GB,不可以听书
  4. 引起失眠的原因有哪些,为什么会失眠呢?
  5. 对于苹果手机(ios)微信浏览器 ajax请求无法响应问题
  6. C++经典问题 猴子偷桃
  7. 《奥日与精灵意志》是如何完成近乎不可能的Switch移植任务的?
  8. CSS flex 布局里面的靠右对齐
  9. BaiduMap---百度地图官方Demo之图层展示(展示普通图,卫星图,交通流量图及百度城市热力图)
  10. SpringMVC的运行流程(一)