Я хотів уточнити, чи правильно я це розумію:
==
є порівняльним посиланням, тобто обидва об'єкти вказують на одне місце пам'яті.equals()
оцінює до порівняння значень в об’єктах
.equals()
як значущо рівнозначний
Я хотів уточнити, чи правильно я це розумію:
==
є порівняльним посиланням, тобто обидва об'єкти вказують на одне місце пам'яті.equals()
оцінює до порівняння значень в об’єктах.equals()
як значущо рівнозначний
Відповіді:
Загалом, відповідь на ваше запитання "так", але ...
.equals(...)
порівняємо лише те, що написано для порівняння, ні більше, ні менше.equals(Object o)
методу найближчого батьківського класу, який перекрив цей метод.Object#equals(Object o)
метод. Для API об’єкта це те саме, що і ==
; тобто він повертає істину тоді і тільки тоді, коли обидві змінні посилаються на один і той же об'єкт, якщо їх посилання є одним і тим же. Таким чином, ви будете перевіряти предметну рівність, а не функціональну рівність .hashCode
якщо ви перекриєте, equals
щоб не «розірвати договір». Відповідно до API, результат, що повертається з hashCode()
методу для двох об'єктів, повинен бути однаковим, якщо їхні equals
методи показують, що вони еквівалентні. Зворотне не обов'язково вірно.==
перевіряє посилання на пам'ять, то чому я отримую таке дивне поведінку в [this] [1] [1]: docs.google.com/document/d/… Я очікував, що результат буде правдивим. можу очистити мої плутанини
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:
В одно () метод порівнює «значення» всередині примірників String (в купі) незалежно від того, якщо два посилання на об'єкти відносяться до тієї ж рядки , наприклад , чи ні. Якщо будь-які дві посилання на об'єкт типу String посилаються на один і той же екземпляр String, то чудово! Якщо два посилання на об'єкт відносяться до двох різних екземплярів String .. це не має значення. Його "значення" (тобто вміст масиву символів) у кожному екземплярі String, який порівнюється.
З іншого боку, оператор "==" порівнює значення двох посилань на об'єкт, щоб побачити, чи вони посилаються на один і той же екземпляр String . Якщо значення обох посилань на об'єкт "посилаються на" один і той же екземпляр String, то результатом булевого виразу буде "true" .. duh. Якщо, з іншого боку, значення обох посилань на об'єкти "посилаються на" різні екземпляри String (навіть якщо обидва екземпляри String мають однакові "значення", тобто вміст масивів символів кожного екземпляра String є однаковим), Результат булевого виразу буде "хибним".
Як і будь-яке пояснення, нехай воно зануриться.
Я сподіваюся, що це трохи прояснить справи.
String
х, ==
це референс дорівнює а, да, але це , як правило , працює (як і в двох String
з з тим же змістом , буде , як правило , бути ==
один з одним), з - за того , як Java ручки String
s. Це не завжди, і це, звичайно, погана практика, але це звичайна помилка, особливо це стосується людей, які походять з інших мов.
String
будувати з строкового литерала буде додано до чого - то називається String constant pool
, наприклад , String s1 = "someString"; String s2 = "someString;"
як s1
і s2
розділить ту ж посилання. s1 == s2
повернеться правдою. Але якщо вони були побудовані за допомогою String constructor
, наприклад, String s1 = new String("someString"); String s2 = new String("someString");
вони не поділять однакові посилання. s1 == s2
повернеться помилковим.
Є деякі невеликі відмінності залежно від того, говорите ви про "примітиви" чи "типи об'єктів"; те саме можна сказати, якщо ви говорите про "статичних" або "нестатичних" членів; ви також можете змішати все вищезазначене ...
Ось приклад (ви можете запустити його):
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;
}
}
Ви можете порівняти пояснення до "==" (Оператор рівності) та ".equals (...)" (метод у класі java.lang.Object) за цими посиланнями:
Різниця між == та рівними мене колись плутала, поки я не вирішив детальніше розглянути це. Багато з них кажуть, що для порівняння рядків слід використовувати, 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
Ой! Тепер ви бачите, що особистістьHashCode (манго) дорівнює ідентичностіHashCode (mango2), але вона не дорівнює identitetHashCode (mango3)
Хоча всі змінні струни - манго, манго2 та манго3 - мають однакове значення, яке є "манго", identityHashCode()
все одно не однакове для всіх.
Тепер спробуйте відкоментувати цей рядок // mango2 = "mang";
і запустіть його знову цього разу, ви побачите, що всі три identityHashCode()
різні. Хм, це корисна підказка
ми знаємо, що якщо hashcode(x)=N
і hashcode(y)=N
=>x is equal to y
Я не впевнений, як java працює всередині, але я припускаю, що це сталося, коли я сказав:
mango = "mango";
java створив рядок, на "mango"
який вказувала (посилалася) змінна mango
щось подібне
mango ----> "mango"
Тепер у наступному рядку, коли я сказав:
mango2 = "mango";
Він фактично повторно використовував ту саму струну, "mango"
яка виглядає приблизно так
mango ----> "mango" <---- mango2
І манго, і mango2 вказують на ту саму довідку Тепер, коли я сказав
mango3 = new String("mango")
Це фактично створило абсолютно нове посилання (рядок) для "манго". яке виглядає приблизно так,
mango -----> "mango" <------ mango2
mango3 ------> "mango"
і тому, коли я виставив значення для mango == mango2
, це вийшло true
. і коли я виставляв значення для mango3 == mango2
, воно виводилось false
(навіть коли значення були однакові).
і коли ви прокоментували рядок, // mango2 = "mang";
це фактично створило рядок "mang", який перетворив наш графік так:
mango ---->"mango"
mango2 ----> "mang"
mango3 -----> "mango"
Ось чому ідентичністьHashCode не однакова для всіх.
Сподіваюся, це допоможе вам, хлопці. Насправді я хотів створити тестовий випадок, коли == провалюється і дорівнює () пропуск. Будь ласка, не соромтесь коментувати і повідомте мені, якщо я помиляюся.
mango == mango2
трапляється це тому, що ви не створили mango2
як новий об'єкт String, а натомість просто безпосередньо посилаєтесь "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)
Тоді як метод equals () перевіряє, чи відносяться дві змінні до об'єктів, що мають однаковий стан (значення) .
String foo = new String("abc");
String bar = new String("abc");
if(foo.equals(bar))
// True (The objects are identical but not same)
Ура :-)
Вам доведеться перекрити функцію рівності (разом з іншими), щоб використовувати це для користувацьких класів.
Метод рівняння порівнює об’єкти.
==
Бінарний оператор порівнює адресу пам'яті.
Обидва == і .equals () посилаються на один і той же об'єкт, якщо ви не переосмислюєте .equals ().
Це ваше бажання, що ви хочете зробити, коли ви переотримаєте .equals (). Ви можете порівняти стан об'єкта, що викликає, з передаваним у стані об'єкта або просто зателефонувати super.equals ()
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 # дорівнює .
Єдиний раз, коли ви дійсно хочете використовувати оператор порівняння для об'єктів, - це wen, ви порівнюєте Enums. Це тому, що одночасно є лише один екземпляр значення Enum. Наприклад, з урахуванням перерахунку
enum FooEnum {A, B, C}
У вас ніколи не буде більше, ніж один екземпляр A
одночасно, і те саме для B
і C
. Це означає, що ви можете насправді написати такий спосіб, як:
public boolean compareFoos(FooEnum x, FooEnum y)
{
return (x == y);
}
І у вас не буде жодних проблем.
Коли ви оцінюєте код, цілком зрозуміло, що (==) порівнюється відповідно до адреси пам'яті, тоді як дорівнює (Object o) порівняння hashCode () екземплярів. Ось чому, як кажуть, не розривайте договір між рівними () та 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, посилаються на те саме місце пам'яті в Heap .
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 , мені потрібно визначити базу критеріїв, за якими я порівнятиму двох осіб . Скажімо, цей клас людини має змінні екземпляри висоти та ваги.
Таким чином, створюючи об'єкти особи person1 and person2
та для порівняння цих двох за допомогою .equals()
I потрібно переосмислити метод рівних класу person, щоб визначити, на основі яких змінних екземплярів (висота чи вага) буде порівняння.
Однак == 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
== посилання оператора завжди порівнюється. Але у випадку
метод рівний ()
це залежить від реалізації, якщо метод переосмислено рівним, ніж він порівнює об'єкт із базовою реалізацією, заданою методом переопределення.
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 і == також. але якщо ми перекриємо рівний метод, ніж
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
}
}
знаю перевірити, він поверне справжнє та хибне для того ж випадку, який ми перекрили
дорівнює методу.
він порівнює об'єкт за основним змістом (id) об'єкта
але ==
все ще порівнюють посилання на об’єкт.
Основна різниця між == і дорівнює ()
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) дорівнює () використовується для порівняння об'єктів. Наприклад :
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
==
може використовуватися в багатьох типах об'єктів, але ви можете використовувати їх Object.equals
для будь-якого типу, особливо для рядків та маркерів Google Map.
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");
}
На відміну від цього, розміщуючи вищевказані два Лонги у два окремі списки масивів, рівне бачить їх однаковими, але == не робить.
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);
рядок басейн (ака інтернування ) і Integer басейн розмиття різниця далі, і може дозволити вам використовувати ==
для об'єктів , в деяких випадках замість.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);
Коротше кажучи, відповідь - так.
У Java ==
оператор порівнює два об'єкти, щоб побачити, чи вказують вони на одне місце пам’яті; при цьому .equals()
метод насправді порівнює два об'єкти, щоб побачити, чи мають вони однакове значення об'єкта.
В основному, ==
порівнює, якщо два об’єкти мають однакове посилання на купу, тому, якщо два посилання не пов'язані з одним і тим же об'єктом, це порівняння буде помилковим.
equals()
це метод, успадкований від Object
класу. Цей метод за замовчуванням порівнює, якщо два об'єкти мають одне і те ж референс. Це означає:
object1.equals(object2)
<=> object1 == object2
Однак якщо ви хочете встановити рівність між двома об'єктами одного класу, вам слід перекрити цей метод. Також дуже важливо скасувати метод, hashCode()
якщо ви його перекрили equals()
.
Реалізувати, hashCode()
коли встановлення рівності є частиною Договору Java-об'єкта. Якщо ви працюєте з колекціями, а ви не реалізували 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 не підтримує перевантаження оператора, == поводиться однаково для кожного об'єкта, але дорівнює () - метод, який можна перекрити в Java, а логіка для порівняння об'єктів може бути змінена на основі правил бізнесу.
Основна відмінність == від рівня в Java полягає в тому, що для порівняння примітивів використовується "==", а для перевірки рівності об'єктів рекомендується метод equals ().
Порівняння рядків є загальним сценарієм використання методу як ==, так і рівняння. Оскільки java.lang.String клас переопределення дорівнює методу, він повертає істину, якщо два об'єкта String містять однаковий вміст, але == повертає істину лише тоді, коли дві посилання вказують на один і той же об'єкт.
Ось приклад порівняння двох рядків у Java для рівності за допомогою методу == та equals (), який очистить деякі сумніви:
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);
}
}