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