Apakah praktik yang baik untuk menggunakan refleksi jika sangat mengurangi jumlah kode boilerplate?
Pada dasarnya ada trade-off antara kinerja dan mungkin keterbacaan di satu sisi dan abstraksi / otomatisasi / pengurangan kode boilerplate di sisi lain.
Sunting: Berikut adalah contoh penggunaan refleksi yang disarankan .
Untuk memberi contoh, anggaplah ada kelas abstrak Base
yang memiliki 10 bidang dan memiliki 3 subclass SubclassA
, SubclassB
dan SubclassC
masing-masing dengan 10 bidang yang berbeda; mereka semua adalah kacang sederhana. Masalahnya adalah bahwa Anda mendapatkan dua Base
jenis referensi dan Anda ingin melihat apakah objek yang sesuai memiliki jenis (sub) yang sama dan sama.
Sebagai solusi ada solusi mentah di mana Anda pertama kali memeriksa apakah jenisnya sama dan kemudian memeriksa semua bidang atau Anda dapat menggunakan refleksi dan melihat secara dinamis apakah mereka dari jenis yang sama dan beralih ke semua metode yang dimulai dengan "dapatkan" (konvensi). lebih dari konfigurasi), panggil mereka pada kedua objek dan sebut sama pada hasil.
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");
}
}