🐷

Java if文の条件式で==ではなくて=使っているのにコンパイルエラーにならない

2023/04/30に公開

問題

Oracle Certified Java Programmer, Bronze SE 認定資格対策で
Javaの文法普段書かないから挙動分からないなっていう問題あったので解説します。
下記のTest1.javaをコンパイル・実行した結果はどうなるでしょうか?
シンプルながら間違えやすい問題だと思います。

Test1.java
class Test1 {
  public static void main(String[] args) {
    boolean b = true;
    if (b = false)
      System.out.println(b);
      System.out.println(b);
  }
}

解説

1つ目の落とし穴

まず、if文の条件式に比較演算子==ではなくて、代入演算子=が使われています。

なので、コンパイルエラーになるかと思いきや、実はエラーは発生しません。
なぜなら、if文の条件式がboolean型であれば代入演算子を使ってもよいからです。

if (b = false) // bにfalseを代入してfalseを返す

このようにすると、bはboolean型なので、if文の条件式もboolean型になります。
b = falseは代入演算子で、bにfalseを代入してfalseを返します。

2つ目の落とし穴

if文の条件式がfalseを返すから、if文中の命令文は何も実行されず、
何も出力しないように思われます。
しかし、ここでも注意すべき落とし穴があります。

よく見ると、if文に波括弧{}がありません。
では、コンパイルエラーになるかといえば、そうはなりません。
波括弧{}がない場合、if文は次の一行だけを実行します。

Test1.javaの4~6行目
if (b = false)
  System.out.println(b); // この行だけがif文に属す
  System.out.println(b); // この行は常に実行される

そのため、最初のSystem.out.println(b)は実行されず、
次のSystem.out.println(b)は常に実行されます。
つまり、Test1.javaと以下のTest3.javaは同じ内容を記述したコードになります。

Test3.java
class Test3 {
  public static void main(String[] args) {
    boolean b = true;
    if (b = false) {
      System.out.println(b);
    }
      System.out.println(b);
  }
}

結局、if文は実行されず、bが出力されます。
bは宣言された時にはtrueでしたが、bにはfalseが代入されたので、
問題の解答はfalseになります。

余談

整数の代入は許されるのか?

整数の代入は、boolean型ではないので、コンパイルエラーになります。

Test2.java
class Test2 {
  public static void main(String[] args) {
    int a = 1;
    if (a = 2)
      System.out.println(a);
      System.out.println(a);
  }
}

if文の条件式(a = 2)がint型になりますが、if文の条件式はboolean型でなければなりません。
コンパイラは、

incompatible types: int cannot be converted to boolean

というエラーメッセージを出します。

boolean型のif文の条件式に=はあまり使わない方がいいよって話

boolean型ならば代入演算子=を使えますが、
これは意図しない動作を引き起こす可能性があります。
なので代入演算子=ではなく、比較演算子==を使うべきです。

if (b == false) // bとfalseを比較して結果を返す

このようにすると、bの値を変えずに、比較できます。
ちなみに、以下のように書いても同じ意味です。

if (!b) // bとfalseを比較して結果を返す

むしろ、こちらの書き方の方が自然かもしれません。

参考文献

https://coderanch.com/t/366734/java/assignment-operator-statement
https://stackoverflow.com/questions/2393988/getting-confused-with-and-in-if-statement
https://wiki.sei.cmu.edu/confluence/display/java/EXP51-J.+Do+not+perform+assignments+in+conditional+expressions

Discussion