我最近遇到了为什么 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;
...
所以老班继续工作没有问题。
谁能解释更改克隆的返回类型如何破坏字节码?