Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 深度复制对象数组_Java_Arrays_Clone - Fatal编程技术网

Java 深度复制对象数组

Java 深度复制对象数组,java,arrays,clone,Java,Arrays,Clone,我对Java还是相当陌生的,现在我正在尝试复制菜单。我想我已经做了一点,创建了一个包含新菜单项的新菜单对象。MenuItems是另一个类,具有两个字符串变量和一个双变量,即itemName和itemDescription以及itemPrice。所以我试图将原始菜单项的三个变量的内容复制到菜单项副本中,但我不知道如何复制。我一直在试图将克隆副本的名称设置为原始名称 public class Menu { Menu() { } final int maxItem

我对Java还是相当陌生的,现在我正在尝试复制菜单。我想我已经做了一点,创建了一个包含新菜单项的新菜单对象。MenuItems是另一个类,具有两个字符串变量和一个双变量,即itemName和itemDescription以及itemPrice。所以我试图将原始菜单项的三个变量的内容复制到菜单项副本中,但我不知道如何复制。我一直在试图将克隆副本的名称设置为原始名称

public class Menu 
{
    Menu()
    {

    }

    final int maxItems = 50;

    MenuItem[] food = new MenuItem[maxItems + 1];


    public Object clone()
    {
        Menu menuClone = new Menu();
        MenuItem[] foodClone = new MenuItem[maxItems + 1];

        for(int i = 1; i <= maxItems + 1; i++)
        {  
            foodClone[i] = new MenuItem();
            foodClone[i] = food[i].setItemName();
        }

    }

你就快到了,你已经:

foodClone[i] = food[i].setItemName();
您可能想要(除了MenuItem的其他变量)

但是,最好使用克隆方法或复制构造函数(嗯,)

我更喜欢使用复制构造函数,例如:

MenuItem(MenuItem menuItemToClone)
{
     this.name = menuItemToClone.name;
     this.descrip = menuItemToClone.descrip;
     this.price = menuItemToClone.price;
}
那么你就做:

foodClone[i] = new MenuItem(food[i]);

尽管前面有一些建议,克隆只提供了一个浅拷贝

深度复制问题的常见解决方案是使用Java对象序列化(JOS)。想法很简单:使用JOS的ObjectOutputStream将对象写入数组,然后使用ObjectInputStream重新构建对象的副本。结果将是一个完全不同的对象,具有完全不同的引用对象。JOS负责所有细节:超类字段、跟踪对象图以及处理对图中相同对象的重复引用。图3显示了一个实用程序类的初稿,该实用程序类使用JOS制作深度副本

import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;

/**
 * Utility for making deep copies (vs. clone()'s shallow copies) of 
 * objects. Objects are first serialized and then deserialized. Error
 * checking is fairly minimal in this implementation. If an object is
 * encountered that cannot be serialized (or that references an object
 * that cannot be serialized) an error is printed to System.err and
 * null is returned. Depending on your specific application, it might
 * make more sense to have copy(...) re-throw the exception.
 *
 * A later version of this class includes some minor optimizations.
 */
public class UnoptimizedDeepCopy {

/**
 * Returns a copy of the object, or null if the object cannot
 * be serialized.
 */
public static Object copy(Object orig) {
    Object obj = null;
    try {
        // Write the object out to a byte array
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bos);
        out.writeObject(orig);
        out.flush();
        out.close();

        // Make an input stream from the byte array and read
        // a copy of the object back in.
        ObjectInputStream in = new ObjectInputStream(
            new ByteArrayInputStream(bos.toByteArray()));
        obj = in.readObject();
    }
    catch(IOException e) {
        e.printStackTrace();
    }
    catch(ClassNotFoundException cnfe) {
        cnfe.printStackTrace();
    }
    return obj;
}
}

不幸的是,这种方法存在一些问题:

  • 它仅在被复制的对象以及该对象直接或间接引用的所有其他对象可序列化时才起作用。(换句话说,它们必须实现java.io.Serializable。)幸运的是,只要声明给定类实现java.io.Serializable并让java的默认序列化机制完成它们的工作就足够了

  • Java对象序列化速度很慢,使用它来创建深度副本需要序列化和反序列化。有一些方法可以加快速度(例如,通过预计算串行版本ID和定义自定义readObject()和writeObject()方法),但这通常是主要的瓶颈

  • java.io包中包含的字节数组流实现被设计为足够通用,可以对不同大小的数据执行合理的操作,并且可以安全地在多线程环境中使用。但是,这些特性通过TearrayInputStream和(在较小程度上)TearrayInputStream减慢


  • 来源:

    如果要克隆对象,我建议尝试使用
    clone()
    方法。您必须正确重写
    clone
    对象并实现可克隆..或简单地创建一个复制构造函数。。还有小费。。java中的数组是基于0的。。所以第一个元素是数组[0],而不是[1]4。Java序列化向外界公开私有状态,并允许在读回对象时违反不变量。
    foodClone[i] = new MenuItem(food[i]);
    
    import java.io.IOException;
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.ObjectOutputStream;
    import java.io.ObjectInputStream;
    
    /**
     * Utility for making deep copies (vs. clone()'s shallow copies) of 
     * objects. Objects are first serialized and then deserialized. Error
     * checking is fairly minimal in this implementation. If an object is
     * encountered that cannot be serialized (or that references an object
     * that cannot be serialized) an error is printed to System.err and
     * null is returned. Depending on your specific application, it might
     * make more sense to have copy(...) re-throw the exception.
     *
     * A later version of this class includes some minor optimizations.
     */
    public class UnoptimizedDeepCopy {
    
    /**
     * Returns a copy of the object, or null if the object cannot
     * be serialized.
     */
    public static Object copy(Object orig) {
        Object obj = null;
        try {
            // Write the object out to a byte array
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(bos);
            out.writeObject(orig);
            out.flush();
            out.close();
    
            // Make an input stream from the byte array and read
            // a copy of the object back in.
            ObjectInputStream in = new ObjectInputStream(
                new ByteArrayInputStream(bos.toByteArray()));
            obj = in.readObject();
        }
        catch(IOException e) {
            e.printStackTrace();
        }
        catch(ClassNotFoundException cnfe) {
            cnfe.printStackTrace();
        }
        return obj;
    }