加入收藏 | 设为首页 | 会员中心 | 我要投稿 拼字网 - 核心网 (https://www.hexinwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 编程要点 > 语言 > 正文

让你滔滔不绝的Java的泛型知识点梳理

发布时间:2021-05-23 18:21:46 所属栏目:语言 来源:互联网
导读:最近技术交流群里,有朋友问:Object和泛型T有啥区别。回答完问题,不禁在想,面试在即,还有那么多朋友不了泛型?是时候给大家整理一篇泛型相关的文章了,一篇文
副标题[/!--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: 

(编辑:拼字网 - 核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!