检查对象是否正确内置 Java
Checking an object is correctly built in Java
这是我遇到的一个将军issue/problem。我想知道是否有人知道任何适合的设计模式或技术。
private ExternalObject personObject;
private String name;
private int age;
private String address;
private String postCode;
public MyBuilderClass(ExternalObject obj)
this.personObject=obj;
build();
}
public build() {
setName(personObject.getName());
setAge(personObject.getAge());
setAddress(personObject.getAddress());
setPostCode(personObject.getPostCode());
.
.
. many more setters
}
上面的 class 从队列中获取外部对象并构造 MyBuilderClass 对象。
如果所有字段都设置为非空非空值,则成功构建 MyBuilderClass 对象。
将有许多无法构建的 MyBuilderClass 对象,因为 ExternalObject 中将缺少数据。
我的问题是,检测对象是否已正确构建的最佳方法是什么?
- 我可以在 set 方法中检查 null 或空值并抛出异常。这种方法的问题是抛出异常是昂贵的,它会阻塞日志文件,因为会有很多实例无法构建对象;
我还可以使用哪些其他方法?
据我所知,您可以覆盖对象的 equals 方法并将其与有效的示例对象进行比较。它很脏,可能只在某些情况下有效。
你的方法是我能想到的最好的方法。编写一个单独的方法或 class,例如具有静态验证方法。您可以在任何地方重复使用它。
正如之前的答案所暗示的,这里有 2 个选项,其中一个应该在您尝试设置变量后添加。
使用反射检查是否有任何变量为空。 (如评论中所述,这将检查该对象中的所有字段,但要小心任何超类中的字段)。
public boolean checkNull() throws IllegalAccessException {
for (Field f : getClass().getDeclaredFields())
if (f.get(this) != null)
return false;
return true;
}
对每个变量执行空值检查。
boolean isValidObject = !Stream.of(name, age, ...).anyMatch(Objects::isNull);
Previous answer
如果我错了请纠正我:您正在尝试找到一种检查对象是否有效的好方法,如果不是,请在不使用异常的情况下将此告诉客户端代码。
你可以试试工厂方法:
private MyBuilderClass(ExternalObject obj)
this.personObject=obj;
build();
}
public static MyBuilderClass initWithExternalObject(ExternalObject obj) {
// check obj's properties...
if (obj.getSomeProperty() == null && ...) {
// invalid external object, so return null
return null;
} else {
// valid
MyBuilderClass builder = new MyBuilderClass(obj);
return builder.build();
}
}
现在你知道一个对象是否有效而不使用异常。你只需要检查 initWithExternalObject
返回的值是否为 null.
我不会在没有异常的情况下抛出异常。由于构造函数不生成对象的唯一方法是抛出,因此您不应延迟对构造函数的验证。
我仍然建议构造函数在其结果无效时抛出异常,但在此之前应该进行验证,因此您甚至不要使用无效 ExternalObject
调用构造函数。
是否要将其实现为静态方法boolean MyBuilderClass.validate(ExternalObject)
或通过此验证使用构建器模式,由您决定。
这种验证的另一种方法是使用 java Annotations
:
做一个简单的注释class,假设Validate
:
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@interface Validate {
boolean required() default true;
}
然后将您要显示的字段注释为 @Validate(required=true)
:
class MyBuilderClass {
private ExternalObject externalObject;
@Validate(required=true)
private String name;
@Validate(required=false) /*since it's a primitive field*/
private int age;
@Validate(required=true)
private String address;
@Validate(required=true)
private String postCode;
MyBuilderClass(ExternalObject externalObject) {
this.externalObject = externalObject;
build();
}
public void build() {
setName(personObject.getName());
setAge(personObject.getAge());
setAddress(personObject.getAddress());
setPostCode(personObject.getPostCode());
}
//.
//.
//. many more setters
}
然后在MyBuilderClass
class中添加这个方法,为了检查你的Object是否构建正确:
public boolean isCorrectlyBuilt() throws IllegalAccessException {
boolean retVal = true;
for (Field f : getClass().getDeclaredFields()) {
f.setAccessible(true);
boolean isToBeChecked = f.isAnnotationPresent(Validate.class);
if (isToBeChecked) {
Validate validate = f.getAnnotation(Validate.class);
if (validate.required()/*==true*/) {
if (f.get(this) == null) {
retVal = false;
break;
/* return false; */
}
}
}
}
return retVal;
}
下面是一个使用示例:
public static void main(String[] args) throws Exception {
ExternalObject personObject = new ExternalObject();
personObject.setAge(20);
personObject.setName("Musta");
personObject.setAddress("Home");
personObject.setPostCode("123445678");
MyBuilderClass myBuilderClass = new MyBuilderClass(personObject);
System.out.println(myBuilderClass.isCorrectlyBuilt());
}
Output : true
因为对象构建正确。
这将允许您通过反射选择您想要在结构中的字段,而无需带来从基础 class 继承的字段。
这是我遇到的一个将军issue/problem。我想知道是否有人知道任何适合的设计模式或技术。
private ExternalObject personObject;
private String name;
private int age;
private String address;
private String postCode;
public MyBuilderClass(ExternalObject obj)
this.personObject=obj;
build();
}
public build() {
setName(personObject.getName());
setAge(personObject.getAge());
setAddress(personObject.getAddress());
setPostCode(personObject.getPostCode());
.
.
. many more setters
}
上面的 class 从队列中获取外部对象并构造 MyBuilderClass 对象。
如果所有字段都设置为非空非空值,则成功构建 MyBuilderClass 对象。
将有许多无法构建的 MyBuilderClass 对象,因为 ExternalObject 中将缺少数据。
我的问题是,检测对象是否已正确构建的最佳方法是什么?
- 我可以在 set 方法中检查 null 或空值并抛出异常。这种方法的问题是抛出异常是昂贵的,它会阻塞日志文件,因为会有很多实例无法构建对象;
我还可以使用哪些其他方法?
据我所知,您可以覆盖对象的 equals 方法并将其与有效的示例对象进行比较。它很脏,可能只在某些情况下有效。
你的方法是我能想到的最好的方法。编写一个单独的方法或 class,例如具有静态验证方法。您可以在任何地方重复使用它。
正如之前的答案所暗示的,这里有 2 个选项,其中一个应该在您尝试设置变量后添加。
使用反射检查是否有任何变量为空。 (如评论中所述,这将检查该对象中的所有字段,但要小心任何超类中的字段)。
public boolean checkNull() throws IllegalAccessException {
for (Field f : getClass().getDeclaredFields())
if (f.get(this) != null)
return false;
return true;
}
对每个变量执行空值检查。
boolean isValidObject = !Stream.of(name, age, ...).anyMatch(Objects::isNull);
Previous answer
如果我错了请纠正我:您正在尝试找到一种检查对象是否有效的好方法,如果不是,请在不使用异常的情况下将此告诉客户端代码。
你可以试试工厂方法:
private MyBuilderClass(ExternalObject obj)
this.personObject=obj;
build();
}
public static MyBuilderClass initWithExternalObject(ExternalObject obj) {
// check obj's properties...
if (obj.getSomeProperty() == null && ...) {
// invalid external object, so return null
return null;
} else {
// valid
MyBuilderClass builder = new MyBuilderClass(obj);
return builder.build();
}
}
现在你知道一个对象是否有效而不使用异常。你只需要检查 initWithExternalObject
返回的值是否为 null.
我不会在没有异常的情况下抛出异常。由于构造函数不生成对象的唯一方法是抛出,因此您不应延迟对构造函数的验证。
我仍然建议构造函数在其结果无效时抛出异常,但在此之前应该进行验证,因此您甚至不要使用无效 ExternalObject
调用构造函数。
是否要将其实现为静态方法boolean MyBuilderClass.validate(ExternalObject)
或通过此验证使用构建器模式,由您决定。
这种验证的另一种方法是使用 java Annotations
:
做一个简单的注释class,假设
Validate
:@Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @interface Validate { boolean required() default true; }
然后将您要显示的字段注释为
@Validate(required=true)
:class MyBuilderClass { private ExternalObject externalObject; @Validate(required=true) private String name; @Validate(required=false) /*since it's a primitive field*/ private int age; @Validate(required=true) private String address; @Validate(required=true) private String postCode; MyBuilderClass(ExternalObject externalObject) { this.externalObject = externalObject; build(); } public void build() { setName(personObject.getName()); setAge(personObject.getAge()); setAddress(personObject.getAddress()); setPostCode(personObject.getPostCode()); } //. //. //. many more setters }
然后在
MyBuilderClass
class中添加这个方法,为了检查你的Object是否构建正确:public boolean isCorrectlyBuilt() throws IllegalAccessException { boolean retVal = true; for (Field f : getClass().getDeclaredFields()) { f.setAccessible(true); boolean isToBeChecked = f.isAnnotationPresent(Validate.class); if (isToBeChecked) { Validate validate = f.getAnnotation(Validate.class); if (validate.required()/*==true*/) { if (f.get(this) == null) { retVal = false; break; /* return false; */ } } } } return retVal; }
下面是一个使用示例:
public static void main(String[] args) throws Exception { ExternalObject personObject = new ExternalObject(); personObject.setAge(20); personObject.setName("Musta"); personObject.setAddress("Home"); personObject.setPostCode("123445678"); MyBuilderClass myBuilderClass = new MyBuilderClass(personObject); System.out.println(myBuilderClass.isCorrectlyBuilt());
}
Output : true
因为对象构建正确。
这将允许您通过反射选择您想要在结构中的字段,而无需带来从基础 class 继承的字段。