清除类型和桥接方法说明

时间:2019-04-21 13:16:06

标签: java generics erasure java-bridge-method

以下代码摘自Oracle泛型文档-

 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);
    }

     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;  // Causes a ClassCastException to be thrown.
     }
}

我对这段代码的理解-

问-方法setData被覆盖还是重载?

我的立场-由于MyNode正在扩展Node<Integer>,因此类型参数T的值设置为Integer

因此类Node的方法setData(Integer data)为T = Integer 类MyNode具有方法setData(Integer data)

覆盖,因为签名相同。

Q-即使擦除后,setData方法仍被覆盖吗? 我的理解-

在我们擦除<T>之后,set方法变成Node,变成setData(Object data)

Mynode的设置方法将为-setData(Integer data),因为没有类型参数,也没有要删除的内容。

但这是超载

问-我们要重载还是覆盖?

我的理解-通过擦除前定义的方法的外观,我们要覆盖

问-那么如何在擦除后实现覆盖?

我的理解-通过桥接方法。例如:

setData(Object data){
    setData((Integer) Data);
}

我的理解正确吗?

此外,class MyNode extends Node<Integer>何时传递给Integer?什么时候叫super?

1 个答案:

答案 0 :(得分:1)

  1. 是的,方法// declare variable outside document.ready var plot1; var storedData; var drawWithNoDataIndicator = true; var updateId = 0; var updates = [ [ ['Take home pay', 44228.33], ['Tax', 8771.67], ['Super', 4162.5 ], ['Regular expenses', 0 ], ['Unallocated', 44228.33], ['Testing', 8000] ], [ ['Take home pay', 14228.33], ['Tax', 18771.67], ['Super', 14162.5 ], ['Regular expenses', 0 ], ['Unallocated', 44228.33], ['Testing', 8000] ], [], ]; function getNextUpdate() { var data = updates[updateId]; updateId++; if(updateId >= updates.length) updateId = 0; return data; } $(document).ready(function () { //jQuery.jqplot.config.enablePlugins = false; plot1 = $.jqplot('myChart', [''], { seriesDefaults: { renderer: $.jqplot.PieRenderer, rendererOptions: { showDataLabels: true, } }, noDataIndicator: { show: drawWithNoDataIndicator, indicator: 'Loading Data...', }, legend: { show: true, location: 'e' } }); $('#updateGraph').click(function(){updateGraph();}); $('#redrawGraph').click(function(){redrawGraph();}); }); function updateGraph() { plot1.destroy(); plot1.series[0].data = getNextUpdate(); if(plot1.series[0].data.length === 0) { plot1.noDataIndicator = { show: true, indicator: 'No data in the selected set.' }; } else { plot1.noDataIndicator = { show: false }; } plot1.replot(true); } function redrawGraph() { plot1.destroy(); $('#myChart').empty(); plot1 = $.jqplot('myChart', drawWithNoDataIndicator ? [''] : updates[updateId], { seriesDefaults: { renderer: $.jqplot.PieRenderer, rendererOptions: { showDataLabels: true, } }, noDataIndicator: { show: drawWithNoDataIndicator, indicator: 'Loading Data...', }, legend: { show: true, location: 'e' } }); drawWithNoDataIndicator = !drawWithNoDataIndicator; } 被覆盖。
  2. 从用户的角度来看,好像setDatasetData(T data)覆盖,即,当您调用setData(Integer i)时,它将打印带有< em>“ MyNode” ,而不是“ Node”

    在类型擦除方法签名的级别上,这将通过添加到setData(42)的合成桥接方法setData(Object)来实现,即,如果用MyNode反编译MyNode.class,您将看到两个方法:

    javap
  3. 语言规范说“ override” ,我不知道为什么有人会想要其他东西。

  4. “ <擦除后实现覆盖” 的含义不明确。类型擦除是在类型检查并确定哪些优先于什么之后进行的。没有什么可以“实现”的,而仅仅是工作的顺序(另请参见this comment)。覆盖原始 public void setData(java.lang.Integer); public void setData(java.lang.Object); 的综合桥接方法看起来像您所写的内容(最多为小错别字):

    setData(Object)

    至少是the documentation says。但这是一个 synthetic 方法,它是由编译器自动生成的。如果它出现在源代码中,则会给您带来编译错误。