【Java核心知识】泛型和类型擦除

心已赠人 2024-03-09 00:43 141阅读 0赞

文章目录

  • 泛型
    • 什么是泛型
    • 类型限定
    • 类型擦除
    • 如何在运行时判断泛型具体类型
    • 参考链接

泛型

什么是泛型

Java中的泛型是通过定义模板参数来处理一类操作,这类操作并不关心具体传入的参数类型。比如对于add()方法来说,我们可以使两个int相加,也可以使两个long相加,如果不使用泛型,因为函数签名是通过参数类型区分的,那么就会造成需要写两个方法的问题.

但这两个方法内部的逻辑是一致的,只是传入参数不相同,况且方法内部也并不关心你传入的参数类型。

针对这种情况,我们可以使用泛型解决,泛型并不会限定你传入的参数类型,它只关心方法内部的逻辑操作

常见的集合类都使用了泛型

类型限定

既然泛型类可以传入各种各样的类型,那么使用上会不会出问题呢?比如一个集合既放入了Integer,又放入了String

答案是不会的,我们在创建泛型类时,一般都会提前传入泛型的类型进行类型限定,比如 Array<Integer> list = new ArrayList<>();,表明list只能存放Integer类型的对象,而不能存放String类型的变量,这是由于编译器在编译代码时通过类型限定对代码进行了检查,从而避免传入不一致的类型;

类型擦除

上面我们讲到是在编译时进行了类型检查,其实Java的泛型并不是真正的泛型,编译完成后会进行类型擦除,也就是说ArrayList这个类并不知道自己存放的类型是什么,内部统一用基类Object表示,这就是类型擦除

如果正常写代码,类型擦除对我们并没有什么影响,可如果想要通过反射获取泛型属性的具体类型是做不到的。因为反射时我们一般先拿到对应类的Class对象,然后利用反射获取Field,但由于类型擦除的存在,泛型属性在Class对象内部都是基类Object,并不是具体的类型。

下面是一个示例,count是一个泛型属性,如果想要通过反射获取count运行时真正的类型,是做不到的,type永远是一个java.lang.Object

  1. public class ValJson {
  2. static class Count<T> {
  3. public T count;
  4. public void setCount(T count) {
  5. this.count = count;
  6. }
  7. }
  8. public static void main(String[] args) throws NoSuchFieldException {
  9. Count<Integer> count = new Count<>();
  10. count.setCount(2);
  11. // 由于类型擦除,type 的类型为 java.lang.Object
  12. Type type = count.getClass().getField("count").getType();
  13. System.out.println(count);
  14. }
  15. }

如何在运行时判断泛型具体类型

只能在方法内部通过isinstance(a, String.class)逐一判断类型实现,这样会有很多种if语句

参考链接

Java泛型类型擦除以及类型擦除带来的问题

发表评论

表情:
评论列表 (有 0 条评论,141人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Java-类型

    Java泛型-类型擦除 一、概述 Java泛型在使用过程有诸多的问题,如不存在List.class, List不能赋值给List(不可协变),奇怪的ClassCastE

    相关 Java类型

    类型擦除详解: [来自CSDN的一篇我认为最好的讲解类型擦除的文章][CSDN]. 个人补充: 泛型擦除是指Java 编译后的字节码中已经没有泛型的任何信