我不确定我是否了解clone()
中ArrayList
的用途。
有很多方法可以制作ArrayList
的浅表副本,我至少知道两种:
List<Integer> L1 = new ArrayList<>(Arrays.asList(1, 2, 3, 4));
List<Integer> L1_copy = new ArrayList<>(L1);
List<Integer> L1_copy2 = List.copyOf(L1); // inmutable but solve by below:
List<Integer> L1_copy3 = new ArrayList<>(List.copyOf(L1));
令人惊讶的是,它返回一个Object
,而不是ArrayList
,而且我不得不垂头丧气:
ArrayList<Integer> AL1 = new ArrayList<>(Arrays.asList(1, 2, 3, 4));
ArrayList<Integer> AL1_copy = (ArrayList<Integer>) AL1.clone();
为什么设计为以Object
的形式返回?
与其他浅拷贝方法相比,使用克隆有什么优势?
答案 0 :(得分:2)
由于clone()
方法的存在,我认为没有额外的优势。在基元的情况下,它相当于深层副本。
另外,除了构造函数之一外,我不知道Java中的许多方法,在该方法中,您将Collection
作为构造函数的参数进行传递。
它还实现了Cloneable
接口,我认为它类似于标记接口。
它返回Object
,因为它是所有类的超类,返回它不会破坏代码。
答案 1 :(得分:2)
键入是ArrayList在Java 5之前编写的结果。在Java 5之前,重写方法的返回类型必须与被重写的方法相同(是 invariant ) 。如今,由于方法返回类型可以是专门的(协变),因此,如果要重写ArrayList,则应使用ArrayList作为返回类型来编写。
但是,这里存在一个深层的问题,即虽然实现可以专门化clone()的返回类型,但类型系统并未完全表达类型关系。最好是Java只能少量支持的“自我”类型。这使您深入了解打字理论。例如,请参见:Java self-typed methods: cannot safely cast to actual type。
从实用程序的角度来看,正如其他人所说,Cloneable并不是一个非常有用的API。在实践中,关于一个人希望如何复制单个API以使其适合所有这些细节的方式,往往会有太多细节。
答案 2 :(得分:0)
通常,公共clone()方法支持多态。您可以在超类类型的引用上调用它,以克隆任何子类类型的对象。
为什么设计它作为对象返回?
协变返回类型是在Java 5中引入的。ArrayList
是在Java 2中引入的。
ArrayList
不是最终课程。修改其返回类型以返回ArrayList可能会破坏第三方子类。
与其他浅拷贝方法相比,使用克隆有何优势?
多态性。