提问者:小点点

具有Getter/Setter的私有列表与公共列表


在私有类中创建一个全局List并具有getter和setter方法会更好,还是只公开它会更好?Java的标准是什么?

我被教导将变量设为私有,只有getter和setter方法,但是访问公共列表肯定比私有列表更好。

public exampleclassThatContainsTheList.goodieList.add("Candy");

private exampleclassThatContainsTheList.setGoodieList(exampleclassThatContainsTheList.getGoodieList().add("Candy"));

这是我的观点,但我当然更喜欢按照标准去做,而不是按照看起来好的去做。


共3个答案

匿名用户

首先,您不应该直接使用public字段,除非它们是常量(静态最终)字段并确保它们的状态不会改变。它们应该使用封装公开,以避免您的类的客户端修改状态。这是一个通过以防御方式实现getter/setter来编写自己的框架的示例,以便不改变List的当前状态:

public class Foo {
    private List<String> stringList;
    public Foo() {
        //always initialized, never null
        this.stringList = new ArrayList<>();
    }
    public List<String> getStringList() {
        //defensive implementation
        //do not let clients to alter the state of the list
        //for example, avoiding clear the list through getStringList().clear()
        return new ArrayList(stringList);
    }
    public void setStringList(List<String> stringList) {
        //defensive implementation
        //do not let clients to pass a null parameter
        this.stringList = (stringList == null) ? new ArrayList<>() : new ArrayList<>(stringList);
    }
}

除此之外,JavaBean规范声明Java类中的字段不应该是public,它们的访问应该通过getter和setter方法。

7 房源

属性是Java Bean的离散的命名属性,会影响其外观或行为。例如,GUI按钮可能有一个名为“Label”的属性,它表示按钮中显示的文本。

属性以多种方式显示:

  1. 属性可能会在脚本环境中公开,就好像它们是对象的字段一样。因此,在Javascript环境中,我可能会执行“b.Label = foo”来设置属性的值。
  2. 属性可以通过调用其 getter 和 setter 方法的其他组件以编程方式访问(请参阅下面的第 7.1 节)。

(...)

7.1访问器方法

属性总是通过对其所属对象的方法调用来访问。对于可读属性,将有一个getter方法来读取属性值。对于可写属性,将有一个setter方法来允许属性值被更新。

有些框架遵循这些规范,以便允许通过反射注入/检索类字段的值。例如,Spring和JSF。

通过XML配置的Spring示例:

<bean id="fooBean" class="my.package.Foo">
    <property name="stringList">
        <list>
            <value>Hello</value>
            <value>World</value>
        </list>
    </property>
</bean>

以及相关的Java类:

package my.package;

public class Foo {
    private List<String> stringList;
    public String getStringList() {
        return this.stringList;
    }
    //allows Spring to set the value of stringList through reflection
    public void setStringList(List<String> stringList) {
        this.stringList = stringList;
    }
}

使用表达式语言进行字段绑定的JSF示例:

<!-- allows JSF to call getter through reflection -->
<h:dataTable value="#{foo.stringList}" var="value">
    <h:column>
        #{value}
    </h:column>
</h:dataTable>

以及相关的Java类:

package my.package;

@ManagedBean
@ViewScoped
public class Foo {
    private List<String> stringList;
    @PostConstruct
    public void init() {
        stringList = new List<>();
        stringList.add("Hello");
        stringList.add("world");
    }
    public String getStringList() {
        return this.stringList;
    }
    public void setStringList(List<String> stringList) {
        this.stringList = stringList;
    }
}

使用哪种选项:防御型getter/setter还是普通getter/seter?这将取决于你在做什么。

匿名用户

标准是拥有私有实例变量和公共getter/setter方法(就像你被教导的那样)。你总是想封装或“隐藏”数据,这是OOP的基本概念之一。这样做的主要好处之一(除其他外)是修改我们实现的代码,而不会破坏可能使用相同代码的其他开发人员的代码。这种方法还会增加可运维性。

匿名用户

我会更进一步:

为什么有人知道你是如何存储数据的?信息隐藏是关键词。在您的示例中,关于数据类型泄漏到外部的详细信息。关键字列表泄露了关于实现的细节,这是1)不必要的信息-你甚至可以将其命名为2)你的类的可能用户是否对实现做出假设,这是一件坏事。给你的类一个域名,比如goodies,给方法命名,比如put/pull。如果要添加多个元素,我会使用更通用的接口,如Iterable。