Выполнение оператора присваивания Java
в Java я понимаю, что присваивание оценивает значение правого операнда, поэтому операторы типа x == (y = x) оценка для true.
этот код, однако, выходы false.
public static void main(String[]args){
String x = "hello";
String y = "goodbye";
System.out.println(x.equals(x = y));
}
почему это? В моем понимании, он сначала оценивает (x = y), который назначает x значение y, а затем возвращает значение y. Тогда x.equals(y) оценивается, что должно быть true С x и y должны иметь одинаковые ссылки теперь, но вместо этого, я получаю false.

что здесь происходит?
9 ответов:
прежде всего: это интересный вопрос, но он никогда не должен возникать в "реальном коде", поскольку назначение переменной, которую вы вызываете в той же строке, сбивает с толку, даже если вы знаете, как это работает.
что происходит, вот эти 3 шага:
- выяснить, какой объект для вызова метода (т. е. оценить первый
x, это приведет к ссылке на строку "hello")- выяснить параметры (т. е. оценить
x = y, которым изменитсяxчтобы указать на строку "goodbye", а также вернуть ссылку на эту строку)- вызов метода
equalsна результат #1, используя результат #2 в качестве параметра (который будет ссылки на строки "hello" и "goodbye" соответственно).глядя на байтовый код, созданный для этого метода, становится ясно (предполагая, что вы свободно владеете байт-кодом Java):
0: ldc #2 // String hello 2: astore_1 3: ldc #3 // String goodbye 5: astore_2 6: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream; 9: aload_1 10: aload_2 11: dup 12: astore_1 13: invokevirtual #5 // Method java/lang/String.equals:(Ljava/lang/Object;)Z 16: invokevirtual #6 // Method java/io/PrintStream.println:(Z)V 19: returnстрока #9-это шаг 1 выше (т. е. оценивает
xи запоминает значение).строка #10-12-это шаг 2. Он загружает
y, дублирует его (один раз для присвоения, один раз для возвращаемого значения выражения присваивания) и присваивает егоx.строка #13 вызывает
equalsна результат, вычисленный в строке #9 и результат строк #10-12.
хороший вопрос! И у JLS есть ответ...
§15.12.4.1 (пример 15.12.4.1-2). Порядок Оценки При Вызове Метода:
как часть вызова метода экземпляра существует выражение, которое обозначает объект, который будет вызван. Это выражение, кажется, полностью вычисляется перед любой частью любого выражения аргумента метода вызов оценивается.
так, в:
String x = "hello"; String y = "goodbye"; System.out.println(x.equals(x = y));возникновение
xдо.equalsвычисляется первым, перед выражением аргументаx = y.поэтому ссылка на строку
helloзапоминается как целевая ссылка перед локальной переменнойxизменяется для ссылки на строкуgoodbye. В результатеequalsметод вызывается для объектаhelloС аргументомgoodbye, так что результат вызоваfalse.
важно помнить, что a
Stringв java это объект, а значит и ссылка. Когда вы звонитеx.equals(...)он проверяет, если значение в месте, на которое в настоящее время ссылается
xравно тому,что вы проходите. Внутри, вы меняете значениеxи ссылка, но ты все еще звонишьequalsС оригинал ссылка (ссылка на "привет"). Итак, прямо сейчас ваш код сравнивается, чтобы увидеть, если "привет "равнозначно" до свидания", чего явно нет. После этого момента, если вы используетеxопять же, это приведет ссылку на то же значение, что и y.
x=yв скобках означает, что выражение(x=y)теперьgoodbye, в то время как внешний x вx.equalsимеет значениеhello
Реймус дал правильный ответ, но я хотел бы уточнить.
в Java (и большинстве языков) соглашение переменная идет слева, назначение справа.
давайте разберем его:
String x = "hello"; //x <- "hello" String y = "goodbye"; //y <- "goodbye";для целей отладки, а также читабельности кода, это всегда хорошая практика, чтобы разделить ваши строки, так что они делают только одну вещь.
System.out.println(x.equals(x = y)); //Compound statementздесь
x.equals(...)вызывается на исходную ссылку на x, или "Привет", он обновляется для вторая ссылка.Я бы написал это как (и это даст вам ожидаемый ответ):
x = y; // x <- y = "goodbye" boolean xEqualsX = x.equals(x); // xEqualsX <- true System.out.println(xEqualsX); // "true"теперь это кажется очевидным, что он должен вести себя таким образом, но это также очень легко увидеть, что именно происходит в каждой строке, которая является то, что вы должны стремиться.
Я пробовал ваш вопрос в eclipse, ваше выражение правильно. 1) x = = (y = x) оценить в true это верно, потому что значение x присваивается y, который является "привет", то x и y сравнить они будут то же самое так результат будет true
2) x. равно (x = y) это ложь поскольку значение y присваивается x, которое является прощальным, то x и X сравнивают их значение будет отличаться, поэтому результат будет ложным
Я вижу вопрос в непрофессиональных терминах как
"hello".equals("goodbye"). Поэтому он возвращает false.
в java строка-это класс.
String x = "hello"; String y = "goodbye";это две разные строки, которые ссылаются на два разных значения, которые не совпадают а если сравнивать
System.out.println(x.equals(x = y)); //this compare value (hello and goodbye) return true System.out.println(x == (y = x)); // this compare reference of an object (x and y) return false
Comments