Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/327.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.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
如果你没有';t克隆在Java中那么你做什么,你叫它什么?_Java_Oop - Fatal编程技术网

如果你没有';t克隆在Java中那么你做什么,你叫它什么?

如果你没有';t克隆在Java中那么你做什么,你叫它什么?,java,oop,Java,Oop,是否有人对Java中的复制构造函数/工厂方法等有任何建议或建立的最佳实践和命名约定?特别是,假设我有一个类Thing,我希望在某个地方有一个方法返回一个新的Thing,其值与传入的Thing相同(如果它是实例方法,则作为实例)。您会将其作为构造函数还是静态工厂方法或实例方法?你叫它什么 根据标题,我希望避免clone()和Cloneable如果需要,可以覆盖-method。另一种使用的实践是构造函数,它接受这种类型的对象,即..我将其称为复制方法或复制构造函数(视情况而定)。如果它是一个静态方法

是否有人对Java中的复制构造函数/工厂方法等有任何建议或建立的最佳实践和命名约定?特别是,假设我有一个类
Thing
,我希望在某个地方有一个方法返回一个新的
Thing
,其值与传入的
Thing
相同(如果它是实例方法,则作为实例)。您会将其作为构造函数还是静态工厂方法或实例方法?你叫它什么


根据标题,我希望避免
clone()
Cloneable

如果需要,可以覆盖-method。另一种使用的实践是构造函数,它接受这种类型的对象,即..

我将其称为复制方法或复制构造函数(视情况而定)。如果它是一个静态方法,那么我会称之为工厂

就做什么而言,最灵活、最长寿的选择是复制构造函数。这使子类能够像父类一样复制自己。

我要做一个构造函数

...
public Thing(Thing copyFrom)
{
    attr1 = copyFrom.attr1;
    attr2 = copyFrom.attr2;
    //etc...
}
然后当你想克隆它的时候

Thing copy = new Thing(copy from me);

您有几个选项,实现
Cloneable
,添加一个复制构造函数,但我更喜欢的方法是使用一个名称(静态或实例)来描述复制操作正在执行的操作-是深度复制还是浅层复制,等等。

有效的Java推荐以下方法之一:

  • 复制构造函数(如其他人所述):

    公共项目(项目)

  • 复制工厂方法:

    公共静态项newInstance(项)

  • (另外,不可变项不允许复制)

    主要区别在于,使用#1选择结果的实际类,使用#2,实现者可以返回一个子类。类的语义可能会指导您选择最佳的类。

    使用。您认为需要克隆()的唯一原因是您正在原地修改对象。别这样。想想你如何做到:

    • 让你的课成为期末考试
    • 将类中的字段设置为最终字段和专用字段
    例如,这里有一个不可变3D矢量对象的“setter”:

    public Vector3D setX(double x) {
      return new Vector3D(x, this.y, this.z);
    }
    

    所以我想我说的是。。。我使用复制构造函数而不是变异,我只是根据要修改的属性命名它们。

    另一个选项是在源对象中实现复制方法,例如:

    interface Has3DCoords {
        void setLocation(double x, double y, double z);
    
        void copyCoordsTo(Has3DCoords dest);
    }
    
    然后,您将使用一段代码实现复制,如:

    class Thing implements Has3DCoords {
        private Point3D loc;
        // ...
    
        void setLocation(double x, double y, double z) {
            loc.setLocation(x, y, z);
            // or: loc = new Point3D(x, y, z);
        }
    
        void copyCoordsTo(Has3DCoords dest) {
            loc.copyCoordsTo(dest);
            // or: dest.setLocation(loc.getX(), loc.getY(), loc.getZ());
        }
    
        OtherThing createOtherThing() {
            OtherThing result = new OtherThing();
            this.copyCoordsTo(result);
            return result;
        }
    }
    
    在以下情况下,这可能很有用:

    • 克隆整个对象没有意义
    • 有一组相关属性通常作为一个单元复制
    • 您不想将
      loc
      作为
      Thing
    • 属性的数量很大(或者有许多这样的组),因此需要所有属性作为参数的构造函数将非常笨拙

    这不是复制对象的最佳方法,但如果您希望对可序列化对象执行深度复制,则以下方法有时非常有用。这避免了必须编写复制构造函数、实现可克隆或编写工厂类

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(bos);
    
    //Serializes the input object
    oos.writeObject(input);
    
    ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray());
    ObjectInputStream ois = new ObjectInputStream(bais);
    
    //Copy of the input object
    Object output = ois.readObject();
    

    别忘了处理异常并很好地关闭流。

    为什么要避免clone()和Cloneable?@Thomas Owens,请参阅此处:回答:将复制构造函数作为解决方案:复制构造函数不能正确处理所有情况。例如,当您不知道具体类时(但仍然可以在clone/copy/whateveryoucallit方法中使用copy构造函数)。