effective java(23) 之请不要在新代码中使用原生态类型

effective java 之请不要在新代码中使用原生态类型


1、声明中具有一个或者多个类型参数(type parameter)的类或者接口,就是泛型。泛型类和泛型接口统称为泛型(generic type)。


2、每种泛型定义一组参数化的类型,构成格式为:先是类或者接口的名称,接着用尖括号(<>)把对应于泛型形式类型参数的实际类型参数列表括起来。


3、原生态类型就像从类型声明中删除了所有的泛型信息一样。实际上,原生态类型List与Java平台没有泛型之前的接口类型List完全一样。
如果不提供类型参数,只是使用集合类型和其他泛型的原生态类型仍然是合法的,但是不应该这么做。如果使用原生态类型,就失掉了泛型在安全性和表述性方面的所有优势。


4、既然不应该使用原生态类型,为什么Java还要允许使用原生态类型呢?
因为这是为了兼容性,因为在JDK1.5之前,Java已经进入它的第二个十年,而在这之前,Java没有泛型,为了以前的代码的仍然能够正常使用,促使Java仍然支持原生态类型。


5、虽然不应该在新代码中使用像List这样的原生态类型,使用参数化的Object类型以允许插入任意对象,如List<Object>,这还是可以的。


6、原生态List类型和List<Object>类型之间的区别:不严格的说,前者逃避了泛型检查,后者则明确告知编译器,它能够持有任意类型的对象。


7、可以将List<String>类型的对象赋给原生态List类型的变量,但是不能将List<String>类型的对象赋给List<Object>类型的变量。
因为泛型有自己的子类型化的规则,List<String>是原生态List的一个子类型,而不是参数化类型List<Object>的子类型。
因此使用像List这样的原生态类型,就会失掉类型安全性,但是如果使用像List<Object>这样的参数化类型,则不会。


8、在不确定或者不在乎集合中的元素类型的情况下,你也许会使用原生态类型。但是使用原生态类型是很危险的。


9、为了避免使用原生态类型,但是在不确定或者不在乎这个集合中应该存放哪种类型的对象时,Java提供了一种安全的替代方法,称作无限制的通配符类型。
如果要使用泛型,但不确定或者不关心实际的类型参数,就可以使用一个问号代替。


public static  void  testMethod(Set<?>  s1 , Set<?>  s2)
{
………
}


10、不要在新代码中使用原生态类型(raw type)  两个小小的例外,两者都源于“泛型信息可以在运行时被擦除”这一事实。
1.在类对象的使用时,必须使用原生态类型。
规范不允许使用参数化类型。List.class,String[].class,int.class都是合法的,但是List<String>.class,List<?>.class则不合法。
2. s1  instanceof  Set是合法的,s1  instanceof  Set<?> 是不合法的。
一旦确定s1是Set集合,就必须将它转化成为通配符类型Set<?>,而不是转换成原生态类型Set。


11、一个实例
	public class ListDemo {
		public static void main(String[] args) {
			List<String> stringList = new ArrayList<String>();


			// 方法add1和add2显示了List和List<Object>的区别


			/*
			 * 方法add1由于参数是List,当把List<String>作为参数传进来时,list添加了一个Integer类型,
			 * string列表中添加了Integer类型的元素,破坏了安全性
			 */
			add1(stringList, new Integer(1));
			// 出错,因为是Integer类型
			String s = stringList.get(0);
			System.out.println(s);
			//Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String


			// 方法add2无法通过编译,因为无法接受 List<String>作为参数
			//可以将List<String>类型的对象赋给原生态List类型的变量,但是不能将List<String>类型的对象赋给List<Object>类型的变量。
			add2(stringList, new Integer(1));


			// 方法add1和add3显示了List和List<?>的区别


			// 方法add3无法通过编译,List<?>一般只能用于读取,不能add,除非是null
			add3(stringList, new Integer(1));

		}


		private static void add1(List list, Object o) {
			list.add(o);
		}
		private static void add2(List<Object> list, Object o) {
			list.add(o);
		}
		private static void add3(List<?> list, Object o) {
			list.add(o);// 错误
			list.add(null);// 正确,可以添加null
		}
	}




每天努力一点,每天都在进步。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

powerfuler

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值