java泛型详解
来源:互联网 发布:高清网络监控 编辑:程序博客网 时间:2024/06/11 01:15
java泛型是java语言中的一颗语法糖,对java的功能没有什么影响,但是能够方便程序员的使用,减少出错的机会。比如hashMap的get()方法,获取的类型是一个Object,java中的所有类型都继承自java.lang.Object类,那么get()方法获取到的对象就存在向任何类型转换的可能,除了程序员自己和运行期的虚拟机,没人知道get到的这个对象到底是什么类型,也就容易出错。还是举一个例子吧:
package test;import java.util.ArrayList;import java.util.List;public class GenericityTest { public static void main(String[] args) { List list = new ArrayList(); list.add(1); list.add(new Dog()); for(Object m : list){ System.out.println((Dog)m); } }}class Dog{ @Override public String toString() { return String.valueOf(this.hashCode()); }}
这段代码在编译期间是没有问题的,因为迭代器返回的对象在编译期是不知道它到底是什么类型,我在list中放了一个int类型的1,又放了一只狗,结果会在运行期间报类型转换错误。假如写成List《Dog》。。。。,加上泛型就能够在编译期间发现这个错误,大家可以自己试一下。
java中的泛型所起的作用就是一个参数的作用,这个参数规定了在集合里能放什么类型,放了不符合参数规定的类型就会在编译期报错。
接下来稍微深入一下,泛型在运行期间到底起到作用了没,答案是否定的,java的泛型实现是用的类型擦除的技术,在编译成class之后,泛型也就消失了,
在java中List《String》和List《Int》类型是同一个类型,也就是说java是一个伪泛型,了解C#的可能知道在C#中List《String》和List《Int》是两个不同的类型。为了证明举了下面这个例子:
package test;import java.util.ArrayList;import java.util.List;public class GenericityTest { public static void say(List<String> list){//编译器报错 System.out.println("String"); } public static void say(List<Integer> list){//编译器报错 System.out.println("Integer"); } public static void main(String[] args) { }}
为什么会这样,因为java编译成class后会擦除掉泛型,所以两个say()方法在class中完全一样从而报错。但是加入非要通过泛型来重载的话,就必须采取一个并不好的方案,改变返回值。有人会说了,java语言中什么时候用返回值来重载了啊,你瞎说!表面上是这样,其实并不是根据返回值来重载,而是通过返回值的不同来防止编译期间的报错,虽然java语言的重载不包括返回值的不同来区分不同的方法,但是在class文件中方法的描述符除了方法名,参数个数类型外,还包括方法的返回值,只有返回值不同的两个方法在class中是可以区分和共存的。不明白的可以结合下面这个例子理解:
package test;import java.util.ArrayList;import java.util.List;//必须使用jdk 1.6的javac才能够编译成功,别的编译器或者jdk版本仍然拒绝编译public class GenericityTest { public static int say(List<String> list){//返回int System.out.println("String"); return 0; } public static String say(List<Integer> list){//返回String System.out.println("Integer"); return "ss"; } public static void main(String[] args) { say(new ArrayList<String>()); say(new ArrayList<Integer>()); }}
对于类型擦除,有兴趣的可以反编译试试,写一个List《String》……,反编译后发现泛型都不见了,变成了List……。
最后补充一点,类型擦除并不意味着完全没有泛型的信息,而是对方法区的字节码进行擦除,在想list中存对象的时候是当成Object存的, LocalVariableTypeTable中的signature中还保留这泛型的信息。
- Java泛型详解
- java泛型详解
- java泛型详解
- Java泛型详解
- Java泛型详解
- java泛型详解
- Java泛型详解
- java泛型详解
- java 泛型详解
- java 泛型详解
- Java 泛型详解
- java 泛型详解
- java 泛型详解
- java泛型详解
- java 泛型详解
- Java泛型详解
- java 泛型详解
- java 泛型详解
- 判断延迟搜索的程序,例如:给pc端的及时搜索用
- 来自一个小人物的唠叨
- JS或PHP判断是否来自微信浏览器访问
- Excel键盘快捷键大全(九)
- Recyclerview Item中图片动画错乱问题解决方案
- java泛型详解
- C#中的CLR
- 开源软件库TensorFlow最全教程和项目列表
- Ubuntu16.0.4LTS 64位上运行32位程序,提示No such file or directory?错误的解决办法
- Excel键盘快捷键大全(十)
- 折腾二维数组
- 德飞莱串口调试软件 ---部件'COMCTL32.OCX'或其附件之一不能正确注册
- RxJava+Retrofit实现全局过期token自动刷新的实践
- MapReduce:详解Shuffle过程