Menjadi final tidak sama dengan tidak berubah.
final != immutable
Kata final
kunci digunakan untuk memastikan referensi tidak berubah (yaitu, referensi yang dimilikinya tidak dapat diganti dengan yang baru)
Tetapi, jika atributnya adalah self dapat dimodifikasi, maka tidak masalah untuk melakukan apa yang baru saja Anda jelaskan.
Contohnya
class SomeHighLevelClass {
public final MutableObject someFinalObject = new MutableObject();
}
Jika kita membuat instance kelas ini, kita tidak akan dapat menetapkan nilai lain ke atribut someFinalObject
karena sudah final .
Jadi ini tidak mungkin:
....
SomeHighLevelClass someObject = new SomeHighLevelClass();
MutableObject impostor = new MutableObject();
someObject.someFinal = impostor;
Tetapi jika objek itu sendiri bisa berubah seperti ini:
class MutableObject {
private int n = 0;
public void incrementNumber() {
n++;
}
public String toString(){
return ""+n;
}
}
Kemudian, nilai yang terkandung oleh objek yang bisa berubah itu dapat diubah.
SomeHighLevelClass someObject = new SomeHighLevelClass();
someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();
System.out.println( someObject.someFinal );
Ini memiliki efek yang sama dengan postingan Anda:
public static void addProvider(ConfigurationProvider provider) {
INSTANCE.providers.add(provider);
}
Di sini Anda tidak mengubah nilai INSTANCE, Anda mengubah status internalnya (melalui, metode provider.add)
jika Anda ingin mencegah definisi kelas harus diubah seperti ini:
public final class ConfigurationService {
private static final ConfigurationService INSTANCE = new ConfigurationService();
private List providers;
private ConfigurationService() {
providers = new ArrayList();
}
....
Tapi, itu mungkin tidak masuk akal :)
Omong-omong, Anda juga harus menyinkronkan akses ke sana pada dasarnya untuk alasan yang sama.