第二十三条:不要在新代码中使用原生类型
2016-09-03 16:14
281 查看
一、泛型的术语
类型参数:public class Request<E>{} 其中的E就是类型参数。参数化类型:List<String> 这叫做参数化类型。
原生类型:List 没有泛型的类,叫做原生。
补:在JAVA中是不推荐使用原生类型的,但是为什么不将原生类型去掉?
因为泛型引入是在JAVA产生的20年后,为了向上兼容以前的代码,所以就保持了原生类型。
二、泛型的优点
①、能够在编译期间报错public static void main(String[] args) { // TODO Auto-generated method stub List<String> stringList = new ArrayList<>(); stringList.add("asd"); stringList.add(1);//报错:无法存储Integer类型 }而以前的代码只能够调用的时候,发现ClassCastException的错误
②、能够隐式转换(就是我输入的是String,那么我获取到的数据也是String)
public static void main(String[] args) { // TODO Auto-generated method stub List<String> stringList = new ArrayList<>(); stringList.add("asd"); for(String str : stringList){ System.out.println(str); } }以前的代码,存储的都是Object类型,所以获取之后需要自己强制转换。
三、泛型的一些特征
①、子类化规则List<String> != List<Object> 虽然它们同为List.class类。
这很好理解,因为里面存储的内容不一样,那么这个容器的类型也就不一样。(比如说茶壶和酒壶)
但是这个机制同时会引发一个问题:
Integer是Number的子类,但是List<Number> list != new List<Integer>()。
按道理来说List<Number> 应该是List<Integer>的父类,应该可以向上转型才是呀,可是根本无法使用。
这种方式是对的,因为当向上转型之后,就表示可以装入Number的子类,比如double,但是double并不是Integer的子类,不能放在List<Integer>的容器中。
例:
public static void main(String[]args){ List<Number> list = new ArrayList<Integer>(); double a = 1.34; list.add(a); }这样其实为List<Integer>的容器就装入了Double类的成员变量,这样就违反了类型约束的规则。
②、原生类型可支持所有泛型
List<String> stringList = new ArrayList<>(); List<Object> objList = new ArrayList<>(); //"大哥"我能支持所有类型赋值 List list = objList; list = stringList<span style="font-family: Arial, Helvetica, sans-serif;">;</span> //并且还能装填各种数据 list.add(1); list.add("string"); list.add(new Object()); //List<Object> 我也能装填各种类型,而且我还有类型检验 objList.add(1); objList.add("string"); objList.add(new Object());
但是如果使用原生类型,就代表放弃了类型安全检验。
使用的时候就会产生错误:
String str = stringList.get(0);就会报错(ClassCastException):
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at Main.main(Main.java:12)
③、无限通配符(?)
JAVA为了解决原生类型不安全的问题,所以产生了无限通配符 来解决这个问题。
使用:只需要List 变成List<?>就可以了。
那么无限通配符真的起到作用了吗?
从意义上讲,是的。
因为List<?>被认为是安全的,而List被认为是不安全的。
至少List<?>没有警告 - -。
但是,事实上还是破坏了类型约束条件。
所以,为保证类型安全,Collection<?>是无法存储null以为的数据的。
④、必须使用原生类型的情形。
原因:因为泛型具有擦除的问题。
什么叫做擦除:指的是,在运行期间,使泛型可以使没使用泛型的代码之间互相的转换。
情形1、使用类文字的时候必须使用原生类型
例:可以使用List.class、String[].class、int.class
但是却不可以使用List<String>.class,List<?>.class
因为,JAVA的擦除会导致List<String>.class其实还是List.class,那么List<String>、List<Object>本不相同的东西,就变成一样了。
情形2、使用instanceof是违法的
例:
List<String> list = new ArrayList<>();
if (list instanceof List<String>) {}//由于擦除问题,这样同样是非法的。
所以一般方式是这样处理的:
if (list instanceof List){
List<?> myList = (List<?>) list;//保证类型安全
}
相关文章推荐
- 偏执却管用的10条Java编程技巧
- python中*和**的用法
- CI框架的自动验证
- 浙江大学 PAT 编程初级2
- C语言之goto浅析
- 腾讯2017暑期实习生编程题
- CI框架---分页
- 浙江大学PAT 编程初级
- 15. Yii 2.0 页面缓存
- Java——Collection接口
- Spring框架IOC容器和AOP解析
- java线程
- Spark菜鸟学习营Day6 分布式代码运行调试
- Spring Boot系列(九) 使用Druid连接池
- java语言运算符
- 通过Springboot拆分服务构建微服务集
- 《C#高级编程》读书笔记(十六):文件和注册表操作
- (14)Struts2_值栈
- C#--反射
- YJQ集合