您的位置 首页 java

Java泛型 – 搞懂泛型这一片文章就够用了“绝对”

关键词

  • 伪泛型
  • 针对引用的检查
  • 类型擦除
  • 协变
  • 多态的冲突

一、介绍

java泛型是伪泛型,java文件编译时会进行类型擦除这样生成的class文件不再包含任何泛型信息。
泛型价值:增加约束,让代码优雅(无需显式的类型转化)。

二、原始类型

 abstract class Math<T> {
    abstract T max(T t1, T t2);
}
-----字节码------
abstract max(Ljava/ lang /Object;Ljava/lang/Object;)Ljava/lang/Object;

abstract class Math2<T extends  Number > {
    abstract T max(T t1, T t2);
}
------字节码-----
abstract max(Ljava/lang/Number;Ljava/lang/Number;)Ljava/lang/Number;
  

Object 或者 Number 就是T 的原始类型。这是类型擦除的基础思路,也由此产生了多态冲突问题。

三、类型擦除

文字描述比较枯燥难懂,以下通过3个示例来介绍,类型擦除、针对引用有效、为什么叫做 伪泛型。

示例1

 // 携带泛型的对象对应字节码完全一致。
   List<String> strList = new ArrayList<String>();
   List intList = new ArrayList();
---------字节码------------
   NEW java/util/ArrayList
   DUP
   INVOKESPECIAL java/util/ArrayList.<init> ()V
   ASTORE 1
   NEW java/util/ArrayList
   DUP
   INVOKESPECIAL java/util/ArrayList.<init> ()V
   ASTORE 2  

示例2

  /**
 * 约定泛型的list,可以通过反射成功添加 int类型数据进去,通过反射可以正常读取,直接读取时会提示类型转化异常。
 */@Test
public void typeErasure() {
    try {
        List<String> strList = new ArrayList();
        strList.getClass().getMethod("add", Object.class).invoke(strList, 123);
        System.out.println("strList'size :" + strList.size());
        System.out.println(strList.getClass().getMethod("get", int.class).invoke(strList, 0));
        System.out.println(strList.get( Integer .valueOf(0)));
    } catch (Exception e) {
        e.printStackTrace();
    }
}  

示例3

 泛型针对引用有效。
List<String> strList1 = new ArrayList();//有效果(阿里巴巴规范也提倡这么写)
List<String> strList2 = new ArrayList<String>();//效果同上面
List strList3 = new ArrayList<String>();//无效果  

由于 泛型仅仅生存到编译时期,所以称之为 伪泛型。

四、多态的冲突

 abstract class Math<T> {
    abstract T max(T t1, T t2);
}
-------二进制码---------
abstract max(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;

class IntMath extends Math<Integer> {

    @Override
    Integer max(Integer t1, Integer t2) {
        return java.lang.Math.max(t1, t2);
    }
}
--------二进制码--------
max(Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer;
synthetic bridge max(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
   L0
    LINENUMBER 28 L0
    ALOAD 0
    ALOAD 1
    CHECKCAST java/lang/Integer
    ALOAD 2
    CHECKCAST java/lang/Integer
    INVOKEVIRTUAL com/hardydou/jmm/IntMath.max (Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer;
    ARETURN  

泛型子类重写不是简单的重写,而是重载+重写

五、实战

5.1、基本类型不可以作为泛型

 List<int> list;//编译不通过  

5.2、泛型不可以被实例化

 class A<T> {
    T t=new T();//不可以被直接实例化
    .......
 }  

5.2、泛型使用instanceOf

 List<String> list1 = new ArrayList<>();
//可以
boolean s1 = (list1 instanceof ArrayList<?>);
boolean s3 = (list1 instanceof ArrayList);
//编译报错
boolean s2 = (list1 instanceof ArrayList<String>);  

文章来源:智云一二三科技

文章标题:Java泛型 – 搞懂泛型这一片文章就够用了“绝对”

文章地址:https://www.zhihuclub.com/182165.shtml

关于作者: 智云科技

热门文章

网站地图