如果大大减少了样板代码的数量,使用反射是否是一种好习惯?
基本上,在性能和一方面的可读性与另一方面的抽象/自动化/简化样板代码之间要进行权衡。
编辑:这是推荐使用反射的示例。
举一个例子,假设有一个抽象类Base
,其具有10个字段和具有3个亚类SubclassA
,SubclassB
并且SubclassC
每个具有10个不同的字段; 它们都是简单的豆子。问题是您有两个Base
类型引用,并且想要查看它们的对应对象是否属于相同(子)类型并且相等。
作为解决方案,有一个原始解决方案,在该解决方案中,您首先要检查类型是否相等,然后检查所有字段,或者可以使用反射并动态查看它们是否属于同一类型,并遍历以“ get”开头的所有方法(约定超出配置),请同时在两个对象上调用它们,并在结果上调用equals。
boolean compare(Base base1, Base, base2) {
if (base1 instanceof SubclassA && base2 instanceof SubclassA) {
SubclassA subclassA1 = (SubclassA) base1;
SubclassA subclassA2 = (SubclassA) base2;
compare(subclassA1, subclassA2);
} else if (base1 instanceof SubclassB && base2 instanceof SubclassB) {
//the same
}
//boilerplate
}
boolean compare(SubclassA subA1, SubclassA subA2) {
if (!subA1.getField1().equals(subA2.getField1)) {
return false;
}
if (!subA1.getField2().equals(subA2.getField2)) {
return false;
}
//boilerplate
}
boolean compare(SubclassB subB1, SubclassB subB2) {
//boilerplate
}
//boilerplate
//alternative with reflection
boolean compare(Base base1, Base base2) {
if (!base1.getClass().isAssignableFrom(base2.getClass())) {
System.out.println("not same");
System.exit(1);
}
Method[] methods = base1.getClass().getMethods();
boolean isOk = true;
for (Method method : methods) {
final String methodName = method.getName();
if (methodName.startsWith("get")) {
Object object1 = method.invoke(base1);
Object object2 = method.invoke(base2);
if(object1 == null || object2 == null) {
continue;
}
if (!object1.equals(object2)) {
System.out.println("not equals because " + object1 + " not equal with " + object2);
isOk = false;
}
}
}
if (isOk) {
System.out.println("is OK");
}
}