91061


Javaでは文字列をオブジェクトとして扱うため"=="で比較すると同じ文字列でも「同じオブジェクトではない」という理由で等しくないと判定されるため.equals()を使わなければいけない、ということは知ってるのですが、何らかの理由で.equals()ではなく"=="を使わなければいけない場面というのは存在するのでしょうか？  
Javaは現在"var"を導入するなど（簡略化する方向に）文法に大きく手を加えていますが、文字列を"=="でも正しく比較できるようにするということはやってないようです。  
何か.equals()と"=="を使い分けなければいけない場面があるからそれができないのでしょうか。それとも単にその必要がないと考えてるだけなのでしょうか。  
Javaの設計者でもない限りわからない問題かもしれませんがよろしくお願いします。


CC BY-SA 4.0
2022-09-12T06:29:52.327
91051
2022-09-12T10:58:02.070
816
question
java
Javaで文字列を"=="で比較する必要がある場面は存在するのでしょうか？


[c#](/questions/tagged/c%23 "'c#' のタグが付いた質問を表示") でいうと `String.Equals` と
`Object.ReferenceEquals` の差ですよね。

Q1. `String` に対して `==` を使わなければならない場面はあるか  
A1. そりゃもちろん、同じオブジェクトであるかの判定がしたい場合には `==` を使うことになります（実用的には極めてレアケースだと思う）

Q2. `==` の挙動が `equals()` になるような言語仕様の変更がありうるか  
A2. 既存のソースコードの挙動が変わるような言語仕様自体の変更は `BREAKING CHANGE` (破壊的変更)
と呼ばれますが、その言語のユーザー（まあ一般のプログラマのことですよね）はこれを好みませんし、言語仕様策定者も嫌がります（要するに別言語になるということだから）おそらく将来にわたってそんな変更は行われないでしょう。  
# 言語仕様自体の不具合があってそれを修正するための破壊的変更はあり得る話だけど、今のこの件はそうは思えない。

`var`
を新設するとかは既存のソースコードを新しいコンパイラでコンパイルしても挙動が変わらないので、そういう非破壊的変更は結構積極的に行われます（新しいソースコードを古いコンパイラで使うことはできないわけですが）


CC BY-SA 4.0
2022-09-12T07:30:15.353
91052
2022-09-12T07:30:15.353
8589
91051
answer


> 何らかの理由で.equals()ではなく"=="を使わなければいけない場面というのは存在するのでしょうか？

「.equals()ではなく"=="が必要とされる」状況は、まず存在しないと思います。Javaの仕様的には「文字列プール」に文字列が格納されているか否かの確認に、"=="比較が役立つ可能性はあります。詳細は[`String#intern()`メソッド](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#intern--)のリファレンスを参照ください。

一方、主に処理速度性能の観点から「.equals()ではなく"=="を使う利点がある」場面は存在します。例えばOpenJDKの[`String#equals()`メソッド内部実装](https://hg.openjdk.java.net/jdk10/jdk10/jdk/file/777356696811/src/java.base/share/classes/java/lang/String.java#l1014)では、まず最初に`this
== (比較対象)`を評価することで自己比較（または文字列プールに両者が格納済み）のケースで、1文字づつ比較するよりも高速な処理が行われます。

[code]

    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String aString = (String)anObject;
            // 1文字づつ比較する処理
        }
        return false;
    }
    
[/code]

* * *

> Javaは現在"var"を導入するなど文法に大きく手を加えていますが、文字列を"=="でも正しく比較できるようにするということはやってないようです。

Java言語仕様の破壊的変更については 774RR さんと同意見です。大量にある既存コード資産を破壊するリスクから「今更変えられない」に尽きると思います。


CC BY-SA 4.0
2022-09-12T08:36:03.130
91055
2022-09-12T08:36:03.130
49
91051
answer


> 何らかの理由で.equals()ではなく"=="を使わなければいけない場面というのは存在するのでしょうか？

パフォーマンス向上を目的として、文字列を
[`String#intern()`](https://docs.oracle.com/javase/jp/17/docs/api/java.base/java/lang/String.html#intern\(\))
して保持した上で比較に `==` を用いるようにする、という判断はあるかもしれません。  
次の議論を参照してみてください:

  * [Is it good practice to use java.lang.String.intern()? - Stack Overflow](https://stackoverflow.com/q/1091045/4506703)

> 何か.equals()と"=="を使い分けなければいけない場面があるからそれができないのでしょうか。

`==` の挙動は `String` の都合で決まっているわけではありません。つまり、使い分けなければいけないかどうかで `==` と `equals()`
の2つが存在するわけではありません。

`==` の挙動は [Java
言語仕様](https://docs.oracle.com/javase/specs/jls/se18/html/jls-15.html#jls-15.21.3)で定められたものです。  
それに対し、 `String#equals()` は [Java 標準ライブラリの API
仕様](https://docs.oracle.com/javase/jp/17/docs/api/java.base/java/lang/String.html#equals\(java.lang.Object\))で定められたもので、レイヤーが異なります。

`==` の仕様が先にあって、それで都合が悪いのであれば別の評価方法を実装する、という順序です。  
(そうして実装されているのが `String#equals()` ということです)

>
> Javaは現在"var"を導入するなど（簡略化する方向に）文法に大きく手を加えていますが、文字列を"=="でも正しく比較できるようにするということはやってないようです。

`==` 演算子で、あなたの言うところの"正しく"比較できるようにする、というのは [Project
Valhalla](https://openjdk.org/projects/valhalla/) の [`value`
クラス](https://openjdk.org/jeps/8277163)として検討されています。  
これによって `==` 演算子の役割が拡張され、特定の条件を満たすクラスを `value`
クラスとして作成することで"正し"い比較ができるようになろうかと思います。  
(ただし、 `String` クラスは条件を満たしていない(しそもそも `value` として定義されていない)ので `String` オブジェクトが
`==` で"正し"く評価できるようになるわけではないです。リンク先で例示されている `Substring`
のように、文字列に関するユーザー作成クラスには役立つこともあろうかと思いますが。)

> 単にその必要がないと考えてるだけなのでしょうか。

`==` は既に定義されているので置き換えることは無理ですが、 `var` のように新しいキーワード、例えば `===` 演算子を導入して
`equals()` のように振る舞う、とすることは可能でしょう。  
これが実現されてないのは、一言でいうとその通りで、必要がない、と考えられているからでしょう。


CC BY-SA 4.0
2022-09-12T10:58:02.070
91061
2022-09-12T10:58:02.070
2808
91051
answer