面试时问到关于Java泛型的问题,之前只是大概的了解,现在做一个总结
1、何为泛型,为什么要使用泛型?
泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。 泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
2、泛型可以使我们在编译时就检查出程序的错误,可以看以下例子:
stringList集合定义的泛型为String类型,但是当stringList.add(1)即为Integer类型时,便会在编译时就会提示错误,编译通不过。
3、泛型只在编译时有效,在运行时便会进行泛型的擦除,在jvm中并不存在泛型,可以看下面的例子:
1 List<String> stringList = new ArrayList<>(); 2 List<Integer> integerList = new ArrayList<>(); 3 4 System.out.println(stringList.getClass() == integerList.getClass()); //输出true
4、泛型有三种使用方式,分别为:泛型类、泛型接口、泛型方法
5、如何获取泛型的真实类型
如果在父类中想要获取泛型T的类型 ,T.class; T.getClass(); 这两种方法都是无法实现的,因为泛型T不是一个真正的类或者实例,
下面通过反射获得泛型T的真实的类的类型:
package Thread.type_demo; import java.lang.reflect.ParameterizedType; @SuppressWarnings("uncheck") public class Base<T> { private Class<T> clazz; //通过反射技术获取泛型类的真实类型 public Base(){ // 获取当前new的对象的泛型的父类类型 ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();// 这里的this代表子类的实例 // 获取第一个类型参数的真实类型 this.clazz = (Class<T>) pt.getActualTypeArguments()[0]; System.out.println("---> clazz : " + this.clazz); } public static void main(String[] args) { User user = new User(); Role role = new Role(); } }
public class User extends Base<User> { }
public class Role extends Base<Role> { }
运行结果: