Java中 泛型 的本质是参数化类型,泛型提供了编译时类型的安全检测机制。泛型机制允许程序在编译的时候检测非法的类型,例如要实现一个对于字符串、整型、浮点型、对象类型等比较其大小的方法,就可以使用泛型,在使用的时候在明确所要比较的数据类型就可以了。

当然如果不想使用泛型对象来作为参数的话,也可以通过Object类型来实现参数任意处理,因为Object是所有对象类型的父类。在具体使用的时候可以根据强制类型转换的方式来对使用的对象进行处理操作。
使用强制类型转换的时候,必须要求开发人员明确地知道实际参数的引用类型,不然不能进行强制类型转换的操作。这种错误在程序编译的时候是不会出现的,只有在正式运行的时候才能检测到具体的参数类型是否安全。
使用泛型的好处是在编译的时候就能检测到所要转换的类型是否正确,保证编译的安全性,同时泛型到具体数据类型的所有的强制性的类型转换都是由 Java 自身来完成,这样的话本身也是提高了代码的安全性。
常用的泛型标记
首先需要知道的常用的泛型标识都有哪些?
- 1、E-Element 在集合中使用,表示在一个集合中存放的元素
- 2、T-Type 表示Java类,包括提供的基本的Java类以及自定义的Java类
- 3、K-Key 在Map中使用,表示KV键值对的K值
- 4、V-Value 表示Map中的V的值
- 5、N-Number 表示数值类型的数据,常用来表示Double、 integer 等类型。
- 6、?表示暂时不确定Java的类型有什么,类似于统配的操作。
类型 通配符 使用“?” 表示所有类型的数据参数,例如再List<?>的定义中,说明在List中课可以放入任何的参数类型。
在使用泛型的时候,如果是想要将类的继承关系中加入泛型中进行使用,这个时候就需要对泛型类型做一定的限制,具体的操作有如下的两种
对泛型的上限进行操作<? extends T>
Java中 使用通配符“?”和extends关键字来指定泛型的上限,具体的用法就是<? extends T>,它表示这个通配符代表的类型是T这个类型的子类或者是实现的子接口类型。
对泛型操作下限的限定<? super T>
使用通配符?和super关键字来指定泛型的下限,表示通配符代表的类型是T类型的父类或者是父类的借口类型。
泛型方法
泛型方法指的是参数的传入定义使用泛型类型,这样做的好处就是在使用方法的时候可以传入不同类型的参数对象,然后方法体内部根据不同的参数进行不同的类型操作
public static <T> void testMethod(T ... inputArray){
for(T element :inputArray){
if(element instanceof Integer){
}else if(element instanceof String){
}else if(element instanceof Double){
}else if(element instanceof Float){
}else if(element instanceof Long){
}else if(element instanceof Boolean ){
}else if(element instanceof Date){
}
}
}
在上面代码中就体现了通过testMethod定义了一个方法传入的参数是一个泛型的列表,在执行到不同的参数的时候可以进入到不同的逻辑判断中,根据不同的参数类型来进行不同的逻辑处理操作。执行不同的条件判断中。
泛型类
泛型类作为在Java中使用比较多的存在,具体是指在定义类型的时候在类上定义的泛型,这样方便在类使用的时候根据不同的参数传入实例化不同的对象。
泛型类的具体使用方式是在类的名称后面,添加一个或者多个类型参数的声明,如下,多个泛型参数可以通过逗号隔开。
public class GeneralClass<T>{
public static void mian(String[] args){
GeneralClass<Integer> integerTest = new GeneralClass<Ineteger>()
integerTest.add(1);
GeneralClass<String> stringTest = new GeneralClass<String>()
stringTest.add("test");
}
private T t ;
public void add(T t){
this.t = t;
}
public T get(){
return t;
}
}
泛型接口
泛型接口的声明与泛型接口的声明是类似的,通过在接口定义的后面添加类型参数的声明部分来实现泛型接口定义。泛型接口的具体的类型一般在实现类中进行声明,也就是说不同的类型实现类需要处理不同类型的业务逻辑。
public interface IGeneral<T>{
public T getId();
}
public class GeneralIntegerImpl implements IGeneral<Integer>{
}
public class GeneralStringImpl implements IGeneral<String>{
}
类型擦除
在编码的时候采用泛型的方式添加上的类型参数,在编译的时候就会被全部去掉,这个过程就被称为是类型擦除。那么为什么要进行类型擦除呢?这就要从泛型的存在的意义来说了,首先呢,泛型主要是用于编译阶段,来标识类型用的,在编译之后生成了 字节码 的问题件中,就不需要泛型类型中的信息了。也就是说需要对其进行使用初始化的时候,就需要明确地进行使用初始化操作了。

例如在编码的时候定义了一个List<String> 的操作,在编译之后,统一就只剩下一个List, JVM 所加载到的内容也是List,对于泛型附加的一些类型信息就没有了。对于JVM是不可见的。
因为种种原因,Java不能实现真正的泛型,只能使用类型擦除来实现伪泛型,这样虽然不会有类型膨胀问题,但是也引起来许多新问题,所以, SUN 对这些问题做出了种种限制,避免我们发生各种错误。