1. ホーム
  2. java

Java代入演算子の実行

2023-09-11 08:22:33

質問

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 .

ここで何が起こっているのでしょうか?

どのように解決するのですか?

まず第一に、それは興味深い質問ですが、quot;実際のコード"では決して出てこないはずです。まさに同じ行で呼び出した変数に代入すると、それがどのように機能するかを知っていても混乱します。

ここで起こることは、以下の3つのステップです。

  1. どのオブジェクトに対してメソッドを呼び出すかを決定する (つまり、最初の x を評価し、その結果、文字列 "hello" への参照が得られます)。
  2. パラメータを把握する(例えば x = y を評価し、それによって x を文字列 "goodbye" を指すように変更し、その文字列への参照も返します)
  3. メソッドを呼び出す equals を呼び出します(それぞれ文字列 "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 を呼び出します。