To fajny artykuł, który przedstawia dwa powody, o których już wspomniano w powyższych odpowiedziach:
- Bezpieczeństwo : system może przekazywać wrażliwe fragmenty informacji tylko do odczytu bez obawy, że zostaną zmienione
- Wydajność : niezmienne dane są bardzo przydatne w zapewnianiu bezpieczeństwa wątków.
I to jest prawdopodobnie najbardziej szczegółowy komentarz w tym artykule. Ma to związek z pulą ciągów w Javie i kwestiami bezpieczeństwa. Chodzi o to, jak zdecydować, co trafia do puli strun. Zakładając, że oba ciągi znaków są równe, jeśli ich sekwencja znaków jest taka sama, wówczas mamy warunek wyścigu określający, kto dotrze tam pierwszy, a wraz z nim kwestie bezpieczeństwa. Jeśli nie, to pula ciągów będzie zawierała zbędne ciągi, co spowoduje utratę korzyści z posiadania jej w pierwszej kolejności. Po prostu przeczytaj to sobie, dobrze?
Rozszerzanie String mogłoby siać spustoszenie wśród równych sobie i stażystów. JavaDoc mówi, że równa się:
Porównuje ten ciąg z określonym obiektem. Wynik jest prawdziwy wtedy i tylko wtedy, gdy argument nie ma wartości null i jest obiektem String, który reprezentuje tę samą sekwencję znaków, co ten obiekt.
Zakładając, że java.lang.Stringnie było ostateczne, a SafeStringmoże równać się a Stringi na odwrót; ponieważ reprezentowałyby tę samą sekwencję znaków.
Co by się stało, gdybyś zgłosił się interndo SafeString- czy SafeStringtrafiłby do puli stringów JVM? ClassLoaderI wszystkich obiektow SafeStringreferencje uznane byłyby następnie zablokowane na miejscu przez cały okres JVM. Otrzymasz stan wyścigu o tym, kto może być pierwszym, który internuje sekwencję postaci - może SafeStringwygrałbyś, może String, a może SafeStringzaładowany przez inny program ładujący (a więc inną klasę).
Jeśli wygrałeś wyścig w puli, byłby to prawdziwy singleton, a ludzie mogliby uzyskać dostęp do całego twojego środowiska (piaskownicy) poprzez refleksję i secretKey.intern().getClass().getClassLoader().
JVM może też zablokować tę dziurę, upewniając się, że do puli zostały dodane tylko konkretne obiekty typu String (bez podklas).
Jeśli equals zostało zaimplementowane w taki sposób, że SafeString! = StringThen SafeString.intern! = String.internI SafeStringmusiałoby zostać dodane do puli. Pula stałaby się wtedy pulą <Class, String>zamiast, <String>a wszystko, czego potrzebujesz, aby wejść do puli, to nowy program ładujący klasy.