关于泛型基础

协变

① 为什么数组是协变的?

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

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

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

③ java 中泛型不支持协变 

由于类型擦除的关系(下例),泛型不支持协变。

④ 无法创建泛型数组

List[] li1 = new ArrayList[2]; // 可以
List<?>[] li2 = new ArrayList<?>[2]; // 可以
List<Integer>[] li3 = new ArrayList<Integer>[2]; // 编译报错

④ scala 中泛型支持协变

scala 中的协变仅用于不可变对象,比如 List 是支持协变的,而 ListBuffer 不支持协变。

 

类型擦除

问题

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

相关文章:

  • 2022-12-23
  • 2021-05-09
  • 2021-07-07
  • 2021-08-31
  • 2022-02-06
  • 2021-04-02
  • 2022-12-23
猜你喜欢
  • 2021-06-13
  • 2022-01-05
  • 2022-02-28
  • 2021-07-30
  • 2021-07-30
  • 2021-09-11
相关资源
相似解决方案