Jak prawie każdy wie, struny w Javie są niezmienne. Ostatnio odkryłem coś, co może sugerować, że nie zawsze jest to prawda. Spróbujmy się ten kod:Zmutowane struny w Javie
System.out.println("-------- BEFORE MODIFICATIONS --------");
String beforeTest = new String("Original");
System.out.println(beforeTest);
java.lang.reflect.Field valueField = String.class.getDeclaredField("value");
valueField.setAccessible(true);
valueField.set("Original", "Modified".toCharArray());
System.out.println("-------- AFTER MODIFICATIONS --------");
System.out.println(beforeTest);
System.out.println("Original");
String test = new String("Original");
System.out.println(test);
String test2 = new String("Original 2");
System.out.println(test2);
wyjście byłoby:
-------- BEFORE MODIFICATIONS --------
Original
-------- AFTER MODIFICATIONS --------
Original
Modified
Modified
Original 2
Jak to działa sztuczka? W jaki sposób JVM wie, które obiekty powinny zostać zmienione, a które nie? Jaki mechanizm znajduje się pod maską tej sztuczki? Dlaczego utworzony ciąg beforeTest
nie został zmieniony? Czy ta sztuczka rzeczywiście stanowi odstępstwo od zasady strings are immutable
?
Odbicie to czarna magia voodoo. –
@HovercraftFullOfEels, Reflection jest doskonale zdefiniowany. Dopiero gdy naruszasz 'private' przez wywołanie' setAccessible', to niezmienniki klasy core wychodzą przez okno. –
@MikeSamuel Reflection * sama * jest dobrze zdefiniowana. * Używanie * nie jest, dlatego voodoo raz głupi zaczyna się niemożliwie. Mam do tego całe ramy (Muckito). –