zoukankan      html  css  js  c++  java
  • EffectiveJava——请不要在代码中使用原生态类型

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

    /**
     * 请不要在新代码中使用原生态类型
     * @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还是会报错的。

  • 相关阅读:
    event loop笔记
    webpack不同devtools打包对比
    windows 7系统搭建本地SVN服务器的过程
    Eclipse安装SVN插件
    总结eclipse中安装maven插件
    myeclipse building workspace如何禁止及提高myeclipse速度
    基于SAML的单点登录介绍
    使用 CAS 在 Tomcat 中实现单点登录
    SSO之CAS备忘
    Maven环境变量配置
  • 原文地址:https://www.cnblogs.com/babycomeon/p/5598697.html
Copyright © 2011-2022 走看看