让你滔滔不绝的Java的泛型知识点梳理
副标题[/!--empirenews.page--]
最近技术交流群里,有朋友问:Object和泛型T有啥区别。回答完问题,不禁在想,面试在即,还有那么多朋友不了泛型?是时候给大家整理一篇泛型相关的文章了,一篇文章全面搞定泛型,让大家再也不愁面试或实践中泛型相关的问题了。 什么是泛型 泛型是在JDK 5时就引入的新特性,也就是“参数化类型”,通俗来讲就是将原来的具体类型通过参数化来定义,使用或调用时再传入具体的类型(类型实参)。 泛型的本质是为了参数化类型(在不创建新类型的前提下,通过泛型指定的不同类型来控制形参具体的类型)。在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。 为什么使用泛型 未使用泛型时,可以通过Object来实现参数的“任意化”,但这样做的缺点就是需要显式的强制类型转换,这就需要开发者知道实际的类型。 而强制类型转换是会出现错误的,比如Object将实际类型为String,强转成Integer。编译期是不会提示错误的,而在运行时就会抛出异常,很明显的安全隐患。 Java通过引入泛型机制,将上述的隐患提前到编译期进行检查,开发人员既可明确的知道实际类型,又可以通过编译期的检查提示错误,从而提升代码的安全性和健壮性。 使用泛型前后的对比 拿一个经典的例子来演示一下未使用泛型会出现的问题。 List list = new ArrayList(); list.add(1); list.add("zhuan2quan"); list.add("程序新视界");
for (int i = 0; i < list.size(); i++) { String value = (String) list.get(i); System.out.println("value=" + value); } 上述代码在编译器并不会报任何错误,但当执行时会抛出如下异常: java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String 那么,是否可以在编译器就解决这个问题,而不是在运行期抛出异常呢?泛型应运而生。上述代码通过泛型来写之后,变成如下形式: List<String> list = new ArrayList<>(); list.add(1); list.add("zhuan2quan"); list.add("程序新视界");
for (String value : list) { System.out.println("value=" + value); } 可以看出,代码变得更加清爽简单,而且list.add(1)这行代码在IDE中直接会提示错误信息: Required type: String Provided: int 提示错误信息便是泛型对向List中添加的数据产生了约束,只能是String类型。 泛型中通配符 在使用泛型时经常会看到T、E、K、V这些通配符,它们代表着什么含义呢? 本质上它们都是通配符,并没有什么区别,换成A-Z之间的任何字母都可以。不过在开发者之间倒是有些不成文的约定: T (type) 表示具体的一个java类型; K V (key value) 分别代表java键值中的Key Value; E (element) 代表Element; 为什么Java的泛型是假泛型 为了做到向下兼容,Java中的泛型仅仅是一个语法糖,并不是C++那样的真泛型。 还是上面的例子,在直接向泛型为String的List中添加int类型会提示错误: List<String> list = new ArrayList<>(); list.add(1); 针对上述代码,我们采用反射间接地调用add方法: @Test public void test3() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { List<Integer> list = new ArrayList<>(); list.add(1); Method add = list.getClass().getMethod("add", Object.class); add.invoke(list,"程序新视界"); System.out.println(list); System.out.println(list.get(1)); } 执行上述代码,我们发现程序并没有抛出异常,正常打印出入: [1, 程序新视界] 程序新视界 原本只能装入Integer的List,成功装入了一个String类型的值。由此可见,所谓的泛型确实是假泛型。 同时,我们还可以通过字节码来证明。拿上面使用了泛型的实例代码,通过javap -c命令来看看字节码: Code: (编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |