1

我最近遇到了为什么 Java 5+ API 不利用协变返回类型?.

我同意这个问题,在 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 以查看“以前编译的类无法找到具有新返回类型的方法”但无法重现该问题。在字节码中,对 old 的调用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;
 ...

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

谁能解释更改克隆的返回类型如何破坏字节码?

4

1 回答 1

2

这个对链接问题的答案确实包含原因:它会破坏ArrayList覆盖该clone方法并指定Object为返回类型的所有子类。

于 2012-12-24T13:35:43.470 回答