深入Java泛型与类型擦除:一篇文章讲透本质!非人哉:哮天旅行团第二站,九月、敖烈都变绿,垃圾分类成问题

10次阅读

深入Java泛型与类型擦除:一篇文章讲透本质!非人哉:哮天旅行团第二站,九月、敖烈都变绿,垃圾分类成问题

什么是泛型?

泛型(Generics)的本质是参数化类型。简单来说,泛型就是允许在定义类、接口或方法时使用类型参数,这个类型参数可以在使用的时候指定具体类型。泛型的出现,使得我们不必为每一种类型去写一个独立的类或方法,而是通过一个通用的代码结构来处理不同类型的数据。

1. 泛型类

泛型类是一种具有类型参数的类,这个类型参数可以由用户在实例化时指定。

深入Java泛型与类型擦除:一篇文章讲透本质!非人哉:哮天旅行团第二站,九月、敖烈都变绿,垃圾分类成问题

在这个例子中,Box类使用了泛型T,这意味着你可以在实例化Box时指定不同的类型,如Box 、Box 等。

深入Java泛型与类型擦除:一篇文章讲透本质!非人哉:哮天旅行团第二站,九月、敖烈都变绿,垃圾分类成问题

2. 泛型方法

泛型不仅可以用在类中,还可以用在方法中。如果你不想整个类都使用泛型,但某个方法需要,你就可以定义一个泛型方法。

深入Java泛型与类型擦除:一篇文章讲透本质!非人哉:哮天旅行团第二站,九月、敖烈都变绿,垃圾分类成问题

在这个例子中,printArray方法是一个泛型方法,它可以接受任何类型的数组并打印出其中的元素。

深入Java泛型与类型擦除:一篇文章讲透本质!非人哉:哮天旅行团第二站,九月、敖烈都变绿,垃圾分类成问题

3. 泛型接口

和泛型类一样,接口也可以使用泛型。假如我们有一个定义了泛型的接口,其他类可以通过实现这个接口,并根据需要指定具体的类型。

深入Java泛型与类型擦除:一篇文章讲透本质!非人哉:哮天旅行团第二站,九月、敖烈都变绿,垃圾分类成问题

通过泛型接口,你可以使接口更加通用化,适应更多不同类型的实现需求。

泛型的好处

泛型给我们的代码带来了许多好处:

类型安全:在编译阶段检查类型的合法性,避免运行时出现ClassCastException。

提高代码复用性:通过泛型,我们可以编写更具通用性的代码,适应不同类型的需求。

提高可读性:泛型让代码更加清晰,明确传递和返回的类型。

类型安全的例子

在没有泛型之前,我们常用的是Object类型来处理不同类型的数据:

深入Java泛型与类型擦除:一篇文章讲透本质!非人哉:哮天旅行团第二站,九月、敖烈都变绿,垃圾分类成问题

如果你不小心把错误的类型从集合中取出来,就可能导致ClassCastException,泛型则有效避免了这种问题。

深入Java泛型与类型擦除:一篇文章讲透本质!非人哉:哮天旅行团第二站,九月、敖烈都变绿,垃圾分类成问题

通过泛型,编译器可以帮你检查类型错误,让代码更加健壮。

泛型擦除

Java的泛型其实是一种“伪泛型”。你在写代码的时候可能觉得泛型是很强大和灵活的,但实际上,Java在编译时并不会真正保留这些泛型信息,而是通过一种机制来将泛型信息擦除,这个过程叫做类型擦除(Type Erasure)

1. 泛型擦除的概念

泛型擦除是指Java编译器在编译代码的时候,会将所有泛型信息擦除,并用它们的原始类型(通常是Object)代替。这意味着在运行时,JVM是看不到任何泛型信息的,所有的泛型类型参数在编译后都消失了。

举个简单的例子:

深入Java泛型与类型擦除:一篇文章讲透本质!非人哉:哮天旅行团第二站,九月、敖烈都变绿,垃圾分类成问题

在编译之后,这两个List类型都会被擦除为原始类型List,在运行时,JVM并不知道这两个List的元素类型是String还是Integer。

2. 泛型擦除的影响

由于泛型擦除,Java的泛型在运行时并不会保存类型信息,所以我们不能像这样编写代码:

深入Java泛型与类型擦除:一篇文章讲透本质!非人哉:哮天旅行团第二站,九月、敖烈都变绿,垃圾分类成问题

因为在运行时,List 和List 已经变成了一样的List,类型信息被擦除了。

3. 泛型擦除与反射

虽然泛型在运行时被擦除,但通过反射我们仍然可以插入其他类型的元素到泛型集合中。这显然破坏了泛型的类型安全性,这也是为什么反射需要特别小心使用的原因。

深入Java泛型与类型擦除:一篇文章讲透本质!非人哉:哮天旅行团第二站,九月、敖烈都变绿,垃圾分类成问题

在这个例子中,虽然stringList的类型是List ,但通过反射,我们依然可以插入一个Integer类型的元素。这证明了在运行时,泛型类型实际上已经被擦除了,List 和List 对JVM来说是没有区别的。

泛型的局限性

泛型虽然强大,但由于泛型擦除的存在,也带来了一些局限性:

不能使用基本类型:Java泛型不支持基本类型,如int、char,只能使用包装类型Integer、Character等。

深入Java泛型与类型擦除:一篇文章讲透本质!非人哉:哮天旅行团第二站,九月、敖烈都变绿,垃圾分类成问题

不能创建泛型数组:泛型数组在Java中是非法的。

深入Java泛型与类型擦除:一篇文章讲透本质!非人哉:哮天旅行团第二站,九月、敖烈都变绿,垃圾分类成问题

不能在运行时检查泛型类型:由于类型擦除的存在,无法在运行时判断一个对象是否为某个具体的泛型类型。

深入Java泛型与类型擦除:一篇文章讲透本质!非人哉:哮天旅行团第二站,九月、敖烈都变绿,垃圾分类成问题

正文完
 0
网站地图