メソッドの実装を見ると、equals()
それは何もしません==
。だから私の質問は==
、同じ仕事をする演算子があるときにこれを別のメソッドとして持つ必要があったのですか?
8 に答える
演算子をオーバーロードすることはできませんが、演算子とは異なる動作をしたい場合、つまり参照を比較せずに実際にオブジェクトを比較したい場合==
はオーバーライドできます(たとえば、フィールドのすべてまたは一部を使用)。equals(Object)
==
また、オーバーライドする場合はequals(Object)
、も参照してくださいhashCode()
。equals(Object)
これらの2つのメソッドは互換性がある必要があります(つまり、同じである必要があるために等しい2つのオブジェクトhashCode()
)。そうでない場合、あらゆる種類の奇妙なエラーが発生します(たとえば、オブジェクトをセットまたはマップに追加する場合)。
==
オブジェクト参照を比較し、2つの参照が同じかどうかを尋ねます。
equals()
オブジェクトの内容を比較し、オブジェクトが同じ概念を表しているかどうかを尋ねます。
プリミティブの場合、オペレーターは 2 つの値が同じ==
かどうかをチェックします。
プリミティブでない場合は、オブジェクトの同じインスタンスを指す2 つのポインター (または参照)であるかどうかを確認します。
このメソッドは、 を使用して参照equals()
をチェックするカスタム チェックを実行します。しかし、他のクラスでは、オーバーライドされることがあります (これが正しい過去分詞かどうかはわかりません)。内容を確認する必要があります。Object
==
equals()
equals()
たとえば、次のようになります。
int i0 = 34;
int i1 = 34;
int i2 = 35;
// results
i0 == i1: true
i1 == i0: true
i2 == i0: false
しかし、非プリミティブがある場合
String str0 = new String("Hello man!");
String str1 = new String("Hello man!");
String str2 = new String("!nam olleH");
String str2copy = str2;
// Results
str0 == str1: false // Pointer to two different object, so == will give false
str1 == str2: false // Idem
str2 == str2copy: true // So this are two pointers to the same object
str0.equals(str1): true // This are not the same objects, but they are equal
str1 == str1: true // Again: two times a pointer to the same object
では、なぜ をstr0.equals(str1)
返すのtrue
でしょうか? String クラスには のオーバーライドがあるためですequals()
。そして、その方法では、実行によってそれらが等しいかどうかをチェックしませんreturn this == obj;
。しかし、その方法では、完全なチェックがあります。2 つの文字列を比較するためにどの方法を使用するかはわかりませんが、次の 2 つの方法が考えられます。
- 2 つの文字列からハッシュコードを生成し、それらが等しいかどうかを確認します (
int == int
) - それらが同じかどうか、文字ごとにチェックします。
だから私はこれが今明確であることを願っています.
両者には非常に重要な違いがあります。
「==」はオブジェクト インスタンスを比較します。デフォルトの equals() 実装もこれを行います。次のコード サンプルを実行して分析してください。
public class Person{
String name;
public Person(String name){
this.name = name;
}
//overriding equals
public boolean equals( Object obj ) {
if( this == obj )
return true;
if( obj == null )
return false;
if( getClass() != obj.getClass() )
return false;
Person other = (Person) obj;
if( name == null ) {
if( other.name != null )
return false;
} else if( !name.equals( other.name ) )
return false;
return true;
}
}
...
...
Person john1 = new Person("John");
Person john2 = new Person("John");
System.out.println("john1 == john2:" + (john1 == john2));
System.out.println("john1.equals(john2):" + john1.equals(john2));
ご覧のとおり、"==" は false を返します (オブジェクトは Person の 2 つの異なるインスタンスです)、equals は true を返します (2 つの Person が同じ名前を持つ場合は等しいと定義したため)。
== 演算子は、参照を比較するために使用されます。
equals() メソッドは、オブジェクト定義に対して定義されています。
Dog d =new Dog();
Collar c =new Collar("Red");
d.setCollar(c);
Dog d2=new Dog();
Collar c2=new Collar("Red");
d2.setCollar(c2);
d2.getCollar() ==d.getCollar()
2 匹の犬が 2 つの異なる首輪オブジェクト (アイテム) を持っていることを示す false を返します。同じ首輪を共有していません。
d2.getCollar().equals(d.getCollar())
首輪が [首輪の色が同じ場合、首輪も同じ] と定義されている場合は true を返します 。2 匹の犬の首輪の色は同じです。
class Collar{
String color="";
public Collar(String p0){
this.color=p0;
}
boolean equals(Object c){
Collar other=(Collar)c;
return this.color.equals(other.getColor());
}
public String getColor(){
return this.color;
}
}
これを可能にするために、次のようにします。
String s1 = new String("foo");
String s2 = new String("foo");
System.out.println(s1 == s2); // false?! Different references!
System.out.println(s1.equals(s2)); // true
のソースを確認すると、互いの内部文字配列 (実際の値)を比較するためString#equals()
に が適切にオーバーライドされていることがわかります。他の多くのクラスでも、このメソッドがオーバーライドされています。Object#equals()
オペランドがプリミティブ データ型の場合、java の equals operator(==) は 2 つの変数のデータに対して動作します。ただし、オペランドがオブジェクトの場合、Java は参照を使用してそれらを比較します。これは、オブジェクトのどのフィールドを比較するかを判断する方法がないためです。
Java は演算子のオーバーライドをサポートしていないため、Java では equals 演算子 (==) をオーバーライドできないため、ユーザー定義フィールドに基づいて比較する方法は 1 つしかなく、equals() メソッドをオーバーライドすることによってオブジェクトで定義されます。
たとえば、名前に基づいて Employee を比較する場合は、以下のように Employee クラスの equals メソッドをオーバーライドしてロジックを定義する必要があります。
public class Employee {
private Integer id;
private String name;
@Override
public boolean equals(Object obj) {
Employee other = (Employee) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
"string"=="string"はfalseを返します"string".equals( "string")はtrueを返します
o1 == o2を使用すると、オブジェクト1がo2と同じオブジェクトであると比較します(参照による)
o1.equals(o2)を使用すると、オブジェクトに応じて、equalsメソッドがオーバーライドされ、「return o1==o2」のようなものでは実装されません。
たとえば、2つのセットインスタンスを作成します。これらの2つのセットオブジェクトは2つの異なるオブジェクトであり、それらのいずれかに異なる要素を追加できます。set1 == set2は常にfalseを返しますが、set2にset1 ...とまったく同じ要素が含まれている場合、set1.equals(set2)は最終的にtrueを返します。これは、setクラスでequalsメソッドがオーバーライドされるためです。
SetのEquals実装は次のとおりです。
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Set))
return false;
Set s = (Set) o;
if (s.size() != c.size())
return false;
return containsAll(s); // Invokes safe containsAll() above
}