[Apex] 文字列の比較における「==」と「equals」の違い


TL;DR

英数字以外の文字が含まれる文字列の比較にはStringクラスのequalsを使いましょう。

「==」はロケールによって結果が違います。
ロケールが日本語でも、結果が感覚とは異なる場合があります。
(例えば、「あいうえお」と「ぁぃぅぇぉ」は等価なのに対し、「アイウエオ」と「アイウエオ」は等価でない。)

「==」と「equals」の違い

大文字小文字の区別

「==」は大文字小文字などの区別がありません。
「equals」は完全におなじ文字かどうかで判定されます。
大文字小文字の違いだけを無視したい場合は「equalsIgnoreCase」を使うことができます。

nullのあつかい

「==」は文字列がnullであっても使用できます。
「equals」はインスタンスメソッドであるため、インスタンスがnullだとNullPointerExceptionとなります。

ロケールによる違い

「==」はロケールによって結果が変わります。
「equals」は変わりません。
このため、英数字以外の文字列を含む可能性がある場合、equalsを使うべきです。

実際の比較

「==」を使用した場合、英字の大文字小文字以外にも、区別されない文字種があることがわかります。

日本語のロケール下での実行結果
System.debug('ABC' == 'abc'); // true ←注意!!
System.debug('ABC' == 'ABC'); // 半角と全角 true ←注意!!
System.debug('ABC' == 'abc'); // 半角と全角 true ←注意!!
System.debug('あいうえお' == 'アイウエオ'); // true ←注意!!
System.debug('あいうえお' == 'ぁぃぅぇぉ'); // true ←注意!!
System.debug('アイウエオ' == 'アイウエオ'); // false

System.debug('ABC'.equals('abc')); // false
System.debug('ABC'.equals('ABC')); // 半角と全角 false
System.debug('ABC'.equals('abc')); // 半角と全角 false
System.debug('あいうえお'.equals('アイウエオ')); // false
System.debug('あいうえお'.equals('ぁぃぅぇぉ')); // false
System.debug('アイウエオ'.equals('アイウエオ')); // false

System.debug('ABC'.equalsIgnoreCase('abc')); // true
System.debug('A'.equalsIgnoreCase('Å')); // false
System.debug('ABC'.equalsIgnoreCase('ABC')); // 半角と全角 false
System.debug('ABC'.equalsIgnoreCase('abc')); // 半角と全角 false
System.debug('あいうえお'.equalsIgnoreCase('アイウエオ')); // false
System.debug('あいうえお'.equalsIgnoreCase('ぁぃぅぇぉ')); // false
System.debug('アイウエオ'.equalsIgnoreCase('アイウエオ')); // false

「==」のロケールによる違い

「==」の結果はコンテキストユーザのロケールの設定によって異なります。

// ロケールが日本語の場合
System.debug('ABC' == 'abc'); // true
System.debug('ABC' == 'ABC'); // 半角と全角 ★true
System.debug('ABC' == 'abc'); // 半角と全角 ★true
System.debug('あいうえお' == 'アイウエオ'); // ★true
System.debug('あいうえお' == 'ぁぃぅぇぉ'); // ★true
System.debug('アイウエオ' == 'アイウエオ'); // false

// ロケールが英語(アメリカ合衆国)の場合
System.debug('ABC' == 'abc'); // true
System.debug('ABC' == 'ABC'); // 半角と全角 ★false
System.debug('ABC' == 'abc'); // 半角と全角 ★false
System.debug('あいうえお' == 'アイウエオ'); // ★false
System.debug('あいうえお' == 'ぁぃぅぇぉ'); // ★false
System.debug('アイウエオ' == 'アイウエオ'); // false

ロケールはユーザの設定画面から変更が可能です。

参考

  • 「Java とは異なり、Apex の == はユーザ定義の型を除き、参照が同等であるかではなく、オブジェクト値が同等であるかを比較します。」「Apex は SOQL 比較セマンティックを使用するため、String の結果はコンテキストユーザのロケールに従って照合され、大文字と小文字は区別されません。」(式の演算 | Apex開発者ガイド)
  • 「渡された文字列が null ではなく、現在の文字列と同じバイナリ文字シーケンスを表す場合、true を返します。」(Stringクラス | Apex開発者ガイド)