Java 数组的浅层副本,但不是引用的副本

Java 数组的浅层副本,但不是引用的副本,java,Java,我偶然发现了一个问题,我必须创建一个不接受任何输入的方法,并返回这个篮子的MarketProduct数组的浅拷贝(不是引用的拷贝) 我知道解决办法如下 public class Basket { private MarketProduct[] marketproducts; public Basket() { this.marketproducts = new MarketProduct[0]; } public MarketProduct[]

我偶然发现了一个问题,我必须创建一个不接受任何输入的方法,并返回这个篮子的MarketProduct数组的浅拷贝(不是引用的拷贝)

我知道解决办法如下

public class Basket {
    private MarketProduct[] marketproducts;

    public Basket() {
        this.marketproducts = new MarketProduct[0];
    }

    public MarketProduct[] getProducts() {
        return this.marketproducts.clone();
我不明白的是 1.如果它是浅拷贝,那么它就是引用的拷贝,对吗?2.我可以对java中的任何对象使用克隆方法吗?它是复制参考还是复制acutal对象?如果是这样的话,那么下面的内容就可以简化了(不是使用for循环,而是使用clone?)

public void添加(市场产品输入){
MarketProduct[]列表=新市场产品[marketproducts.length];
对于(int i=0;i
  • 如果它是浅拷贝,那么它就是引用的拷贝,对吗 不是。它是一个新数组,包含对与原始数组相同的对象的引用

  • 我可以对java中的任何对象使用克隆方法吗 否。请阅读
    Object.clone()
    Cloneable
    的javadoc以了解规则

    如果是这样的话,那么下面的内容就可以简化了(不是使用for循环,而是使用clone?)

    否,因为
    clone()
    将为您提供相同长度的新数组,因此您将无法在数组末尾添加新元素

  • 如果它是浅拷贝,那么它就是引用的拷贝,对吗 不是。它是一个新数组,包含对与原始数组相同的对象的引用

  • 我可以对java中的任何对象使用克隆方法吗 否。请阅读
    Object.clone()
    Cloneable
    的javadoc以了解规则

    如果是这样的话,那么下面的内容就可以简化了(不是使用for循环,而是使用clone?)

    否,因为
    clone()
    将为您提供相同长度的新数组,因此您将无法在数组末尾添加新元素

  • 如果它是浅拷贝,那么它就是引用的拷贝,对吗
  • 不,它是对新对象的新引用,包含该对象属性的副本。详细信息取决于
    clone
    的实现

  • 我可以对java中的任何对象使用克隆方法吗?它是复制参考还是复制acutal对象
  • 首先,
    clone
    不是数组浅拷贝的合适工具。你可以用它来代替。在您的情况下,您需要为新条目分配一个末尾有空间的数组,然后
    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;
    }
    
    显然这有点昂贵,您可能会考虑使用
    列表
    类之一(可能是
    ArrayList
    ),这样就不会每次都增加数组

    有关克隆,请参见:

    创建并返回此对象的副本。确切的意思 “复制”的类型可能取决于对象的类别。将军 其目的是,对于任何对象
    x
    ,表达式: 将
    为真
    ,这不是绝对要求。 按照约定,返回的对象应该通过调用
    super.clone
    。如果一个类及其所有超类(除
    对象
    )遵守此约定,在这种情况下
    x.clone().getClass()==x.getClass()

    按照约定,此方法返回的对象应该是独立的 此对象(正在克隆)的。为了实现这一独立,, 可能需要修改返回对象的一个或多个字段 通过
    super.clone
    ,然后返回。通常,这意味着 复制构成内部“深层结构”的任何可变对象 正在克隆的对象,并替换对这些对象的引用 引用副本的对象。如果一个类只包含 原语字段或对不可变对象的引用,则通常是
    super.clone
    需要修改。

    对象
    的方法
    clone
    执行 特定的克隆操作。首先,如果这个对象的类 未实现可克隆的接口,则 将引发CloneNotSupportedException
    。请注意,所有阵列 被认为是实现接口
    Cloneable
    ,并且 数组类型的
    clone
    方法的返回类型
    T[]
    T[]
    ,其中T是任何引用或基元类型。 否则,此方法将创建该类的新实例 对象,并使用 该对象的相应字段,就像通过赋值一样;这个 字段的内容本身不会被克隆。因此,这种方法 执行此对象的“浅复制”,而不是“深度复制”操作。

    对象
    本身并不实现接口
    Cloneable
    ,因此在对象上调用
    clone
    方法 其类为
    Object
    将导致抛出 运行时发生异常

    因此,您不能在未实现可克隆的对象上使用它,但可以在实现可克隆的对象上使用它

  • 如果它是浅拷贝,那么它就是引用的拷贝,对吗
  • 不,它是对新对象的新引用,包含该对象属性的副本。详细信息取决于
    clone
    的实现

  • 我可以对java中的任何对象使用克隆方法吗?它是复制参考还是复制acutal对象
  • 首先,
    clone
    不是数组浅拷贝的合适工具。你可以用它来代替。在您的情况下,您需要为新条目分配一个末尾有空间的数组,然后
    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;
    }
    
    x.clone() != x x.clone().getClass() == x.getClass() x.clone().equals(x)