暴露不可变对象的状态是否可以?

64

最近我接触到了不可变对象的概念,我想知道控制状态访问的最佳实践。尽管面向对象的那部分大脑让我想在看到公共成员时退缩,但我认为像这样的东西没有技术问题:

public class Foo {
    public final int x;
    public final int y;

    public Foo( int x, int y) {
        this.x = x;
        this.y = y;
    }
}

我更愿意将字段声明为private并为每个字段提供getter方法,但当状态明确为只读时,这似乎过于复杂。

对于提供不可变对象的状态访问权限,最佳实践是什么?

13个回答

1
在仅仅为了将两个值以有意义的名称相互关联的情况下,您甚至可以考虑跳过定义任何构造函数并保持元素可变:
public class Sculpture {
    public int weight = 0;
    public int price = 0;
}

这样做的好处在于,在实例化类时最大程度地减少混淆参数顺序的风险。如果需要限制可变性,可以通过将整个容器置于private控制下来实现。

@miniBill不能是最终版本,我猜测?好的,但私有的。我会更改的。 - Wolf

1
我经常使用与您在问题中提出的非常相似的结构,有时候用(有时是不可变的)数据结构比用类更好地建模一些东西。
一切都取决于您正在建模的对象,如果您正在建模一个对象,则该对象由其行为定义,在这种情况下,永远不要公开内部属性。其他时候,您正在建模数据结构,Java没有专门的构造数据结构的结构,因此可以使用类并公开所有属性,如果您想要不变性,当然可以使用final和public。
例如,罗伯特·马丁(Robert Martin)在伟大的书《代码整洁之道》中有一章关于此事,我认为这是必读的。

0

只是想要反映反思

Foo foo = new Foo(0, 1);  // x=0, y=1
Field fieldX = Foo.class.getField("x");
fieldX.setAccessible(true);
fieldX.set(foo, 5);
System.out.println(foo.x);   // 5!

那么,Foo 还是不可变的吗?:)


1
你可以使用反射来调用私有方法,但人们仍然称私有方法为私有的。当然,尽管你可以使用一些技巧来违反不可变性,但Foo是不可变的。还有其他方法,被Java领域中非常著名的库使用,比如字节码增强。 - AlfredoCasado
没错...不过,我讨厌反射,因为它的缘故。使用反射,你可以做所有通常不被允许的事情。但最终你能够做到! - bobbel
至少在Java中,您有安全管理器,可以保护您的代码免受“未经授权访问”的侵害,包括反射。虽然这不是Java中最常用的功能,但对于某些极端情况而言,它是存在的。如果您不喜欢反射,那么您可能会喜欢Ruby、Python或JavaScript :P - AlfredoCasado

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接