Java 是否有必要在POJO';s

Java 是否有必要在POJO';s,java,coding-style,Java,Coding Style,我已经阅读了干净的代码手册,其中指出类不应该公开其数据的内部状态,而只应该公开其行为。如果一个非常简单和愚蠢的javabean公开了getter和setter的内部状态,那么仅仅删除它们并公开私有成员难道不值得吗?或者只是将类视为数据结构?使成员可访问的问题是,您不再从类内部控制它们 比如说,你让汽车速度变得容易接近。现在,在你的程序中的每一个地方都可以参考它。现在,如果要确保速度永远不会设置为负值(或者要使更改同步,因为需要确保线程安全),则必须: 在所有可以访问速度的点,重写程序以添加控件

我已经阅读了干净的代码手册,其中指出类不应该公开其数据的内部状态,而只应该公开其行为。如果一个非常简单和愚蠢的javabean公开了getter和setter的内部状态,那么仅仅删除它们并公开私有成员难道不值得吗?或者只是将类视为数据结构?

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

比如说,你让汽车速度变得容易接近。现在,在你的程序中的每一个地方都可以参考它。现在,如果要确保速度永远不会设置为负值(或者要使更改同步,因为需要确保线程安全),则必须:

  • 在所有可以访问速度的点,重写程序以添加控件。并希望将来更改程序的每个人都记得这样做

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


最好从一开始就习惯编写getter和setter。如今,不管怎样,大多数IDE都会自动为您完成这项工作。

对此的标准答案是:您不知道您的简单数据结构在未来是否会保持如此简单。它的发展可能比你现在预期的要多。也有可能,任何时候,您都希望该bean中有一些“值更改”的观察者。使用getter和setter方法,您可以在以后非常简单地执行此操作,而无需更改现有的代码库


getter/setter的另一个优点是:如果在罗马,一定要喜欢罗马人。。。这意味着在本例中:许多通用框架都需要getter/setter。如果您不想从一开始就排除所有这些有用的框架,那么请您和您的同事帮个忙,只需实现标准的getter/和setter。

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

我已经阅读了干净的代码手册,其中指出类不应该公开其数据的内部状态,而只应该公开其行为

这就是所谓的封装,也是一个很好的原则

如果一个非常简单和愚蠢的javabean公开了getter和setter的内部状态,那么仅仅删除它们并公开私有成员难道不值得吗

这是另一种办法。一些项目可能禁止这种方法,而另一些项目可能鼓励这种方法。就我个人而言,对于已经以某种方式封装的类,我更倾向于这种方法,例如,它们是本地包

有一种观点认为,有朝一日,你的类可能会有额外的需求,改变“API”是不可能的。这违背了YAGNI原则,并且很少被证明是这种情况,而且当它确实存在时,它的成本要比添加大量不起任何作用的方法低得多

但是,情况并不总是这样,如果你不使用访问器方法,你应该考虑如果你以后需要改变它对项目的影响。在任何地方使用访问器方法都意味着您无需担心这一点


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

我不这么认为。它取决于对象的寿命及其“曝光”(外部修改)

如果您只是将其用作数据结构,那么以安全方式(最终)公开字段就足够了:

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

    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

这就是@peterlawrey对封装的解释

只有一个注意事项:当您处理复杂对象(例如在ORM项目的域模型中)时,当您具有非简单Java类型的属性时,这一点更为重要。例如:

public class Father {
   private List childs = new ArrayList();
   public Father() {
      // ...
   }
   private List getChilds() { 
      return this.childs;   
   }
   public void setChilds(List newChilds) { 
      this.childs = newChilds; 
   }
}

public class Child {
   private String name;
   // ...
   private String getName() { 
      return this.name;   
   }
   public void setName(String newName) { 
      this.name = newName; 
   }
}

如果将一个属性(如
父类中的
childs
属性)公开为公共属性,则无法识别代码的哪个部分正在设置或更改公开属性的一个属性(例如,在这种情况下,将新的
子项
添加到
父项
,甚至更改现有
子项的
名称
).在本例中,只有父对象可以检索子对象的内容,而所有其他类都可以使用其setter对其进行更改。

我认为最好使用getter和setter,除非您有非常具体的速度/内存/效率要求或非常简单的对象

一个很好的例子是
,在这里暴露
.x
.y
变量可能更好、更有效


这就是说,如果您突然需要setter中的一些逻辑,那么实际上改变几个成员变量的可见性并引入getter和setter(即使是对于大型代码库)也不是一件大事。

JavaBeans需要getter和setter。Pojo不需要,反正这有它的好处

getter和setter的目标是实现封装,它管理对象的内部状态。这允许您在应用程序实现后在应用程序中添加或更改业务规则。例如,如果您有一个只允许3个以上字符的文本字段,则可以更改getter或setter代码在将其分配给属性并引发异常之前,请检查,不执行此操作的其他原因是您可能希望更改实现或更改变量名或类似内容。如果该字段可公开访问并可修改,则无法强制执行此操作 无论如何,您可以使用IDE生成setter和getter

如果你
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];
    }
}