Java语言高级
1. 使用泛型的意义
为什么我们需要泛型?
所以泛型的好处就是:
l 适用于多种数据类型执行相同的代码
例如实现int类型的加法, 有时候还需要实现long类型的求和, 如果还需要double类型的求和,需要重新在重载一个输入是double类型的add方法。
如果没有泛型每种类型数字都要重载一个add方法,代码量多而且没有必要,后续维护也麻烦,如果add方法里面增加一行代码?那就需要修改10个方法。
l 泛型中的类型在使用时指定,不需要强制类型转换
例如集合中不用泛型那么默认类型Object,可以存入String,int,double,保存数据很开心,但是用的时候就是灾难了。你必须强制类型转换到具体的目标类型,且很容易出现“java.lang.ClassCastException”异常。
泛型类和泛型接口
泛型,即“参数化类型”。
![](/qrcode.jpg)
参数很熟悉,自定义方法有形参,调用方法时候要传递实参。
顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
泛型的本质是为了参数化类型,过去参数不同输出不同结果,类型也可以参数化,那就是不同参数类型输出不同的结果。
也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
、
限定类型变量
extends 上限通配符 可以接收extend后的类型及子类
super 下限通配符 可以接收super后的类型及父类
T extends Comparable中
T表示应该绑定类型的子类型,Comparable表示绑定类型,子类型和绑定类型可以是类也可以是接口。
如果这个时候,我们试图传入一个没有实现接口Comparable的类的实例,将会发生编译错误。
泛型类的静态上下文中类型变量失效
泛型和static是不兼容的,
不能在静态域或方法中引用类型变量。因**为泛型是要在对象创建的时候才知道是什么类型的,而对象创建的代码执行先后顺序是static的部分,然后才是构造函数等等。所以在对象初始化之前static的部分已经执行了,如果你在静态部分引用的泛型,那么毫无疑问虚拟机根本不知道是什么东西,**因为这个时候类还没有初始化。
类型擦除
泛型是 Java 1.5 版本才引进的概念,在这之前是没有泛型的概念的,但显然,泛型代码能够很好地和之前版本的代码很好地兼容。
这是因为,泛型信息只存在于代码编译阶段,在进入 JVM 之前,与泛型相关的信息会被擦除掉,专业术语叫做类型擦除。
通俗地讲,泛型类和普通类在 java 虚拟机内是没有什么特别的地方。
Java 泛型擦除是 Java 泛型中的一个重要特性,其目的是避免过多的创建类而造成的运行时的过度消耗。所以,想 ArrayList 和 ArrayList 这两个实例,其类实例是同一个。
但很多情况下我们又需要在运行时获得泛型信息,那我们可以通过定义类的方式(通常为匿名内部类,因为我们创建这个类只是为了获得泛型信息)在运行时获得泛型参数,从而满足例如序列化、反序列化等工作的需要。