1

假设你有一个类Dog,它有

public class Dog {

    private String name;
    private double age;

    // some setters
    // some getters

此外,您有一个类DogHandler,它创建一个实例Dog d并将其传递给Owner

我想,我可以

...在将 Dog 传递给之前制作一个副本Owner,但这是一项昂贵的操作,我宁愿避免它。

...提出一个 Dog实现仅包含getter的接口,Dog转换为该接口并传递结果

...在构造函数中初始化可设置变量,并且根本不允许更改此对象实例

有没有其他方法可以确保对象的接收者不能修改它?

如何获取包含一些数据的简单 bean 并将其设为只读?

4

4 回答 4

2

这可以通过几种方式实现,我可以向您推荐其中两种:

a) 与 getter 接口是个好主意

b) 从 Dog 创建派生类,该类阻止了 setters 方法,如下所示:

class UnmodifiedDog extends Dog {
    public UnmodifiedDog(double age, String name) {
        super.setAge(age);
        super.setName(name);
    }
    @Override
    public void setAge(double age) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void setName(String name) {
         throw new UnsupportedOperationException();
    }   
}

在 DogHandler 中:

Dog createDog() {
    return new UnmodifiedDog(10, "Fido");
}

您可以将其传递给所有者:

owner.receiveDog(dogHandler.createDog());
于 2011-09-21T20:04:57.200 回答
0

您在问题中提到的方法几乎是使Dog不可变所采取的标准步骤。唯一的另一个技巧是Dog通过将类声明为 来强制不能被覆盖final

于 2011-09-21T20:09:55.087 回答
0

在此处提到的解决方案中,您还可以利用可见性修饰符。如果DogOwner位于单独的包中,您可以将修改器的可见性设置为默认(包)范围或受保护范围。

这将允许您将Dog和保留DogHandler在同一个包中(因此允许它们都Dog相应地改变对象),同时保持Owner对象分离(从而防止它们对Dog对象进行任何修改)。

于 2011-09-21T20:21:57.703 回答
0

这是一个使用接口和包访问设置器的示例。


package blah.animal;
public interface Dog
{
  double getAge();
  String getName();
}

package blah.animal;
public class DogImpl implements Dog
{
  private double age; // double seems wrong for age.
  private String name;

  ... getters (defined by Dog interface)

  // package access setters.
  void setAge(double newValue)
  {
    age = newValue;
  }

  void setName(String newValue)
  {
    name = newValue;
  }

  package blah.animal;
  public class DogHandler
  {
    public static Dog newDog(double age, String name)
    {
      Dog returnValue = new DogImpl();
      returnValue.setAge(age);
      returnValue.setName(name);

      return returnValue;
    }
  }

  package.blah.somethingelse;
  public class Blam
  {
    private Dog myDog;

    public Blam()
    {
      myDog = DogHandler.newDog(1.4D, "Tippy");
    }
  }
于 2011-09-21T20:39:19.700 回答