Что он делает:
Он получает массив символов, который, как он знает, имеет правильную длину (например, строковую версию в верхнем регистре) и помещает его в качестве резервного массива строки.(Резервный массив называется value
внутри класса String.)
Почему он это делает:
Чтобы проиллюстрировать, что вы можете поместить туда любой массив символов, который захотите.
Почему это полезно:
Строка неизменна, и это позволяет вам обойти неизменность.Конечно, это делать не рекомендуется - КОГДА-ЛИБО .Напротив, я не удивлюсь, если он скажет: «Берегись, потому что люди потенциально могут сделать это с ВАШИМ кодом. Даже если ты думаешь, что твои вещи безопасны, это может быть не так!»
Последствияэто широко распространено.Неизменяемые переменные больше не являются неизменяемыми.Конечные переменные больше не являются окончательными.Потокобезопасные объекты больше не являются поточно-ориентированными.Контракты, на которые вы рассчитывали, вы больше не можете делать.Все потому, что у какого-то инженера где-то была проблема, которую он не мог исправить обычными средствами, поэтому он копается в раздумьях, чтобы ее решить. Не будь «тем парнем».
Вы также заметите, что теперь изменился хэш-код для этой строки.Итак, если вы никогда не вычисляли hashCode для этой строки, он все равно равен 0, так что все в порядке.С другой стороны, если вы рассчитали его, когда вы собираетесь поместить его в HashMap или HashSet, он не будет извлечен.
Примите во внимание следующее:
import java.util.*;
import java.lang.reflect.*;
class HashTest {
/** Results:
C:\Documents and Settings\glowcoder\My Documents>java HashTest
Orig hash: -804322678
New value: STACKOVERFLOW
Contains orig: true
Contains copy: false
*/
public static void main(String[] args) throws Exception {
Set<String> set = new HashSet<String>();
String str = "StackOverflow";
System.out.println("Orig hash: " + str.hashCode());
set.add(str);
Field stringValue = String.class.getDeclaredField("value");
stringValue.setAccessible(true);
stringValue.set(str, str.toUpperCase().toCharArray()); //
System.out.println("New value: " + str);
String copy = new String(str); // force a copy
System.out.println("Contains orig: " + set.contains(str));
System.out.println("Contains copy: " + set.contains(copy));
}
}
IМогу поспорить, что он делает это как предупреждение против плохого поведения, а не показывает «крутой» трюк.
РЕДАКТИРОВАТЬ: Я нашел статью, на которую вы ссылаетесь, и статью, на которой он основан.В оригинальной статье говорится: «Это означает, что если класс в другом пакете« возится »с интернированной строкой, это может привести к хаосу в вашей программе. Это хорошо? (Вам не нужно отвечать ;-)« Ядумаю, это ясно дает понять, что это скорее руководство по защите, чем совет о том, как кодировать.
Так что, если вы уходите из этой цепочки только с одним фрагментом информации, то это отражение опасно, ненадежно,и не шутите!