我想知道这个简单问题的答案。
当我创建一个实体对象并且我想限制一个属性的设置时(例如我不想让任何人设置一个小于1的整数值到一个属性),我应该在setter中实现它这个属性的属性还是我应该在处理这些对象的类中检查这个限制?一般来说,只要我的getter返回并且setter设置属性,我可以实现getter和setter吗?
我知道java中有一些规则(代码约定),所以我不想破坏它们中的任何一个。
提前致谢,希望我的问题足够明确,并对我可能犯过的任何语法错误表示抱歉:/。
答案 0 :(得分:6)
是的getter / setter对此非常有用。
例如:
public void setAge(int age){
if(age < 0){
throw new IllegalArgumentException("Invalid age : " + age);
//or if you don't want to throw an exception you can handle it otherways too
}
}
您也可以将Java-EE的Bean Validators用于此
public class Person{
@Min(value = 0)
@Max(value = 99)
private Integer age;
//some other code
}
答案 1 :(得分:2)
我首选的方法是使用JSR 303(Bean Validation API)来确保类的属性有效。
在setter中执行验证是相当不错的,但这并不总是一种理想的方法。有可能混合几个彼此无关的背景的需求。例如,某些属性绝不能从用户界面设置,而是在保持之前由服务计算。在这种情况下,不希望在setter中包含这个逻辑,因为你需要知道调用setter的上下文;您需要在UI层和持久层中应用不同的规则。 JSR 303允许您使用验证组分离这些问题,以便您的UI验证组与持久性验证组不同。
在JPA 2.0中,当您使用由JSR 303验证器评估的约束来注释您的类时,您的持久性提供程序可以自动评估PrePersist
,PreUpdate
和PreRemove
上的这些约束。 (通常没有完成;见下文)实体的生命周期事件。要在JPA提供程序中执行实体验证,您必须在validation-mode
文件中指定javax.persistence.validation.mode
元素或persistence.xml
属性;值必须为AUTO
(默认值)或CALLBACK
(而非NONE
)。
Bean Validation提供程序的存在足以确保在JPA实体生命周期事件上进行验证,因为默认值为AUTO
。默认情况下,您在Java EE 6应用程序服务器中获得此项; Glassfish使用JSR 303的RI实现,它是Hibernate Validator,它也适用于EclipseLink。
CALLBACK
模式将允许您覆盖触发生命周期事件时要应用的验证组。默认情况下,将验证默认Bean验证组(Default
)是否有更新和持久事件; remove事件不涉及任何验证。 CALLBACK
模式允许您使用属性javax.persistence.validation.group.pre-persist
,javax.persistence.validation.group.pre-update
和javax.persistence.validation.group.pre-remove
为这些事件指定不同的验证组。
请记住,JSR 303验证可以在Java EE容器外部使用,尽管上面发布的Bean Validation API文档链接来自Java EE 6 API文档。
答案 2 :(得分:1)
这是getter和setter的目标。
如果我们不能在这些方法中添加一些行为,那么......为什么我们不使用公共属性?
答案 3 :(得分:0)
从我对你的问题的理解,它几乎与封装OO原则有关。 您可以查看这篇文章:http://www.tutorialspoint.com/java/java_encapsulation.htm
答案 4 :(得分:0)
Getters和setter非常适合添加限制,就像Jigar Joshi在他的回答中一样。这样你就可以立即获得反馈并在引入问题时解决问题。
另一个解决方案是使用对象验证(类似于JSR-303实现),它允许您使用最小值和最大值来注释字段。像
这样的东西@Min(value=1)
private int myvalue;
然后,您可以一次性验证整个对象,如果您有其他受约束的字段,则可以获取所有消息。这在任何地方显然都没用,但如果它符合您的需要,那么它就是一种选择。
最后,当你说“实体”时,我会想到存储在数据库中或与ORM工具相关的东西。如果是这种情况,您将需要小心在getter中执行的操作。例如,如果在getter中进行延迟初始化,则某些ORM供应商会将该实体标记为脏并尝试将其刷新到数据库,从而可能导致意外写入。