Obiekty niemutowalne — to obiekty, których stan nie może być zmieniony po utworzeniu. Ich główne cechy:
Zalety obiektów niemutowalnych:
Przykład implementacji klasy niemutowalnej:
public final class Person { private final String name; private final int age; private final List<String> phones; public Person(String name, int age, List<String> phones) { this.name = name; this.age = age; // Ochrona przed mutacją przekazanej listy this.phones = Collections.unmodifiableList(new ArrayList<>(phones)); } public String getName() { return name; } public int getAge() { return age; } public List<String> getPhones() { return phones; } // Zwracamy listę do odczytu }
Dlaczego String w Javie jest niemutowalny i co by się stało, gdyby tak nie było? Wiele osób odpowiada "dla bezpieczeństwa", ale co to oznacza w praktyce?
Odpowiedź:
String jest używany w wielu miejscach: jako klucze w kolekcjach, w logice bezpieczeństwa (np. hasła). Gdyby można było zmieniać stringa przez jedno odniesienie, wpłynęłoby to na wszystkie inne odniesienia do tego samego obiektu, co uniemożliwiłoby prawidłowe działanie kolekcji (np. HashMap — podczas obliczania hashCode) i mogłoby prowadzić do luk w bezpieczeństwie.
Historia
Collections.unmodifiableList.Historia
Date, List). W jednym wątku konfiguracja została zmieniona, a w drugim uzyskano przestarzałe lub niespójne dane, przez co błędnie działał algorytm biznesowy.Historia
W systemie logowania hasła były przechowywane w zmiennym obiekcie. Z powodu niebezpiecznego dostępu nagle "wyciekło" hasło innego użytkownika, ponieważ ten sam obiekt był używany przez wiele wątków.