Code Fix

言語間比較

== はなぜ言語によって「参照」と「値」のどちらを比較するのか

==(や is)で比較したのに、中身が同じはずの値がfalseになる——この種の間違いは、原因が「参照比較か値比較か」という1点に集約されるにもかかわらず、言語によって発生条件も直し方もばらばらです。5つの言語で同じ罠を横に並べます。

言語ごとの現れ方

Java: == と .equals() の違い(文字列比較)

 1  public class Main {
 2      public static void main(String[] args) {
 3          String a = new String("java");
 4          String b = new String("java");
 5          System.out.println(a == b      );
                                     ^
 6      }
 7  }
出力: false期待: true (コンパイルは通っています)

newで作った文字列同士は中身が同じでも==はfalseになります。文字列リテラル同士だけは定数プールの共有で偶然trueになるため、余計に誤解を招きます。

Javaの解説ページで詳しく見る →

Python: is と == の違い(小さい整数キャッシュで「たまたま動く」)

 1  a = int("1000")
 2  b = int("1000")
 3  print(a is     b)
               ^
出力: False期待: True (エラーにはなりません)

isは同一性、==は値の比較です。-5〜256の小さい整数はキャッシュされているため、本来isを使うべきでない場面でもisで「たまたま」正しく動いてしまいます。

Pythonの解説ページで詳しく見る →

C#: == が参照を比較してしまう理由

 1  class Point { public int X; public int Y; }
 2  class Program {
 3      static void Main(string[] args) {
 4          Point a = new Point { X = 1, Y = 2 };
 5          Point b = new Point { X = 1, Y = 2 };
                                   ^
 6          System.Console.WriteLine(a == b);
 7      }
 8  }
出力: False

classの==は既定で参照比較です。同じフィールド値を持つ2つのインスタンスもfalseになります(structやrecordは挙動が異なります)。

C#の解説ページで詳しく見る →

JavaScript: 同じ内容のオブジェクト同士が === でfalseになる理由

 1  const a = { id: 1 };
 2  const b = { id: 1 };
 3  console.log(a === b      );
                      ^
出力: false期待: true (エラーにはなりません)

オブジェクト・配列の==・===はどちらも参照比較です。中身のプロパティを比較するには自分でフィールドを取り出して比較する必要があります。

JavaScriptの解説ページで詳しく見る →

C言語: error: invalid operands to binary ==(構造体同士の==比較)

 1  #include <stdio.h>
 2  
 3  struct Point { int x, y; };
 4  
 5  int main(void) {
 6      struct Point a = {1, 2};
 7      struct Point b = {1, 2};
 8      if (a == b                        ) {
                           ^
 9          printf("same\n");
10      }
11      return 0;
12  }
main.c:8:11: error: invalid operands to binary == (have 'struct Point' and 'struct Point')

構造体には==自体が定義されておらず、コンパイルエラーになります。「比較できない」ことが最初から明示される点が、他の4言語(黙って参照を比較する)と対照的です。

C言語の解説ページで詳しく見る →

まとめ

共通しているのは「変数が指しているのは値そのものではなく、値の置き場所(参照)である」という一点です。プリミティブ型・小さい整数・文字列リテラルなど、言語ごとに用意された「例外的に値比較に見えるケース」に一度でも当たると、この誤解はかえって強化されます。迷ったら、その言語の「値そのものを比較する方法」(.equals() / == / 各フィールドの比較など)を必ず確認してください。

広告
広告スロット(未設定)