是否有必要在POJO中使用getter和setter
我一直在阅读干净的代码簿,该代码簿指出该类不应暴露其数据的内部状态,只应暴露该行为。 如果一个非常简单和愚蠢的java bean暴露了getter和setter的内部状态,是否值得删除它们并使私有成员公开? 或者只是将类视为数据结构?
我不这么认为。 它取决于对象的生命周期及其“暴露”(外部修改)。
如果您仅将其用作数据结构,则以安全方式(最终)公开字段听起来足够:
public class Person { public final String firstName; public final String lastName; public Person(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } }
术语POJO旨在将类与JavaBeans或任何其他约定区分开来。 因此,根据定义,POJO不需要做任何事情。
我一直在阅读干净的代码簿,该代码簿指出该类不应暴露其数据的内部状态,只应暴露该行为。
这称为封装和良好的原则。
如果一个非常简单和愚蠢的java bean暴露了getter和setter的内部状态,是否值得删除它们并使私有成员公开?
这是另一种方法。 有些项目可能会禁止这种做法,而其他项目可能会鼓励这种做法 就个人而言,我倾向于这种方法用于以某种方式封装的类,例如它们是本地包。
有一种观点认为,有些日子你的课程可能会有额外的要求,改变“API”是不可能的。 这与YAGNI原则相悖,并且很少certificate是这种情况,并且它确实比添加许多不做任何事情的方法成本低得多。
但是,情况并非总是如此,如果您不使用访问器方法,则应考虑如果您以后必须更改它对项目的影响。 在任何地方使用访问器方法意味着您永远不必担心这一点。
总之,如果您非常确定访问器方法毫无意义,以后添加它们不会有问题,我会说您应该使用您的判断。 但是,如果您不确定将来是否存在问题,或者您不想担心它,请使用访问器方法。
POJO的定义并不强制要求getter / setter。
实验上,我没有在当前项目中使用getter和setter。
我采取的方法是这样的:
除非必要,否则不要提供getter / setter。
到目前为止,我没有找到我真正需要获取/设置的情况。
有些朋友告诉我:“如果将来需要xyz,获得/设置是有帮助的”; 我的答复是:在将来 – 我需要这样做,我会提供吸气剂和制定者; 我不想期待什么。
有些人可能提出的关于封装的异议并不是真正有效的:提供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]; } }
构造函数负责validation和准备可管理的数据。 因此,该逻辑不需要在setter / getter中。
几年前,如果我被公众成员看作对象,我可能不会喜欢他们; 也许我现在做错了,但我正在试验,到目前为止还可以。
此外,您需要考虑您的类是否设计为扩展(因此,预见未来是要求的一部分),并且您希望您的对象是不可变的。 那些你只能用get / set做的事情。
如果你的对象必须是不可变的 ,并且你可以避免空的构造函数,你可以将’final’添加到成员实例,顺便说一句。 不幸的是,我不得不添加IsSerializable(类似于java.io.Serializable)和一个空构造函数,因为这是gwt所要求的。 那么,你可以告诉我“你看到了吗?你需要吸气剂是一个二传手”; 好不太确定。
有一些jdbc框架推动使用公共字段btw,如http://iciql.com这并不意味着这个项目是正确的,但有些人正在考虑它。
我认为吸气剂/二传手的需要主要是文化的。
使成员可访问的问题是您不再从类内部控制它们。
假设您可以访问Car.speed。 现在,在你的程序中的任何地方都可以有一些参考。 现在,如果您想确保速度永远不会设置为负值(或者为了使线程安全而使更改同步),您必须:
-
在可以访问速度的所有点中,重写程序以添加控件。 并希望将来改变计划的每个人都记得这样做。
-
再次将成员设为私有,创建getter和setter方法,并重写程序以使用它们。
最好习惯从一开始就写getter和setter。 如今,无论如何,大多数IDE都会自动为您完成。
对此的规范回答是:您不知道您的简单数据结构将来是否会如此简单。 它可能比你现在预期的发展得更多。 也许有可能,您很快就会想要在该bean中使用一些“值已更改”的观察者。 使用getter和setter方法,您可以在以后简单地执行此操作,而无需更改现有的代码库。
getter / setter的另一个优点是:如果在罗马,就像罗马人一样…这意味着在这种情况下:许多通用框架都需要getter / setter。 如果你不想从一开始就统治所有这些有用的框架那么你和你的同事一个忙,并简单地实现标准的getter /和setter。
仅当您在库中使用超出您控制范围的类时才显示该类。
如果您确实发布了这样的库,则统一访问原则规定您应该使用getter和setter,以便以后能够更改底层实现,而无需客户端更改其代码。 Java没有为您提供其他机制。
如果您在自己的系统中使用此类,则不需要:您的IDE可以轻松封装公共字段并在一个安全步骤中更新其所有用法。 在这种情况下,简洁性会赢,并且在您需要封装的时候不会丢失任何东西。
我认为使用getter和setter是个好主意,除非你有非常具体的速度/内存/效率要求或非常简单的对象。
一个很好的例子是Point
,它可能更好,更有效地暴露它的.x
和.y
变量。
也就是说,如果你突然在setter中需要一些逻辑,那么改变一些成员变量的可见性并引入getter和setter即使对于大型代码库也不是很大的努力。
JavaBeans需要getter和setter。 POJO没有,无论如何这有它的好处
getter和setter的目标是实现封装,它管理对象的内部状态。 这允许您在应用程序实现后在应用程序中添加或更改业务规则只更改getter或setter代码,例如,如果您有一个只允许超过3个字符的文本字段可以在将其分配给属性之前进行检查并抛出一个exception,其他原因是,如果您可能想要更改实现或更改变量名称或其他类似的东西。 如果该字段可公开访问和修改,则无论如何都可以使用IDE生成setter和getter,则无法强制执行此操作。
如果您正在开发一个简单的应用程序,可以推荐,如果您的应用程序很复杂,并且不建议进行维护。
对于数据类型对象,如POJO / PODS / JavaBean,在python中,您只有公共成员
您可以设置这些并轻松获取,而无需生成样板设置器和getter代码(在java中,这些样板代码通常(98%)公开内部私有标记,如问题中所述)
在python中,如果你需要与getter进行交互,那么你只需要为此目的定义额外的代码
语言水平清洁有效
在java中他们选择了IDE开发而不是更改基础java,请参阅JavaBean,例如它有多大,java 1.0.2有多久了……
JDK 1。0(1996年1月23日)
EJB规范最初由IBM于1997年开发,后来于1999年由Sun Microsystems(EJB 1.0和1.1)采用
所以只需使用它,使用setter getter,因为这些是由java环境强制执行的
这就是@Peter Lawrey解释封装的真实情况。
只有一个注意事项:当您使用复杂对象时(例如在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; } }
如果您将一个属性(如Father
类中的childs
属性)公开为public,您将无法识别代码的哪个部分正在设置或更改您的公开属性的一个属性(例如,在这种情况下,将新Child
添加到Father
甚至更改现有Child
的name
。 在该示例中,只有Father
对象可以检索子内容,其余所有类都可以使用其setter来更改它。