Est-ce une bonne pratique d'utiliser la réflexion si elle réduit considérablement la quantité de code passe-partout?
Fondamentalement, il existe un compromis entre les performances et peut-être la lisibilité d'un côté et l'abstraction / l'automatisation / la réduction du code passe-partout de l'autre côté.
Edit: Voici un exemple d'utilisation recommandée de la réflexion .
Pour donner un exemple, supposons qu'il existe une classe abstraite Base
qui a 10 champs et 3 sous SubclassA
- classes , SubclassB
et SubclassC
chacune avec 10 champs différents; ce sont tous de simples haricots. Le problème est que vous obtenez deux Base
références de type et que vous voulez voir si leurs objets correspondants sont du même (sous-) type et sont égaux.
En tant que solutions, il existe la solution brute dans laquelle vous vérifiez d'abord si les types sont égaux, puis vérifiez tous les champs ou vous pouvez utiliser la réflexion et voir dynamiquement s'ils sont du même type et parcourir toutes les méthodes commençant par "get" (convention sur la configuration), appelez-les sur les deux objets et appelez égaux sur les résultats.
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");
}
}