在克隆中使用协变返回类型真的会破坏兼容性吗?

时间:2012-12-24 12:44:18

标签: java

我最近遇到了Why doesn't Java 5+ API take advantage of covariant return types?

我同意问题,在Java 5中,JDK开发人员可以使用协变返回类型进行克隆并更改现有类,以便我们可以编写

ArrayList<String> list = new ArrayList<String>();
ArrayList<String> clone = list.clone();

而不是

ArrayList<String> clone = (ArrayList<String>)list.clone();

但由于某些原因,没有那样做。

我做了一些实验,将我的test.ArrayList.clone返回类型从Object更改为ArrayList,看看“以前编译的类无法找到具有新返回类型的方法”,但无法重现该问题。在字节码中,对旧test.ArrayList.clone的调用类似于

 INVOKEVIRTUAL test.ArrayList.clone()Ljava/lang/Object;

也就是说,方法签名包含返回类型,因此在我将其签名更改为test.ArrayList.clone()Ltest.ArrayList之后。所以似乎旧的类会破坏,但实际上并不是因为test.ArrayList.class中有2个克隆方法

  public clone()Ltest.ArrayList;
  public bridge clone()Ljava/lang/Object; 

第二个是桥梁,它只是调用协变版本

 ...
 INVOKEVIRTUAL ArrayList.clone()Ltest.ArrayList;
 ...

所以旧班继续工作没有问题。

任何人都可以解释更改克隆的返回类型如何破坏字节码?

1 个答案:

答案 0 :(得分:2)

链接问题的

This answer确实包含原因:它会破坏覆盖ArrayList方法的clone的所有子类,并将Object指定为返回类型。