나는 이것을 올바르게 이해하는지 분명히하고 싶었습니다.
==
참조 비교입니다. 즉, 두 객체가 모두 동일한 메모리 위치를 가리 킵니다..equals()
객체의 값 비교로 평가
.equals()
것으로 생각할 수 있습니다
나는 이것을 올바르게 이해하는지 분명히하고 싶었습니다.
==
참조 비교입니다. 즉, 두 객체가 모두 동일한 메모리 위치를 가리 킵니다..equals()
객체의 값 비교로 평가.equals()
것으로 생각할 수 있습니다
답변:
일반적으로 질문에 대한 대답은 "예"이지만 ...
.equals(...)
비교 대상으로 작성된 내용 만 비교합니다.equals(Object o)
으로이 메서드를 재정의 한 가장 가까운 부모 클래스의 메서드가 사용됩니다.Object#equals(Object o)
. Object API에 따라 이것은 ==
; 즉, 두 변수가 동일한 객체를 참조하고 참조가 하나이고 동일한 경우에만 true를 반환합니다 . 따라서 기능 평등이 아닌 객체 평등을 테스트합니다 .hashCode
경우 항상 재정의 해야합니다 equals
. API에 따라 hashCode()
두 객체 의 메소드 에서 반환 된 결과는 메소드 가 동일한 것으로 표시되는 경우 동일 해야합니다equals
. 대화가 반드시 사실 은 아닙니다 .==
메모리 참조를 확인 하면 [this] [1] [1] : docs.google.com/document/d/… 에서 이상한 동작이 발생하는 이유는 무엇입니까? 출력이 true라고 예상했습니다. 혼란을
The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).
<br/> Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
( docs.oracle.com/javase/7/docs/api/java/lang/… )
String 클래스와 관련하여 :
equals () 메소드 는 두 객체 참조가 동일한 String 인스턴스를 참조하는지 여부에 관계없이 String 인스턴스 (힙의) 내 "값"을 비교합니다. String 유형의 두 객체 참조가 동일한 String 인스턴스를 참조하면 훌륭합니다! 두 객체 참조가 두 개의 다른 String 인스턴스를 참조하는 경우 차이가 없습니다. 비교되는 각 String 인스턴스 내의 "값"(즉, 문자 배열의 내용)입니다.
반면에 "==" 연산자 는 두 객체 참조 의 값을 비교 하여 동일한 String 인스턴스 를 참조하는지 여부를 확인합니다 . 두 객체 참조의 값이 동일한 String 인스턴스를 "참조"하는 경우 부울 식의 결과는 "true"입니다 ..duh. 반면에 두 객체 참조의 값이 서로 다른 String 인스턴스 를 "참조"하는 경우 (두 String 인스턴스가 동일한 "값"을 갖더라도 (즉, 각 String 인스턴스의 문자 배열의 내용이 동일하더라도) 부울 식의 결과는 "false"입니다.
다른 설명과 마찬가지로 들어가게하십시오.
나는 이것이 약간의 문제를 해결하기를 바랍니다.
String
s의 경우 ==
참조도 같습니다. 그렇지만 Java가 s를 처리하는 방식 때문에 일반적으로 작동합니다 ( String
동일한 내용을 가진 두 개의 s 에서 일반적 으로 ==
서로 같은 것입니다) String
. 항상 그런 것은 아니며 실제로 나쁜 습관이지만, 특히 다른 언어를 사용하는 사람들이 흔히 저지르는 실수입니다.
String
문자열 리터럴에서 빌드가 호출 뭔가에 추가됩니다 String constant pool
, 예를 들어, String s1 = "someString"; String s2 = "someString;"
두 s1
& s2
동일한 참조를 공유합니다. s1 == s2
true를 반환합니다. 그러나 String constructor
예 String s1 = new String("someString"); String s2 = new String("someString");
를 들어을 통해 구성된 경우 동일한 참조를 공유하지 않습니다. s1 == s2
거짓을 반환합니다.
"primitives"또는 "Object Types"에 대해 이야기하고 있는지에 따라 약간의 차이가 있습니다. "정적"또는 "비 정적"멤버에 대해 이야기하는 경우에도 마찬가지입니다. 위의 모든 내용을 혼합 할 수도 있습니다 ...
다음은 예제입니다 (실행할 수 있음).
public final class MyEqualityTest
{
public static void main( String args[] )
{
String s1 = new String( "Test" );
String s2 = new String( "Test" );
System.out.println( "\n1 - PRIMITIVES ");
System.out.println( s1 == s2 ); // false
System.out.println( s1.equals( s2 )); // true
A a1 = new A();
A a2 = new A();
System.out.println( "\n2 - OBJECT TYPES / STATIC VARIABLE" );
System.out.println( a1 == a2 ); // false
System.out.println( a1.s == a2.s ); // true
System.out.println( a1.s.equals( a2.s ) ); // true
B b1 = new B();
B b2 = new B();
System.out.println( "\n3 - OBJECT TYPES / NON-STATIC VARIABLE" );
System.out.println( b1 == b2 ); // false
System.out.println( b1.getS() == b2.getS() ); // false
System.out.println( b1.getS().equals( b2.getS() ) ); // true
}
}
final class A
{
// static
public static String s;
A()
{
this.s = new String( "aTest" );
}
}
final class B
{
private String s;
B()
{
this.s = new String( "aTest" );
}
public String getS()
{
return s;
}
}
다음 링크를 통해 "=="(Equal Operator) 및 ".equals (...)"(java.lang.Object 클래스의 메소드)에 대한 설명을 비교할 수 있습니다.
==와 equals의 차이점은 좀 더 자세히 살펴보기로 결정하기 전까지는 혼란 스러웠습니다. 그들 중 많은 사람들이 문자열을 비교하기 위해서는 사용 equals
하지 말아야한다고 말합니다 ==
. 이 대답에서 희망이 차이를 말할 수 있습니다.
이 질문에 대답하는 가장 좋은 방법은 몇 가지 질문을하는 것입니다. 시작하겠습니다 :
아래 프로그램의 출력은 무엇입니까?
String mango = "mango";
String mango2 = "mango";
System.out.println(mango != mango2);
System.out.println(mango == mango2);
당신이 말하는 경우,
false
true
나는 당신이 옳다고 말할 것이지만 왜 그렇게 말했 습니까? 그리고 출력이
true
false
나는 당신이 틀렸다고 말할 것입니다. 그러나 여전히 당신에게 물어볼 것입니다. 왜 당신이 옳다고 생각합니까?
좋아, 이것에 대답 해 보자.
아래 프로그램의 출력은 무엇입니까?
String mango = "mango";
String mango3 = new String("mango");
System.out.println(mango != mango3);
System.out.println(mango == mango3);
지금 말하면
false
true
나는 당신이 틀렸다고 말하지만 왜 지금은 틀린가 ? 이 프로그램의 올바른 출력은
true
false
위의 프로그램을 비교하고 생각하십시오.
확인. 이제 이것이 도움이 될 수 있습니다 (이 글을 읽으십시오 : 객체의 주소를 인쇄하십시오 -불가능하지만 여전히 사용할 수 있습니다).
String mango = "mango";
String mango2 = "mango";
String mango3 = new String("mango");
System.out.println(mango != mango2);
System.out.println(mango == mango2);
System.out.println(mango3 != mango2);
System.out.println(mango3 == mango2);
// mango2 = "mang";
System.out.println(mango+" "+ mango2);
System.out.println(mango != mango2);
System.out.println(mango == mango2);
System.out.println(System.identityHashCode(mango));
System.out.println(System.identityHashCode(mango2));
System.out.println(System.identityHashCode(mango3));
날이 밖으로 인쇄 ideone 위해 (: 당신은 위의 코드에서 마지막 세 줄의 출력에 대해 생각하는 시도 할 수 있습니다 당신은 여기에 코드를 확인하실 수 있습니다 )
false
true
true
false
mango mango
false
true
17225372
17225372
5433634
오! 이제 identityHashCode (mango)는 identityHashCode (mango2)와 같지만 identityHashCode (mango3)와 같지 않습니다.
모든 문자열 변수 (mango, mango2 및 mango3) 는 "mango"인 동일한 값을 갖지만 identityHashCode()
여전히 모두 동일하지는 않습니다.
이제이 줄의 주석을 해제 // mango2 = "mang";
하고 이번에 다시 실행하여 세 가지 identityHashCode()
가 모두 다른 것을 볼 수 있습니다. 흠 그것은 유용한 힌트입니다
우리는 if hashcode(x)=N
and hashcode(y)=N
=>x is equal to y
Java가 내부적으로 어떻게 작동하는지 잘 모르겠지만 이것이 내가 말했을 때 일어난 일이라고 가정합니다.
mango = "mango";
자바 "mango"
는 mango
다음과 같은 변수에 의해 지적 된 문자열 을 만들었습니다.
mango ----> "mango"
이제 내가 말했을 때 다음 줄에서 :
mango2 = "mango";
실제로 다음과 같은 문자열 "mango"
을 재사용 했습니다.
mango ----> "mango" <---- mango2
망고와 망고 2 모두 같은 참조를 가리키고 있습니다.
mango3 = new String("mango")
실제로 "망고"에 대한 완전히 새로운 참조 (문자열)를 만들었습니다. 이런 식으로 보입니다
mango -----> "mango" <------ mango2
mango3 ------> "mango"
그래서 내가에 대한 값을 mango == mango2
낼 때을 내 보냅니다 true
. 에 대한 값을 mango3 == mango2
넣을 때 false
(값이 같더라도) 나타납니다.
그리고 주석을 해제 할 때 // mango2 = "mang";
실제로 "mang"라는 문자열을 생성하여 그래프를 다음과 같이 설정했습니다.
mango ---->"mango"
mango2 ----> "mang"
mango3 -----> "mango"
이것이 identityHashCode가 모두 동일하지 않은 이유입니다.
이것이 여러분에게 도움이되기를 바랍니다. 실제로 == 실패하고 equals ()가 통과하는 테스트 사례를 생성하고 싶었습니다. 내가 틀렸다면 의견을 말하고 알려주십시오.
mango == mango2
만들지 mango2
않고 직접 참조 했기 때문에 발생 합니까 "mango"
?
==의 두 변수 여부 운영자가 테스트는 (메모리 어드레스 포인터 일명) 동일한 참조 .
String foo = new String("abc");
String bar = new String("abc");
if(foo==bar)
// False (The objects are not the same)
bar = foo;
if(foo==bar)
// True (Now the objects are the same)
반면 등호 () 메소드 테스트 두 변수가있는 개체 참조 여부 동일한 상태 (값) .
String foo = new String("abc");
String bar = new String("abc");
if(foo.equals(bar))
// True (The objects are identical but not same)
건배 :-)
String w1 ="Sarat";
String w2 ="Sarat";
String w3 = new String("Sarat");
System.out.println(w1.hashCode()); //3254818
System.out.println(w2.hashCode()); //3254818
System.out.println(w3.hashCode()); //3254818
System.out.println(System.identityHashCode(w1)); //prints 705927765
System.out.println(System.identityHashCode(w2)); //prints 705927765
System.out.println(System.identityHashCode(w3)); //prints 366712642
if(w1==w2) // (705927765==705927765)
{
System.out.println("true");
}
else
{
System.out.println("false");
}
//prints true
if(w2==w3) // (705927765==366712642)
{
System.out.println("true");
}
else
{
System.out.println("false");
}
//prints false
if(w2.equals(w3)) // (Content of 705927765== Content of 366712642)
{
System.out.println("true");
}
else
{
System.out.println("false");
}
//prints true
.equals(...)
비교하려는 클래스에서 구현 해야한다는 것을 기억하십시오 . 그렇지 않으면 아무 의미가 없습니다. Object 클래스의 메소드 버전은 비교 작업과 동일한 작업을 수행합니다. Object # equals .
실제로 객체에 비교 연산자를 사용하려는 유일한 경우는 Enum을 비교하는 것입니다. 한 번에 하나의 Enum 값 인스턴스 만 있기 때문입니다. 예를 들어 열거 형이 주어지면
enum FooEnum {A, B, C}
한 번에 둘 이상의 인스턴스를 가질 수 없으며 A
for B
및 C
. 이것은 실제로 다음과 같은 메소드를 작성할 수 있음을 의미합니다.
public boolean compareFoos(FooEnum x, FooEnum y)
{
return (x == y);
}
그리고 당신은 어떤 문제도 없을 것입니다.
코드를 평가할 때 (==)는 메모리 주소에 따라 비교되는 반면 equals (Object o)는 인스턴스의 hashCode ()를 비교합니다. 그렇기 때문에 나중에 놀라움에 직면하지 않으면 equals ()와 hashCode () 사이의 계약을 위반하지 마십시오.
String s1 = new String("Ali");
String s2 = new String("Veli");
String s3 = new String("Ali");
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
System.out.println(s3.hashCode());
System.out.println("(s1==s2):" + (s1 == s2));
System.out.println("(s1==s3):" + (s1 == s3));
System.out.println("s1.equals(s2):" + (s1.equals(s2)));
System.out.println("s1.equal(s3):" + (s1.equals(s3)));
/*Output
96670
3615852
96670
(s1==s2):false
(s1==s3):false
s1.equals(s2):false
s1.equal(s3):true
*/
여기에서의 차이점에 대한 일반적인 규칙의 손가락이다 relational operator ==
하고 the method .equals()
.
object1 == object2
object1 및 object2가 참조하는 오브젝트 가 힙의 동일한 메모리 위치를 참조하는지 비교합니다 .
object1.equals(object2)
메모리의 위치에 관계없이 object1 및 object2의 값을 비교 합니다 .
이것은 String을 사용하여 잘 설명 할 수 있습니다
시나리오 1
public class Conditionals {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = new String("Hello");
System.out.println("is str1 == str2 ? " + (str1 == str2 ));
System.out.println("is str1.equals(str2) ? " + (str1.equals(str2 )));
}
}
The result is
is str1 == str2 ? false
is str1.equals(str2) ? true
시나리오 2
public class Conditionals {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = "Hello";
System.out.println("is str1 == str2 ? " + (str1 == str2 ));
System.out.println("is str1.equals(str2) ? " + (str1.equals(str2 )));
}
}
The result is
is str1 == str2 ? true
is str1.equals(str2) ? true
이 문자열 비교는 다른 유형의 객체를 비교하기위한 기초로 사용될 수 있습니다.
예를 들어 Person 클래스 가 있는 경우 두 사람을 비교할 기준 을 정의해야합니다 . 이 개인 클래스에는 키와 몸무게의 인스턴스 변수 .
따라서 person 객체를 만들고 person1 and person2
이것을 사용 하여이 두 객체 를 비교 하려면 person 클래스.equals()
의 equals 메소드 를 재정의해야합니다. 인스턴스 변수 (heigh 또는 weight)를 기반으로 정의해야합니다.
그러나 == operator will still return results based on the memory location of the two objects(person1 and person2)
.
이 사람 객체 비교를 일반화하기 위해 다음 테스트 클래스를 만들었습니다. 이러한 개념을 실험하면 수많은 사실이 드러날 것 입니다.
package com.tadtab.CS5044;
public class Person {
private double height;
private double weight;
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(height);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
/**
* This method uses the height as a means of comparing person objects.
* NOTE: weight is not part of the comparison criteria
*/
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 (Double.doubleToLongBits(height) != Double.doubleToLongBits(other.height))
return false;
return true;
}
public static void main(String[] args) {
Person person1 = new Person();
person1.setHeight(5.50);
person1.setWeight(140.00);
Person person2 = new Person();
person2.setHeight(5.70);
person2.setWeight(160.00);
Person person3 = new Person();
person3 = person2;
Person person4 = new Person();
person4.setHeight(5.70);
Person person5 = new Person();
person5.setWeight(160.00);
System.out.println("is person1 == person2 ? " + (person1 == person2)); // false;
System.out.println("is person2 == person3 ? " + (person2 == person3)); // true
//this is because perosn3 and person to refer to the one person object in memory. They are aliases;
System.out.println("is person2.equals(person3) ? " + (person2.equals(person3))); // true;
System.out.println("is person2.equals(person4) ? " + (person2.equals(person4))); // true;
// even if the person2 and person5 have the same weight, they are not equal.
// it is because their height is different
System.out.println("is person2.equals(person4) ? " + (person2.equals(person5))); // false;
}
}
이 클래스 실행 결과는 다음과 같습니다.
is person1 == person2 ? false
is person2 == person3 ? true
is person2.equals(person3) ? true
is person2.equals(person4) ? true
is person2.equals(person4) ? false
== 연산자 항상 참조가 비교됩니다. 그러나
equals () 메소드
재정의 된 메소드에 주어진 구현의 기본에 대한 객체를 비교하는 것보다 메소드가 재정의 된 경우 구현에 달려 있습니다.
class A
{
int id;
String str;
public A(int id,String str)
{
this.id=id;
this.str=str;
}
public static void main(String arg[])
{
A obj=new A(101,"sam");
A obj1=new A(101,"sam");
obj.equals(obj1)//fasle
obj==obj1 // fasle
}
}
위의 코드에서 obj와 obj1 객체는 동일한 데이터를 포함하지만 참조는 동일하지 않으므로 return false 및 ==와 같습니다. 그러나 우리가 equals보다
class A
{
int id;
String str;
public A(int id,String str)
{
this.id=id;
this.str=str;
}
public boolean equals(Object obj)
{
A a1=(A)obj;
return this.id==a1.id;
}
public static void main(String arg[])
{
A obj=new A(101,"sam");
A obj1=new A(101,"sam");
obj.equals(obj1)//true
obj==obj1 // fasle
}
}
우리가 오버라이드 한 동일한 경우에 대해 true와 false를 반환하는지 확인하십시오.
method와 같습니다.
그것은 객체의 내용 (ID)의 기본에 대한 객체를 비교합니다
하지만 ==
여전히 객체의 참조를 비교하십시오.
==와 equals ()의 주요 차이점은
1) ==는 프리미티브를 비교하는 데 사용됩니다.
예를 들면 다음과 같습니다.
String string1 = "Ravi";
String string2 = "Ravi";
String string3 = new String("Ravi");
String string4 = new String("Prakash");
System.out.println(string1 == string2); // true because same reference in string pool
System.out.println(string1 == string3); // false
2) equals ()는 객체를 비교하는 데 사용됩니다. 예를 들면 다음과 같습니다.
System.out.println(string1.equals(string2)); // true equals() comparison of values in the objects
System.out.println(string1.equals(string3)); // true
System.out.println(string1.equals(string4)); // false
public class StringPool {
public static void main(String[] args) {
String s1 = "Cat";// will create reference in string pool of heap memory
String s2 = "Cat";
String s3 = new String("Cat");//will create a object in heap memory
// Using == will give us true because same reference in string pool
if (s1 == s2) {
System.out.println("true");
} else {
System.out.println("false");
}
// Using == with reference and Object will give us False
if (s1 == s3) {
System.out.println("true");
} else {
System.out.println("false");
}
// Using .equals method which refers to value
if (s1.equals(s3)) {
System.out.println("true");
} else {
System.out.println("False");
}
}
}
---- 출력 ----- 참 거짓 참
프리미티브 유형의 래퍼 객체 (예 : Int, Long, Double-==는 두 값이 같으면 true를 반환 함)를 추가하는 것이 좋습니다.
Long a = 10L;
Long b = 10L;
if (a == b) {
System.out.println("Wrapped primitives behave like values");
}
대조적으로, 위의 두 Long을 두 개의 개별 ArrayList에 넣으면 equals는 동일하지만 ==는 그렇지 않습니다.
ArrayList<Long> c = new ArrayList<>();
ArrayList<Long> d = new ArrayList<>();
c.add(a);
d.add(b);
if (c == d) System.out.println("No way!");
if (c.equals(d)) System.out.println("Yes, this is true.");
Long a = 128l; Long b = 128l; System.out.println(a == b);
문자열 풀 (일명 인턴 ) 및 정수 풀 흐림 더 차이, 그리고 사용을 허용 할 수 있습니다==
경우에 따라 개체를 대신.equals
이렇게하면 더 복잡한 비용으로 더 큰 성능 (?)을 얻을 수 있습니다.
예 :
assert "ab" == "a" + "b";
Integer i = 1;
Integer j = i;
assert i == j;
복잡성 트레이드 오프 : 다음은 사용자를 놀라게 할 수 있습니다.
assert new String("a") != new String("a");
Integer i = 128;
Integer j = 128;
assert i != j;
그런 미세 최적화를 피하고 항상.equals
객체와 ==
기본 요소에 사용 하는 것이 좋습니다 .
assert (new String("a")).equals(new String("a"));
Integer i = 128;
Integer j = 128;
assert i.equals(j);
기본적으로 ==
두 객체가 힙에서 동일한 참조를 갖는지 비교하므로 두 참조가 동일한 객체에 연결되어 있지 않으면이 비교는 거짓이됩니다.
equals()
Object
클래스 에서 상속 된 메소드입니다. 기본적으로이 방법은 두 객체의 참조가 같은지 비교합니다. 그 뜻은:
object1.equals(object2)
<=> object1 == object2
그러나 같은 클래스의 두 개체간에 동등성을 설정하려면이 메서드를 재정의해야합니다. 재정의 한 hashCode()
경우 메소드를 재정의하는 것도 매우 중요합니다.equals()
.
hashCode()
동등성을 확립 할 때의 구현 은 Java Object Contract의 일부입니다. 컬렉션으로 작업하고 있고 구현하지 않은 hashCode()
경우 이상한 나쁜 일이 발생할 수 있습니다.
HashMap<Cat, String> cats = new HashMap<>();
Cat cat = new Cat("molly");
cats.put(cat, "This is a cool cat");
System.out.println(cats.get(new Cat("molly"));
null
구현하지 않은 경우 이전 코드를 실행 한 후 인쇄됩니다 hashCode()
.
Java는 연산자 오버로딩을 지원하지 않기 때문에 ==는 모든 객체에 대해 동일하게 작동하지만 equals ()는 메소드로 Java에서 재정의 될 수 있으며 비즈니스 규칙에 따라 객체를 비교하는 논리를 변경할 수 있습니다.
Java에서 ==와 equals의 주요 차이점은 "=="는 프리미티브를 비교하는 데 사용되는 반면 equals () 메소드는 객체의 동등성을 확인하는 것이 좋습니다.
문자열 비교는 == 및 equals 방법을 모두 사용하는 일반적인 시나리오입니다. java.lang.String 클래스 재정의는 메소드와 같으므로 두 String 객체에 동일한 내용이 포함되어 있으면 true를 반환하지만 두 참조가 동일한 객체를 가리키는 경우에만 ==를 반환합니다.
다음은 == 및 equals () 메소드를 사용하여 Java에서 두 문자열이 동일한 지 비교 하는 예 입니다.
public class TEstT{
public static void main(String[] args) {
String text1 = new String("apple");
String text2 = new String("apple");
//since two strings are different object result should be false
boolean result = text1 == text2;
System.out.println("Comparing two strings with == operator: " + result);
//since strings contains same content , equals() should return true
result = text1.equals(text2);
System.out.println("Comparing two Strings with same content using equals method: " + result);
text2 = text1;
//since both text2 and text1d reference variable are pointing to same object
//"==" should return true
result = (text1 == text2);
System.out.println("Comparing two reference pointing to same String with == operator: " + result);
}
}