2013-02-23 3 views
4

Я прочитал this answer о том, как проверить, если строка интернирован в Java, но я не понимаю, следующие результаты:Java 7 - String.intern() поведение

String x = args[0]; // args[0] = "abc"; 
String a = "a"; 
String y = a + "bc"; 
System.out.println(y.intern() == y); // true 

Но если я объявляю строковый:

String x = "abc"; 
String a = "a"; 
String y = a + "bc"; 
System.out.println(y.intern() == y); // false 

Кроме того, без какого-либо строкового литерала, то args[0], кажется, непосредственно интернирован:

// String x = "abc"; 
String y = args[0]; 
System.out.println(y.intern() == y); // true (???) 
// false if the first line is uncommented 

Почему y.intern() == y изменяется в зависимости от того, является ли x литералом или нет, даже для примера, когда используется аргумент командной строки?

Я знаю literal strings are interned at compile time, но я не понимаю, почему это влияет на предыдущие примеры. Я также прочитал несколько вопросов по поводу строки интернирование, как String Pool behavior, Questions about Java's String pool и Java String pool - When does the pool change?. Однако ни одно из них не дает возможного объяснения этому поведению.

Edit:

я ошибочно написал, что в третьем примере результат не изменится, если String x = "abc"; объявлена, но она делает.

+1

Я получаю ложь во всех случаях – aditsu

+0

Вы можете получить «истину» во втором случае, если компилятор должен «обмануть» и объединить 2-е и 3-е задания (что в лучшем случае минимально «легально», учитывая правила Java). –

+0

Такое поведение является пугающим ... –

ответ

6

Это потому, что y.intern() возвращает y, если строка не была интернирована раньше. Если строка уже существует, вызов вернет уже существующий экземпляр, который, скорее всего, отличается от y.

Однако все это сильно зависит от реализации, поэтому могут различаться в разных версиях JVM и компилятора.

+0

Значит ли это, что 'y.intern() == y' является ложным, когда строка уже интернирована? Разве это не противоречит [ответ на который я упомянул в начале] (http://stackoverflow.com/questions/4883821/java-tell-if-a-string-is-interned/4883828#4883828)? –

+0

Если строка, которая равна y, но является другим экземпляром, уже интернирована, вы получите false. Если тот же экземпляр, что и 'y', был ранее интернирован, вы получите правду. Вы также получите правду, если ни одна строка, равная 'y', не была интернирована раньше. – Henry

+0

Это противоречит ответу, но код в ответе неверен. Это должно быть '! =', Чтобы проверить, был ли он уже интернирован. – Jochen

0

Сведения о реализации могут отличаться. Но это именно то поведение, которое я ожидал бы. Ваш первый случай означает, что аргументы командной строки не интернированы по умолчанию. Следовательно, y.intern() возвращает ссылку на y после его интернирования.

Второй случай, когда виртуальная машина автоматически ставит букву, так что y.intern() возвращает ссылку на x, которая отличается от y.

И последний случай снова происходит потому, что по умолчанию ничего не интернировано, поэтому вызов intern() возвращает ссылку на y . Я считаю, что законно работать с String более агрессивно, но это минимальное поведение, требуемое спецификацией, насколько я понимаю.

Смежные вопросы