Java における equals() と == の違いと使い方

Java における equals() と == の違いと使い方

Java 開発において、一見単純な質問ですが、インターネット上には多くのトピックや質問があります。それは、equals() 演算子と == 演算子の違いは何ですか?

  • ==: 演算子は、2 つのオブジェクトのアドレスが等しいかどうかを比較するために使用されます。
  • equals(): メソッドは、2つのオブジェクトの内容が等しいかどうかを比較するために使用されます。

本日のコンテンツ紹介は約9分です

写真

違いをよりよく理解するために、例を見てみましょう。

 String str1 = new String("Hello"); String str2 = new String("Hello"); System.out.println(str1.equals(str2)); // 输出true System.out.println(str1 == str2); // 输出false

この例では、2 つの文字列の内容は同じですが、メモリ内のアドレスは異なります。したがって、.equals() メソッドを使用して内容を比較すると true が返されますが、"==" 演算子を使用してアドレスを比較すると false が返されます。

1. .equals() メソッドをオーバーライドする

Java の基礎を学んだことがあるなら、すべての Java クラスがデフォルトで Object クラスを継承し、Object クラスに .equals() メソッドがあることを知っているはずです。

 public boolean equals(Object obj) { return (this == obj); }

コードから、.equals() メソッドはデフォルトで比較に == 演算子を使用していることがわかります。サブクラスが equals() メソッドをオーバーライドしない場合、== 演算子を使用すると、equals() メソッドと同じ結果になります。これは、2 つのオブジェクトのメモリ アドレスが等しいかどうかを比較するために使用されます。

しかし、現実には、多くのクラスがequals()メソッドをオーバーライドしています。これは、メモリアドレスの比較要件が比較的厳しく、実際にはすべてのシナリオのニーズを満たしていないためです。たとえば、Stringクラスを比較する場合、ほとんどの人はコンテンツが等しいかどうかのみを判断したいだけで、メモリアドレスが等しいかどうか(オブジェクトであるかどうか)を実際に知りたいわけではありません。

また、「Java文字列定数プールの詳細な理解」の記事では、Java仮想マシンがメモリオーバーヘッドを削減し、パフォーマンスを向上させるために文字列用のスペースを特別に割り当てることがすでにわかっています - 文字列定数プール

つまり、new はヒープ上に新しいスペースを必要とするため、new キーワードを使用する代わりに、String s = "Hello" の形式を使用して文字列オブジェクトを作成することをお勧めします。

1.1. Stringクラスのequals()メソッド

Jdk11のStringクラスのequals()メソッド

public boolean equals(Object anObject) { //如果是同一个对象(即两个引用指向内存中的同一块地址),则直接返回true if (this == anObject) { return true; } //如果是String类型的实例if (anObject instanceof String) { //Object类型的对象强制转换为String类型String aString = (String)anObject; //如果当前字符串对象和传入的字符串对象的编码方式相同if (coder() == aString.coder()) { //如果当前字符串和传入的字符串都是Latin1编码,则调用StringLatin1类的equals方法进行比较;如果其中一个或两个字符串是UTF16编码,则调用StringUTF16类的equals方法进行比较return isLatin1() ? StringLatin1.equals(value, aString.value) : StringUTF16.equals(value, aString.value); } } return false; }

特記事項: Latin1 (ISO 8859-1 とも呼ばれる) と UTF-16 (Unicode Transformation Format 16 ビット) は、2 つの異なる文字エンコード方式です。

Latin1 と UTF-16 は 2 つのエンコード方式ですが、違いは大きくありません。UTF-16 の equals() メソッドを例に挙げてみましょう。

 @HotSpotIntrinsicCandidate public static boolean equals(byte[] value, byte[] other) { if (value.length == other.length) { int len = value.length >> 1; for (int i = 0; i < len; i++) { if (getChar(value, i) != getChar(other, i)) { return false; } } return true; } return false; }

注: Java 8とJava 11のequals()メソッドのソースコードは異なります。JDK8のequals()メソッド

public boolean equals(Object anObject) { // 如果是同一个对象(即两个引用指向内存中的同一块地址),则直接返回true if (this == anObject) { return true; } // 如果是String类型的实例if (anObject instanceof String) { ////Object类型的对象强制转换为String类型String anotherString = (String)anObject; int n = value.length; // 如果字符串长度相等if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; // 判断每个字符是否相等while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }

1.2. 例の説明

例1:

 new String("hello").equals("hello")

出力は何ですか?

String クラスの equals メソッドは、文字列オブジェクトの内容が等しいかどうかを比較します。両方とも "Hello" なので、結果は true になります。

例2:

 new String("hello") == "hello";

出力は何ですか?

== 演算子は、オブジェクトのアドレスが等しいかどうかを比較します。== の左側はヒープ内に作成されたオブジェクトで、右側は文字列定数プール オブジェクトです。内容は等しいですが、アドレスが等しくないため、結果は false になります。

例3:

 new String("hello") == new String("hello");

出力は何ですか?

新しいオブジェクトは完全に異なるメモリアドレスを持つ必要があるため、結果は偽になります。

例4:

 "hello" == "h"+"ello"

出力は何ですか?

hとelloは両方とも文字列定数プールにあるので、コンパイラは+演算子に遭遇すると自動的にhelloに最適化し、結果はtrueになります。

例5:

 new String("hello").intern() == "hello"

出力は何ですか?

new String("hello") が実行されると、まず文字列定数プールにオブジェクトが作成され、次にヒープにオブジェクトが作成されます。 intern() メソッドが実行されると、文字列定数プールにオブジェクト 'hello' がすでに存在することが判明するため、文字列定数プールのオブジェクト参照が直接返され、文字列定数プールの 'hello' と比較されるため、結果は true になります。

String.intern()の詳細な分析では、すでにその理由を紹介しました。

2. 他の方法との比較

.equals() メソッドと "==" 演算子に加えて、使用できる他の比較メソッドがいくつかあります。

  • 1.Objects.equals() メソッド: この静的メソッドを使用すると、呼び出す前にオブジェクトが空かどうかを判断する必要なく、2 つのオブジェクトが等しいかどうかを比較できます。
 Objects.equals("Hello", new String("Hello")); // 返回true
  • 2. String クラスの .contentEquals() メソッド: このメソッドは、文字列が任意の文字シーケンス (StringBuffer、StringBuilder、String、CharSequence など) と等しいかどうかを比較するために使用できます。
 String str = "Hello"; StringBuffer buffer = new StringBuffer("Hello"); System.out.println(str.contentEquals(buffer)); // 输出true

<<:  世界最強のモデル クロード3号が物理・化学を覆す!博士課程の1年間の実験の結果が2時間で解読され、ネットユーザーは「科学的研究はもう存在しない」と叫んだ。

>>:  Claude3はマイクロソフトとOpenAIに警鐘を鳴らした

ブログ    
ブログ    
ブログ    
ブログ    

推薦する

15分 = 1年!人工知能と材料科学が出会うとき...

最近、NPJ—Computational Materials誌に研究論文が掲載されました。この論文は...

ビジネスにおける人工知能のリスクと限界

ビジネスにおいては、人工知能のリスクと限界を考慮する必要があります。 AI のリスクと限界には、プラ...

ルカンのリーダーシップの下、自己監督に賭けるMeta AI

自己教師学習は本当に AGI への重要なステップなのでしょうか? Metaの主任AI科学者であるヤン...

AIを活用することで大型機種の消費電力を節約できるのか? ? ?

この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...

人工知能の出現は教育にどのような影響を与えるのでしょうか?

近年、科学技術における人工知能の急速な発展により、人工知能は私たちの日常生活にいくつかの新たなハイラ...

AIが高度な数学の核心を突破、微分方程式と不定積分を1秒以内に解き、その性能はMatlabをはるかに上回る

この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...

トランスワープテクノロジーの孫元浩氏が「中国の人工知能起業家30人」の一人に選出

2020 年は特別な年であり、World Innovators Meet (WIM) の 6 年目と...

LianjiaのFeng Yang氏:不動産業界でデータと機械学習が輝く

[51CTO.comより引用] 2017年12月1日~2日、51CTO主催のWOTDグローバルソフト...

AIの奇妙な使い方:マクドナルドはゴミ箱の監視にAIを活用

この記事は公開アカウント「Reading Core Technique」(ID: AI_Discov...

7,346 人が参加したアルゴリズム コンテストは JD.com に何をもたらしたのでしょうか?

[51CTO.comより引用] 今年3月中旬、JD.comとIntelが共同主催するJDataアル...

ML コミュニティにおける 8 つの主要な「癌」: 盲目的崇拝、相互批判、SOTA の重視と有効性の軽視...

諺にあるように、人がいるところには川や湖があり、さまざまな立場や利害の争いがあるものです。科学研究の...

Alibaba DAMO Academyの従業員が空き時間に「紙の知識グラフ」を作成: 非常に高速な検索と完全な視覚化

この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...

AISpeechは多角的な視点からAIエコロジカルバリアを構築し、AIチップはラストマイルを切り開く

最近、シビチェンがチップスを製造しているというニュースが大きな騒ぎを引き起こしました。 [[2547...

AgentGPT: ブラウザ上の自律型 AI エージェント

翻訳者 |ブガッティレビュー | Chonglou AgentGPT Web は、ユーザーがカスタマ...

トップレベルの人工知能チームを構築するにはどうすればよいでしょうか?

市場には優れた AI ソフトウェア ツールが数多く存在しますが、プロジェクトを実装する際には強力なチ...