我偶然发现了一个问题,我必须创建一个不接受任何输入并返回此购物篮MarketProduct的数组的浅表副本(而不是引用的副本)的方法。
我知道解决方法如下
public class Basket {
private MarketProduct[] marketproducts;
public Basket() {
this.marketproducts = new MarketProduct[0];
}
public MarketProduct[] getProducts() {
return this.marketproducts.clone();
我不明白的是 1.如果是浅表副本,那么它是引用权的副本? 2.我可以对Java中的任何对象使用克隆方法吗?它会复制参考对象或实际对象吗?如果是这样,那么可以简化以下内容(代替使用for循环,我可以使用clone?)?
public void add(MarketProduct input) {
MarketProduct[] list = new MarketProduct[marketproducts.length];
for(int i = 0; i < marketproducts.length; i++) {
list[i] = marketproducts[i];
}
list[list.length-1] = input;
this.marketproducts = list;
}
答案 0 :(得分:1)
- 如果是浅表副本,那么它是引用权的副本?
不。这是一个新数组,其中包含与原始数组相同的对象的引用
- 我可以对Java中的任何对象使用克隆方法吗?
不。阅读Object.clone()
和Cloneable
的Javadoc来了解规则。
如果是这样,那么可以简化以下内容(代替使用for循环,我可以使用克隆吗?)?
否,因为clone()
将为您提供相同长度的新数组,因此您将无法在该数组的末尾添加新元素。
答案 1 :(得分:1)
- 如果它是浅表副本,那么它是参考权的副本?
否,它是对具有该对象属性副本的新对象的新引用。详细信息取决于clone
的实现。
- 我可以对Java中的任何对象使用克隆方法吗?它会复制引用对象还是实际对象?
首先,clone
不是用于数组浅拷贝的正确工具。您可以改用System.arraycopy
。对于您的情况,您需要为新条目分配一个末尾有空间的数组,然后将arraycopy
原始数组放入其中,然后添加条目。
public void add(MarketProduct input) {
MarketProduct[] list = new MarketProduct[marketproducts.length + 1];
System.arraycopy(marketproducts, 0, list, 0, marketproducts.length);
list[list.length-1] = input;
this.marketproducts = list;
}
显然,这有点贵,您可以考虑使用List
类之一(也许是ArrayList
),这样就不必每次都增加数组。
关于clone
,请参见the JavaDoc:
创建并返回此对象的副本。确切含义 “副本”的类型可能取决于对象的类。一般 目的是,对于任何对象x
,表达式:将为真,并且该表达式:x.clone() != x将为x.clone().getClass() == x.getClass()true
,但这不是绝对要求。 通常情况是:将为x.clone().equals(x)true
,这不是绝对要求。按照惯例,返回的对象应通过调用
super.clone
。如果一个类及其所有超类(除Object
)遵守这一约定,情况就是这样x.clone().getClass() == x.getClass()
。按照惯例,此方法返回的对象应该是独立的 此对象(正在克隆)的对象。为了实现这种独立性, 可能需要修改返回对象的一个或多个字段
super.clone
之前返回。通常,这意味着 复制构成内部“深度结构”的任何可变对象 被克隆的对象并替换对这些对象的引用 引用副本的对象。如果一个类仅包含 基本字段或对不可变对象的引用,那么通常super.clone
返回的对象中没有字段的情况 需要修改。类
clone
的方法Object
执行 具体的克隆操作。首先,如果此对象的类 没有实现接口Cloneable
,然后 抛出CloneNotSupportedException
。注意所有数组 被认为实现了Cloneable
接口,并且 数组类型clone
的{{1}}方法的返回类型 是T[]
,其中T是任何引用或原始类型。 否则,此方法将创建此类的新实例。 对象并使用确切的内容初始化其所有字段 该对象的相应字段,就像通过分配;的 字段的内容本身不会被克隆。因此,这种方法 执行此对象的“浅表复制”,而不是“深表复制”操作。类
T[]
本身并不实现接口Object
,因此在对象上调用Cloneable
方法 其类为clone
的结果将引发 运行时出现异常。
因此,您不能在未实现Object
的objets上使用它,但是可以在具有此功能的对象上使用它。