このステートメントの後に、文字列オブジェクトへの参照のメモリへの文字列割り当てが行われます。質問する

このステートメントの後に、文字列オブジェクトへの参照のメモリへの文字列割り当てが行われます。質問する

どうしてこれなの?

String str1 = "one";
String str2 = "two";
System.out.println(str1.equals(str1 = str2)); // false, doesn't assignment of ref. to string object memory location happens after???
System.out.println(str1.equals(str1 = str2)); // true, same statement

模擬面接でこの質問をされたのですが、まだわかりません。

ベストアンサー1

答えはJava言語仕様15.7項の評価順序について説明しています。一般的には左から右に行われます。あなたの場合、評価は

  1. str1 を読み込む (からstr1.equals) ->"one"
  2. str2 を読み込む ( からstr1 = str2) ->"two"
  3. 値をstr1に格納する(からstr1 = str2) -> str1は現在"two"
  4. 完全な式の値str1 = str2は です"two"が、この文では str1 が最初のステップですでにロードされていることに注意してください。再度ロードされることはありません。
  5. "one"パラメータ"two"-> falseを指定して、 equals on (すでにロード済み、上記参照) を呼び出します。

また、逆コンパイルされた Java コード (クラスパスで実行) を確認するとjavap -c ClassName、この順序も表示されます。

       0: ldc           #7                  // String one
       2: astore_1
       3: ldc           #9                  // String two
       5: astore_2
    [...]
       9: aload_1           // <-- loads the value of str1
      10: aload_2           // <-- loads the value of str2
      11: dup
      12: astore_1          // <-- stores to str1
      13: invokevirtual #17 // <-- invokes equals

これは、str1 に格納した後にその値を再度読み込むことはありません。

言語仕様には、エッジケースとその処理方法の例がさらにいくつかあります (「関数の引数の 1 つが例外をスローする関数である場合に何が起こるか」など)。

おすすめ記事