简体   繁体   English

如何创建具有可变对象的不可变类作为引用

[英]how Immutable class is created having mutable object as refernce

I am asking very basis question about 'How to make immutable Object in java'. 我问的问题是“如何在java中创建不可变对象”。

So I have one Address class from third party which does not inherit any Cloneable interface and its mutable class. 所以我有一个来自第三方的Address类,它不继承任何Cloneable接口及其可变类。 It looks like this 看起来像这样

public class Address {

    private String city;
    private String address;

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

Now I have another immutable class called Person which implements Cloneable interface and also override clone method.Class Looks like this 现在我有另一个名为Person的不可变类,它实现了Cloneable接口,并且还覆盖了clone方法.Class看起来像这样

public class Person implements Cloneable {

    private String name;
    private Address address;

    public Person() {

    }

    public Person(String name, Address address) {
        this.name = name;
        this.address = address;
        //this.address = (Address) address.clone();
    }

    public String getName() {
        return name;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person person = (Person) super.clone();
        return super.clone();
    }

    public Address getAddress() {
        return address;
    }

    @Override
    public String toString() {
        return "name:" + name + ", address" + address.getAddress() + ", city="
                + address.getCity();
    }

}

Now my question is, surely I can clone the Person class object but how can address class instance be cloned. 现在我的问题是,我当然可以克隆Person类对象但是如何克隆类实例。 I also read some article about shallow cloning and deep cloning. 我还阅读了一些关于浅层克隆和深度克隆的文章。 But I could not understand the how deep cloning can be done with thirty party API. 但我无法理解使用三十方API可以做多深的克隆。 Or correct me if I understood something wrong about cloning. 如果我理解克隆的错误,请纠正我。

I think you understand very well: clone is a bad mechanism and there's actually a complete list of things wrong with it (check out Effective Java). 我认为你理解得很好: clone是一种糟糕的机制,实际上有一个完整的错误列表(请查看Effective Java)。 Particularly relevant to your case, you cannot deep-clone an object with final fields. 与您的情况特别相关,您无法使用final字段深度克隆对象。

Instead choose a custom mechanism for copying objects, such as copy-constructors or dedicated methods. 而是选择用于复制对象的自定义机制,例如复制构造函数或专用方法。

There is also a trick with in-memory serialize-deserialize cycle, but I wouldn't really recommend it unless performance and efficiency are not high on your list. 内存序列化 - 反序列化循环也有一个技巧,但我不会真的推荐它,除非你的列表中的性能和效率不高。

One of the many problems with the Cloneable facility is that after calling super.clone() there can be fields whose state you need to go back and -fix- before returning the cloned value. Cloneable工具的许多问题之一是在调用super.clone()之后,在返回克隆值之前,可能存在需要返回状态的字段和-fix-。 This prevents you from making those fields final in your class and is at odds with the principle of an immutable class. 这可以防止你在你的类中使这些字段成为final ,并且与不可变类的原则不一致。 Moreover, the facility can introduce security vulnerabilities into your class chiefly because it relies on an extralinguistic mechanism for object creation. 此外,该设施可能会在您的班级中引入安全漏洞,主要是因为它依赖于创建对象的语言机制。

A good rule of thumb is if you can avoid implementing Cloneable in your classes, then avoid it. 一个好的经验法则是, 如果您可以避免在类中实现Cloneable,那么请避免使用它。

As Marko mentioned, copy constructors of copy factory methods are usually superior strategies that do not rely upon a flawed, extralinguistic mechanism for object creation. 正如Marko所提到的,复制工厂方法的复制构造者通常是优越的策略,不依赖于有缺陷的,用于创建对象的语言机制。 The only good time to use the clone() method of which I am aware is when obtaining defensive copies of arrays of immutable values such as primitives or Strings . 使用我所知道的clone()方法的唯一好处是获取不可变值数组(如基元或Strings防御性副本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM