美文网首页程序员
Android 开发也要掌握的Java知识 - Java 泛型擦

Android 开发也要掌握的Java知识 - Java 泛型擦

作者: 进击的包籽 | 来源:发表于2020-07-28 11:51 被阅读0次

如果需要看泛型使用Java泛型

1.什么是泛型擦除

  • 因为Java 泛型是1.5版本才引入的,为了向下兼容,其实虚拟机是不支持泛型的,Java里面是伪泛型机制
  • Java在编译期就擦除了所有泛型信息,这样Java就不需要产生新的类型到字节码,所有泛型类型最终都是一种类型

2.编译期如何擦除泛型:

1.检查泛型类型,获取目标类型
2.擦除类型变量,替换为限定类型
2.1如果泛型类型的类型变量没有限定,比如<T>,就替换为Object类型为原始类型
2.2如果类型变量是<T extends xxxCalss>,就替换为xxxClass类型为原始类型
2.3如果多个限定<T extends xClass1 & XClass2>,就用第一个xClass1类型为原始类型
3.必要的时候插入类型转换来保存类型安全
4.生成桥接方法,在扩展时保持多态性

3.泛型擦除也会有副作用

1.泛型擦除后替换为Object类型,所以不能传基本数据类型,比如List不能写int类型(List<int>)
2.不能使用instanceof来判断类型,因为是Object嘛
3.类不能声明静态的成员变量,因为泛型参数要创建对象时就确定
等等其他

4.这里放黑马教程的截图,可以在哔哩哔哩上免费观看

无限制类型擦除.png 有限制类型擦除.png 擦除方法中类型定义的参数.png 桥接方法.png

5.验证泛型擦除

5.1用反射查看
public class Test<T extends Number> {
    T t;
 
    public T getT() {
        return t;
    }
 
    public void setT(T t) {
        this.t = t;
    }
 
    public <T extends Number> T show(T t) {
        return t;
    }
}
 
 
/*----------------------------------------------------------*/
 
public class TestObject<T> {
    T t;
 
    public T getT() {
        return t;
    }
 
    public void setT(T t) {
        this.t = t;
    }
 
    public <T> T show(T t){
        return t;
    }
}
 
 
/*----------------------------------------------------------*/

//利用反射,获取Test类的类对象
Test<Integer> test = new Test<>();
Class<? extends Test> clazz = test.getClass();
//获取成员变量
Field[] testField = clazz.getDeclaredFields();
for (Field field : testField) {
    Log.d(TAG, field.getName() + " : " + field.getType().getSimpleName());
}
Log.d(TAG, "-----------------------------------");
//成员方法
Method[] methods = clazz.getMethods();
for (Method method : methods) {
    Log.d(TAG, method.getName() + " : " + method.getReturnType().getSimpleName());
}


Log.d(TAG, "-----------------------------------");


TestObject<Integer> testObject = new TestObject<>();
Class<? extends TestObject> clz = testObject.getClass();
//获取成员变量
Field[] testObjectField = clz.getDeclaredFields();
for (Field field : testObjectField) {
    Log.d(TAG, field.getName() + " : " + field.getType().getSimpleName());
}
Log.d(TAG, "-----------------------------------");
//成员方法
Method[] objectMethods = clz.getMethods();
for (Method method : objectMethods) {
    Log.d(TAG, method.getName() + " : " + method.getReturnType().getSimpleName());
}
泛型有限制擦除.png 泛型无限制擦除.png
  • 我们可以看到 extends Number,反射拿到的类型就是Number,否则就是Object
5.2用字节码查看
  • Android studio 安装ASM Bytecode Viewer就能查看


    getT()返回的类型为Number
    show()方法类型为Number
    getT()返回类型为Object
    showT()方法类型为Object

6.验证泛型桥接

6.1用反射查看桥接方法
public interface Info<T> {
    T info(T t);
}
 
public class InfoImpl implements Info<Integer> {
    @Override
    public Integer info(Integer integer) {
        return integer;
    }
}
 
/*----------------------------------------------------------*/

InfoImpl info = new InfoImpl();
Class<InfoImpl> infoClazz = InfoImpl.class;
//获取成员变量
Field[] infoFields = infoClazz.getDeclaredFields();
for (Field field : infoFields) {
    Log.d(TAG, field.getName() + " : " + field.getType().getSimpleName());
}
Log.d(TAG, "-----------------------------------");
//成员方法
Method[] infoMethods = infoClazz.getMethods();
for (Method method : infoMethods) {
    Log.d(TAG, method.getName() + " : " + method.getReturnType().getSimpleName());
}
泛型桥接.png
  • 可以看到info方法有两个
6.2用字节码查看桥接方法
字节码查看桥接方法

7.参考文章

Java中的泛型擦除
哔哩哔哩视频

如果有写的不对,希望大家帮忙指出错误,谢谢!

相关文章

  • Android 开发也要掌握的Java知识 - Java 泛型擦

    如果需要看泛型使用Java泛型 1.什么是泛型擦除 因为Java 泛型是1.5版本才引入的,为了向下兼容,其实虚拟...

  • Android 开发也要掌握的Java知识 - Java泛型

    如果需要看泛型擦除Java泛型擦除 1.Java泛型有什么用?为啥要使用泛型? Java中数组的类型是定义的时候就...

  • Java 泛型

    导读 移动开发知识体系总章(Java基础、Android、Flutter) 为什么会有泛型? 泛型类 泛型方法 泛...

  • Android 知识体系整理

    基础的知识点全部略过,下面都为进阶知识点 Java 篇 1. 泛型 熟练掌握泛型语法是在java开发中涉及到的架构...

  • 深入浅出 Java 泛型之(一):前生今世

    本文出自伯特的《LoulanPlan》,转载务必注明作者及出处。 对于 Java 开发者而言,泛型是必须掌握的知识...

  • Android-基本的MVP结构的模板工程(泛型,Rx通用请求,

    关键实践链接: Android-Java-泛型-总得有个开始的篇 Android-Java-泛型-官方文档走一走 ...

  • Java 反射机制

    不论是 Java 开发 还是 Android 开发,反射、泛型、注解 都是架构设计中很重要的一个知识点。 为了更好...

  • Java泛型教程

    Java泛型教程导航 Java 泛型概述 Java泛型环境设置 Java泛型通用类 Java泛型类型参数命名约定 ...

  • Java泛型

    参考:Java知识点总结(Java泛型) 自定义泛型类 自定义泛型接口 非泛型类中定义泛型方法 继承泛型类 通配符...

  • 死磕Java泛型(一篇就够)

    Java泛型,算是一个比较容易产生误解的知识点,因为Java的泛型基于擦除实现,在使用Java泛型时,往往会受到泛...

网友评论

    本文标题:Android 开发也要掌握的Java知识 - Java 泛型擦

    本文链接:https://www.haomeiwen.com/subject/jptfrktx.html