1. ホーム

[解決済み】 x == (x = y) と (x = y) == x はなぜ同じではないのですか?

2022-04-11 14:01:18

疑問点

次のような例を考えてみましょう。

class Quirky {
    public static void main(String[] args) {
        int x = 1;
        int y = 3;

        System.out.println(x == (x = y)); // false
        x = 1; // reset
        System.out.println((x = y) == x); // true
     }
}

Java言語仕様の中に、変数の前の値を読み込んで右辺と比較することを指示する項目があるのかどうか、よくわかりません( x = y のように、括弧が意味する順序によって、最初に計算されるべきです。

なぜ最初の式は false であるのに対し、2つ目の評価では true ? 私は (x = y) が最初に評価され、次に x を自分自身と置き換えます ( 3 を返します。 true .


とは異なる質問です。 Java式における部分式の評価順序 その中で x は、ここでは間違いなく「部分式」ではありません。次のようにする必要があります。 ロード は、「評価」されるのではなく、「比較」されるのです。この質問はJavaに特有のもので、式は x == (x = y) これは、トリッキーな面接の質問のためによく作られる遠回しの非実用的な構成とは異なり、実際のプロジェクトで作られたものです。これは、比較と置換のイディオムを1行で置き換えるものでした。

int oldX = x;
x = y;
return oldX == y;

これは、x86のCMPXCHG命令よりもさらに単純であるため、Javaではより短い式に値する。

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

<ブロッククオート

のどちらを先に計算するかは、括弧で囲まれた順序で決まります。

括弧が計算や評価の順番に影響を与えるというのは、よくある誤解です。括弧は、式の各部を特定のツリーにまとめ、適切なオペランドを適切な操作に結びつけるだけです。

(また、演算子を使用しない場合、この情報は演算子の優先順位と連想性から得られますが、これは言語の構文木がどのように定義されているかの結果です。実際、括弧を使ってもこの仕組みは変わりませんが、ここでは簡略化して、優先順位の規則には一切頼らないとします)。

それが終わると(つまり、コードがプログラムにパースされると)、オペランドはまだ評価される必要があり、それがどのように行われるかについては別のルールがあります。

ただし、これはすべての言語で当てはまるわけではありません。たとえば、C++では、次のような短絡演算子を使わない限りは && または || オペランドの評価順序は一般に不特定であり、それに依存するべきではありません。

教師は、演算子の優先順位を説明するときに、quot; this makes the add happen first" のような誤解を招く言い方をするのをやめる必要があります。次のような式があるとします。 x * y + z 演算子の優先順位は、演算子と演算子の間の加算を行う。 x * yz の間ではなく yz というように、順番は一切書いていません。