Java 中协变类型擦除与桥接方法

Posted Lemo_wd

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 中协变类型擦除与桥接方法相关的知识,希望对你有一定的参考价值。

协变

① 为什么数组是协变的?

jdk1.5 之前不支持泛型,,想要为每个数组类型添加通用的 equals方法,所以设计成是协变的。

② 为什么数组需要在运行时保留类型信息?

由于数组是协变的,利用其多态特性,即 Integer[]的实例对象可以赋给 Number[]类型的变量。则可以向该 Integer[ ] 实例放入Double类型的元素。因此保留类型信息则可在运行时检查出类型错误,从而阻止此类问题。

 

类型擦除

问题

class Node<T> {

    public T data;

    public Node(T data) {
        this.data = data;
    }

    public void setData(T data) {
        System.out.println("Node.setData");
        this.data = data;
    }
}

class MyNode extends Node<Integer> {
    public MyNode(Integer data) {
        super(data);
    }

    public void setData(Integer data) {
        System.out.println("MyNode.setData");
        super.setData(data);
    }
}

class Main {
    public static void main(String[] args) {
        MyNode mn = new MyNode(5);
        Node n = mn;            // A raw type - compiler throws an unchecked warning
        n.setData("Hello");
        Integer x=mn.data;
    }
}

 

桥接方法

编译后,由于类型擦除生成的一个辅助方法。

public class Node<T> {

    public T data;

    public Node(T data) { this.data = data; }

    public void setData(T data) {
        System.out.println("Node.setData");
        this.data = data;
    }
}

public class MyNode extends Node<Integer> {
    public MyNode(Integer data) { super(data); }

    public void setData(Integer data) {
        System.out.println("MyNode.setData");
        super.setData(data);
    }
}

编译后

public class Node {

    public Object data;

    public Node(Object data) { this.data = data; }

    public void setData(Object data) {
        System.out.println("Node.setData");
        this.data = data;
    }
}

class MyNode extends Node {

    // Bridge method generated by the compiler
    //
    public void setData(Object data) {
        setData((Integer) data);
    }

    public void setData(Integer data) {
        System.out.println("MyNode.setData");
        super.setData(data);
    }

    // ...
}

为了满足对象继承关系,生成立一个桥接方法。该桥接方法具有和 Node 类方法签名一致的方法,然后委托具体的类型方法。

 

233

参考资料


https://hongjiang.info/scala-type-system-array-type/#:~:text=scala%E9%87%8C%E4%B8%8D%E6%94%AF%E6%8C%81%E6%95%B0%E7%BB%84,%5BAny%5D%20%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%8F%98%E9%87%8F%E3%80%82

https://zq99299.github.io/java-tutorial/java/generics/bridgeMethods.html#%E6%A1%A5%E6%8E%A5%E6%96%B9%E6%B3%95

以上是关于Java 中协变类型擦除与桥接方法的主要内容,如果未能解决你的问题,请参考以下文章

Java中的类型擦除与桥方法

泛型(10)-泛型擦除与转换

C++ 克隆习语中协变返回类型的用处?

JAVA中的协变与逆变

java 泛型擦除 通配符? 的思考 T与?擦除,协变

Java编程:浅析泛型类型中的桥接方法