是否有必要在POJO中使用getter和setter

tin*_*tin 11 java coding-style

我一直在阅读干净的代码簿,该代码簿指出该类不应暴露其数据的内部状态,只应暴露该行为.如果一个非常简单和愚蠢的java bean暴露了getter和setter的内部状态,是否值得删除它们并使私有成员公开?或者只是将类视为数据结构?

Des*_*ica 21

我不这么认为.它取决于对象的生命周期及其"暴露"(外部修改).

如果您仅将其用作数据结构,则以安全方式(最终)公开字段听起来足够:

public class Person {
    public final String firstName;
    public final String lastName;

    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}
Run Code Online (Sandbox Code Playgroud)


Pet*_*rey 8

术语POJO旨在将类与JavaBeans或任何其他约定区分开来.因此,根据定义,POJO不需要做任何事情.

我一直在阅读干净的代码簿,该代码簿指出该类不应暴露其数据的内部状态,只应暴露该行为.

这称为封装和良好的原则.

如果一个非常简单和愚蠢的java bean暴露了getter和setter的内部状态,是否值得删除它们并使私有成员公开?

这是另一种方法.有些项目可能会禁止这种方法,而其他项目可能会鼓励这种做法 就个人而言,我赞成这种方法用于以某种方式封装的类,例如它们是本地包.

有一种观点认为,某种程度上某天您的课程可能会有其他要求,并且更改"API"将是不可能的.这违背了YAGNI原则,并且很少证明是这种情况,并且它确实比添加许多不做任何事情的方法成本低得多.

但是,情况并非总是如此,如果您不使用访问器方法,则应考虑在以后必须更改时对项目的影响.在任何地方使用访问器方法意味着您永远不必担心这一点.

总之,如果您非常确定访问器方法毫无意义,以后添加它们不会有问题,我会说您应该使用您的判断.但是,如果您不确定将来是否存在问题,或者您不想担心它,请使用访问器方法.


Lui*_*ano 5

POJO的定义不要求getter / setter。

实验上,我在当前项目中没有使用getter和setter。

我采用的方法是:

除非有必要,否则请不要提供吸气剂/设置剂。

到目前为止,我还没有找到真正需要获取/设置的情况。

一位朋友告诉我:“如果将来需要xyz,则进行获取/设置会很有帮助”;我的答复是:将来,当我需要这样做时,我将提供吸气剂和吸气剂;我不想期待任何事情。

一些人可能提出的关于封装的反对意见实际上不是一个有效的反对意见:以相同的方式提供getter和setter中断封装,另外还有(无用的)代码行。错误也可能存在于getter和setter中。

这是非平凡的域类之一的示例:

public class SSHKey implements IsSerializable {
    public Long id;
    public Long userId;
    public String type;
    public String bits;
    public String fingerprint;
    public String comment;

    @SuppressWarnings("unused")
    private SSHKey() { // required by gwt-rpc
    }

    public SSHKey(String text) throws InvalidSSHKeyException {
        Ensure.that(text != null, new InvalidSSHKeyException("Invalid Key"));
        text = text.trim();
        String[] parts = text.split(" ", 3);
        Ensure.that(parts.length >= 2,
                new InvalidSSHKeyException("Invalid Key"));

        type = getType(parts);
        Ensure.that(type.equals("ssh-rsa") || type.equals("ssh-dss"),
                new InvalidSSHKeyException(
                        "Key must start with 'ssh-rsa' or 'ssh-dss'"));
        bits = getBits(parts);
        comment = getComment(parts);
    }

    private String getBits(String[] parts) {
        return parts[1];
    }

    private String getComment(String[] parts) {
        if (parts.length == 3)
            return parts[2];
        return type + " " + bits.substring(0, min(15, bits.length())) + "...";
    }

    private String getType(String[] parts) {
        return parts[0];
    }
}
Run Code Online (Sandbox Code Playgroud)

构造函数负责验证和准备可管理的数据。因此,此逻辑不需要在setter / getter中。

如果几年前我被公众成员反对,我可能会不喜欢他们。也许我现在做错了,但是我正在尝试,到目前为止还可以。

另外,您还需要考虑是否将您的类设计为可扩展的(因此,可以预见将来是需求的一部分),以及是否希望对象是不可变的。您只能使用get / set做的那些事情。

如果您的对象必须是不可变的,并且可以避免使用空的构造方法,则可以将“ final”添加到成员实例btw中。不幸的是,我必须添加IsSerializable(类似于java.io.Serializable)和一个空的构造函数,因为gwt需要这样做。因此,您可以告诉我,“您知道吗?不太确定。

有一些jdbc框架可以促进对公共字段的使用,例如http://iciql.com。 这并不意味着该项目是正确的,但是有些人正在考虑它。

我认为吸气剂/装填剂的需求主要是文化因素。


SJu*_*n76 2

使成员可访问的问题是您不再从类内部控制它们。

假设您使 Car.speed 可供访问。现在,程序中的任何地方都可以引用它。现在,如果您想确保速度永远不会设置为负值(或者使更改同步,因为您需要使其线程安全),您必须:

  • 在所有可以达到速度的点上,重写程序以添加控制。并希望将来改变程序的每个人都记得这样做。

  • 再次将该成员设为私有,创建 getter 和 setter 方法,并重写程序以使用它们。

最好从一开始就习惯编写 getter 和 setter。无论如何,现在大多数 IDE 都会自动为您完成这些工作。