如何防止不可变对象中的可变对象的更改

时间:2015-07-29 10:10:57

标签: java immutability

有人可以告诉我们如何阻止用户修改不可变类中定义的可变对象的值吗?

示例: 我们有一个不可变的Student类,它包含Address类的最终引用,它是可变的。我想阻止用户在Address类中进行任何更改?

2 个答案:

答案 0 :(得分:1)

安排Address成为interface。像往常一样使你的可变MutableAddress成为一个ImmutableAddress包装它,防止对字段的写访问。

interface Address {

    public String getNumber();

    public void setNumber(String number) throws IllegalAccessException;

    public String getStreet();

    public void setStreet(String street) throws IllegalAccessException;

    public String getZip();

    public void setZip(String zip) throws IllegalAccessException;

}

class MutableAddress implements Address {

    String number;
    String street;
    String zip;

    @Override
    public String getNumber() {
        return number;
    }

    @Override
    public void setNumber(String number) {
        this.number = number;
    }

    @Override
    public String getStreet() {
        return street;
    }

    @Override
    public void setStreet(String street) {
        this.street = street;
    }

    @Override
    public String getZip() {
        return zip;
    }

    @Override
    public void setZip(String zip) {
        this.zip = zip;
    }

}

class ImmutableAddress implements Address {

    private final Address address;

    public ImmutableAddress(Address address) {
        this.address = address;
    }

    @Override
    public String getNumber() {
        return address.getNumber();
    }

    @Override
    public void setNumber(String number) throws IllegalAccessException {
        throw new IllegalAccessException("Cannot write to this field.");
    }

    @Override
    public String getStreet() {
        return address.getStreet();
    }

    @Override
    public void setStreet(String street) throws IllegalAccessException {
        throw new IllegalAccessException("Cannot write to this field.");
    }

    @Override
    public String getZip() {
        return address.getZip();
    }

    @Override
    public void setZip(String zip) throws IllegalAccessException {
        throw new IllegalAccessException("Cannot write to this field.");
    }

}

或者,将其包裹在Proxy中。这要复杂得多,但是当您无法访问来源时可以提供帮助。

答案 1 :(得分:1)

所以你需要:

1.使最终和私人的可变课程。

2.对于任何可变对象,您必须防止从外部看到对该对象的引用。

在这种情况下,#2可能意味着您不能像使用getAddress()那样返回对Address的引用。你必须在构造函数中制作一个防御性副本。即,制作任何可变参数的副本,并将副本存储在Employee中。如果你不能制作防御性副本,那么就没有办法让员工不变。

public final class Employee{
        private final int id;
        private final Address address;
        public Employee(int id, Address address)
        {
            this.id = id;
            this.address=new Address();  // defensive copy
            this.address.setStreet( address.getStreet() );
        }
        pulbic int getId(){
            return id;
        }
        public Address getAddress() {
            Address nuAdd = new Address(); // must copy here too
            nuAdd.setStreet( address.getStreet() );
            return nuAdd;
    }

How can we maintain Immutability of a class with a mutable reference