先看一个栗子,看看能不能找出来里面的错误:

/**
* 请不要在新代码中使用原生态类型
* @author weishiyao
*
*/
public class Test { public static void main(String[] args) {
List<String> strings = new ArrayList<>();
unsafeAdd(strings, new Integer(42));
String string = strings.get(0);
System.out.println(string);
} private static void unsafeAdd(List list, Object object) {
list.add(object);
}
}

  运行一下,看一下报错结果:

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at com.weishiyao.effectiveJava.entry23.Test.main(Test.java:16)

  对的,是一个ClassCastException,这是一个编译器声称的转换,因此一般会保证成功,但是我嘛在这个栗子中忽略了一条编译器的警告,就会为此而付出代价。

  但是,如果用unsafeAdd(List<Object> list, Object object)代替原生的List类型,我们的IDE会直接报错。

  在不确定或者不在乎集合中元素类型的情况下,你也许会使用原生态的类型。例如,假设想要编写一个方法,它有两个集合(set),并从中返回他们公有的元素的数量。如果不熟悉范型的话,可以参考以下方式来编写这种方法:

	static int numElementsInCommen(Set s1, Set s2) {
int result = 0;
for (Object object : s1) {
if (s2.contains(object)) {
result++;
}
}
return result;
}

  这个方法倒是可行,但是它使用了原生态类型,这是很危险的。从java1.5发行版本开始,java就提供了一种安全的替代方法,称作无限制的通配符类型,如果要使用范型,但是确定或者不关心实际的参数类型,就可以用一个问号代替。例如范型Set<E>的无限制通配符类型为Set<?>。这是最普通的参数化Set类型,可以持有任何集合。

  在无限制通配类型Set<?>和原生态类型Set之间有什么区别呢?这个问号真正起到作用了么?这一点不需要赘述,但通配符类型是安全的,原生态类型则不安全。可以将任何元素放入使用原生态类型的集合中,因此很容易破坏该集合类型的约束条件;但不能将任何元素(除了null)放到Collection<?>中。

  不要在新代码中使用原生态类型,这条规则有两个小小的例外,两者都源于“范型信息可以在运行时被擦除”这一事实。在类文字中必须使用原生形态。规范不允许使用参数化类型。换句话说,List.class,String[].class和int.class都是合法的。但是List<String>.class和List<?>则不合法。

  这条规则第二个例外与instanceof操作符有关。由于范型信息可以在运行时被擦除,一次在参数化类型而非无限制通配符上使用instanceof操作符时非法的。用无限制通配符类型代替原生态类型,对instanceof操作符的行为不回产生任何影响。在这种情况下,尖括号<>和问号?就显得多余了。下面是利用范型来使用instanceof操作符的首选方法:

				if (object instanceof Set) {	// Raw type
Set<?> m = (Set<?>) object; // Wildcard type
}

  注意,一旦确定这个object是个Set,就必须将他转换成通配符类型Set<?>,而不是原生类型,这个是受检的,否则的话我们的IDE还是会报错的。

EffectiveJava——请不要在代码中使用原生态类型的更多相关文章

  1. effective_java第23条:请不要新代码中使用原生态类型

    从这条开始涉及泛型相关的点. 从JDK5开始Java新增了“泛型”新特性,例如:List<String>,在这之前则只有List不会限定类型. 如今的JDK版本中还是可以写原生类型,但这会 ...

  2. EffectiveJava(23)为什么不能在新生代码中使用原生态类型

    泛型类和泛型接口 声明一个或者多个类型参数的类或者接口. 为什么不要在新代码中使用原生态类型 原生态类型,即泛型不带参数的类型 如List的list,list就是其原生态类型 1.使用原生态类型,插入 ...

  3. Effective java 系列之避免过度同步和不要使用原生态类型,优先考虑泛型

    避免过度同步(67):在一个被同步的方法或代码块中,不要调用哪些被设计成被覆盖的方法或者是由客户端以函数对象的形式提供的方法(21). 有点拗口,书上提供的创建者与观察者模式,add方法太多,看得眼花 ...

  4. 在Visual Studio代码中使用Flask

    Flask是一个用于Web应用程序的轻量级Python框架,它提供了URL路由和页面呈现的基础知识. Flask被称为“微”框架,因为它不直接提供表单验证,数据库抽象,身份验证等功能.这些功能由称为F ...

  5. Dynamics AX 2012 R2 从代码中调用SSRS Report

    平时,我们制作SSRS Report的方法主要有两种:使用Query或RDP.如果需要为报表传递参数,就要在代码中为报表参数赋值,然后在代码中调用报表.下面我总结下这两种报表在代码中传参和调用的方式: ...

  6. 「Flink」Flink中的时间类型

    Flink中的时间类型和窗口是非常重要概念,是学习Flink必须要掌握的两个知识点. Flink中的时间类型 时间类型介绍 Flink流式处理中支持不同类型的时间.分为以下几种: 处理时间 Flink ...

  7. 该对象尚未初始化。请确保在所有其他初始化代码后面的应用程序启动代码中调用 HttpConfiguration.EnsureInitialized()。

    WebAPI使用属性路由,配置config.MapHttpAttributeRoutes();后出现错误: System.InvalidOperationException: 该对象尚未初始化.请确保 ...

  8. 【转】代码中特殊的注释技术——TODO、FIXME和XXX的用处

    (转自:http://blog.csdn.net/reille/article/details/7161942) 作者:reille 本博客网址:http://blog.csdn.net/reille ...

  9. linux内核分析作业4:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

    系统调用:库函数封装了系统调用,通过库函数和系统调用打交道 用户态:低级别执行状态,代码的掌控范围会受到限制. 内核态:高执行级别,代码可移植性特权指令,访问任意物理地址 为什么划分级别:如果全部特权 ...

随机推荐

  1. Atitit js中的依赖注入di ioc的实现

    Atitit js中的依赖注入di ioc的实现 全类名(FQCN)为标识符1 混合请求模式1 使用类内  builder  即可..2 Service locator method走ok拦2 Jav ...

  2. iOS-数据持久化基础-JSON与XML数据解析

    解析的基本概念 所谓“解析”:从事先规定好的格式串中提取数据 解析的前提:提前约定好格式.数据提供方按照格式提供数据.数据获取方按照格式获取数据 iOS开发常见的解析:XML解析.JSON解析 一.X ...

  3. Win7系统.net framework 4.0没有注册导致部署在IIS的站点跑不起来怎么办

    win7装了VS再装IIS,结果IIS里面有.NET4.0,但是程序始终是跑不起来,怎么办呢? 分析觉得可能是因为4.0没有注册到IIS,在win7下如果先安装vs2010 (附带会安装Microso ...

  4. php使用正则过滤js脚本代码实例

    匹配的规则不能用 "/<script.*<\/script>/i",因为它不能匹配到换行符,那么多行js就匹配不掉了. 要用 "/<script[ ...

  5. WPF自定义控件与样式(7)-列表控件DataGrid与ListView自定义样式

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: Dat ...

  6. java JFileChooser选择文件和保存文件

    //文件过滤器import java.io.File; import javax.swing.filechooser.FileFilter; public class MyFilter extends ...

  7. poj 3352Road Construction(无向双连通分量的分解)

    /* 题意:给定一个连通的无向图G,至少要添加几条边,才能使其变为强连通图(指的是边强联通). 思路:利用tarjan算法找出所有的双联通分量!然后根据low[]值的不同将双联通分量 进行缩点,最后图 ...

  8. tomcat触发ServletContext初始化监听事件的源码(原创)

    tomcat 8.0.36 知识点: 动态监听器的好处可以根据环境条件进行选择性添加. 静态监听器有七类. ServletContextAttributeListener ServletRequest ...

  9. 机器学习&数据挖掘笔记_20(PGM练习四:图模型的精确推理)

    前言: 这次实验完成的是图模型的精确推理.exact inference分为2种,求边缘概率和求MAP,分别对应sum-product和max-sum算法.这次实验涉及到的知识点很多,不仅需要熟悉图模 ...

  10. 学习制作精美 CSS3 按钮效果的10个优秀教程

    由于互联网世界正在发生变化,人们往往喜欢那些有更多互动元素的网站,因此现在很多 Web 开发人员也在专注于提高他们的 CSS3 技能,因为 CSS3 技能可以帮助他们在很大的程度上实现所需的吸引力.这 ...