Heim  >  Artikel  >  Java  >  Was sind equal und == in Java? Was sind die Unterschiede?

Was sind equal und == in Java? Was sind die Unterschiede?

青灯夜游
青灯夜游nach vorne
2018-10-19 17:12:183781Durchsuche

Der Inhalt dieses Artikels besteht darin, vorzustellen, was gleich und == in Java sind. Was sind die Unterschiede? Es hat einen gewissen Referenzwert. Freunde in Not können sich darauf beziehen. Ich hoffe, es wird Ihnen hilfreich sein.

1. Datentypen in Java und die Bedeutung von „==":

  • Grundlegende Datentypen (auch primitive Datentypen genannt): Byte, Short, Char, Int, Long, Float, Double, Boolean. Um sie zu vergleichen, verwenden Sie das doppelte Gleichheitszeichen (==) und vergleicht ihre Werte .

  • Referenzdatentyp: Wenn sie mit (==) verglichen werden, werden sie mit der Speicheradresse verglichen im Speicher (genauer gesagt handelt es sich um Heap-Speicher Adresse ).

Hinweis: Für den zweiten Typ ist das Ergebnis ihres Vergleichs wahr, es sei denn, es handelt sich um dasselbe neue Objekt, andernfalls ist das Ergebnis des Vergleichs falsch. Denn jedes Mal wird der Heap-Speicherplatz neu geöffnet.

2. Einführung in die Methode equal():

Alle Klassen in JAVA erben von der Superklasse Object In der Object-Klasse Die Methode equal ist in definiert. Der Quellcode von equal ist wie folgt geschrieben:

public boolean equals(Object obj) {
    //this - s1
    //obj - s2
    return (this == obj);
}

Wie Sie sehen können, besteht das anfängliche Standardverhalten dieser Methode darin, den Speicheradressenwert des Objekts zu vergleichen ist von geringer Bedeutung. Daher wurde diese Methode in einigen Klassenbibliotheken wie String, Integer und Date überschrieben. Unter diesen Klassen verfügt equals über eine eigene Implementierung (wird im Allgemeinen verwendet, um zu vergleichen, ob die Werte der Mitgliedsvariablen von Objekten gleich sind), anstatt die Speicheradresse der Klasse im Heapspeicher zu vergleichen.

Also Beim Gleichheitsvergleich zwischen zusammengesetzten Datentypen ist der Vergleich zwischen ihnen immer noch der Adresswert des Speicherorts im Speicher, ohne die Gleichheitsmethode zu überschreiben als doppeltes Gleichheitszeichen (==); wenn es überschrieben wird, befolgen Sie die Anforderungen zum Überschreiben.

Fassen wir die beiden obigen Absätze zusammen:

== Funktion:
Grundtyp: Was verglichen wird, ist, ob die Werte sind gleich
Referenztyp: Es wird verglichen, ob der Adresswert gleich ist

Die Rolle von Gleichheit:
Referenz Typ: Standardmäßig wird der Adresswert verglichen.

Hinweis: Wir können diese Methode jedoch je nach Situation selbst überschreiben. Im Allgemeinen wird das Umschreiben automatisch generiert und die Mitgliedsvariablenwerte der Vergleichsobjekte sind gleich

3. Die Methode equal() der String-Klasse:

Nehmen wir nun die String-Klasse als Beispiel:

Wir gehen in das Verzeichnis srcjavalang, um die String-Klasse zu finden und stellen fest, dass die Methode equal wie folgt umgeschrieben wurde:

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof 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;
    }

Wie aus dem obigen Code ersichtlich ist, vergleicht die überschriebene Zeichenfolge in der String-Klasse die Methode equal() tatsächlich den Inhalt zweier Zeichenfolgen. Werfen wir einen Blick auf den Vergleich von String-Klassen anhand des tatsächlichen Codes.

1. Der Beispielcode lautet wie folgt:

public class StringDemo {
    public static void main(String[] args) {
        String s1 = "Hello";
        String s2 = "Hello";
        System.out.println(s1 == s2);   // true
    }
}

Verwenden Sie im obigen Code „==", um s1 und s2 zu vergleichen, und das zurückgegebene Ergebnis ist wahr.

2. Wenn Sie das Programm geringfügig ändern, werden Sie etwas Seltsames finden:

public class StringDemo {
    public static void main(String args[]) {
        String str1 = "Hello";
        String str2 = new String("Hello");
        String str3 = str2; // 引用传递
        System.out.println(str1 == str2); // false
        System.out.println(str1 == str3); // false
        System.out.println(str2 == str3); // true
        System.out.println(str1.equals(str2)); // true
        System.out.println(str1.equals(str3)); // true
        System.out.println(str2.equals(str3)); // true
    }
}

In der 4. Codezeile oben erstellen wir ein neues Objekt, verwenden Sie „==", um s1 zu vergleichen und s2, und das Ergebnis ist falsch. Wenn Sie „equals“ verwenden, um s1 und s2 zu vergleichen, ist das zurückgegebene Ergebnis wahr.

Um den obigen Code zu analysieren, müssen wir zuerst den Heap-Speicherplatz und den Stapelspeicherplatz analysieren. Dies ist sehr wichtig:

Bitte erläutern Sie den Unterschied zwischen „==" und equal() beim String-Vergleich?

  • ==: Was verglichen wird, ist, ob die Werte zweier String-Speicheradressen (Heap-Speicher) gleich sind, was a ist numerischer Vergleich;

  • equal(): Vergleicht den Inhalt zweier Zeichenfolgen, was einem Inhaltsvergleich entspricht.

Zukünftig wird equal() bei der Beurteilung der Stringgleichheit verwendet.

3. Ändern Sie das Programm erneut:

public class ObjectDemo{
    public static void main(String[] args) {
        String s1 = "Hello";
        String s2 = new String("Hello");
        s2 = s2.intern();
        System.out.println(s1 == s2);       //  true
        System.out.println(s1.equals(s2));  //  true
    }
}

In Zeile 5 des obigen Codes wird die intern()-Methode „abc“.intern() von java.lang verwendet .String Der Rückgabewert der Methode ist immer noch die Zeichenfolge „abc“. Oberflächlich betrachtet scheint diese Methode nutzlos zu sein. Tatsächlich führt es jedoch eine kleine Aktion aus: Prüft, ob eine Zeichenfolge wie „abc“ im Zeichenfolgenpool vorhanden ist. Wenn sie nicht vorhanden ist, wird die Zeichenfolge zurückgegeben. Bei dieser Methode wird „abc“ zum String-Pool hinzugefügt, bevor ihre Referenz zurückgegeben wird.

4. Vergleichen Sie die Werte zweier Objekte:

Der Code lautet wie folgt:

package com.smyh;

public class ObjectDemo {
    public static void main(String args[]){
        Student student1 = new Student("生命壹号",22,"成都");
        Student student2 = new Student("生命壹号",22,"成都"); 
        System.out.println(student1==student2);
        System.out.println(student1.equals(student2));
    }
}
class Student {
    private String name;
    private int age;
    private String address;
    public Student(String name,int age,String address){
        this.name = name;
        this.age = age;
        this.address = address;
    }
    //重写Object类中的equals方法(比较两个对象的值是否相等)
    public boolean equals(Object obj){
        //为了提高效率:如果两个内存地址相等,那么一定是指向同一个对内存中的对象,就无需比较两个对象的属性值(自己跟自己比,没啥意义嘛)
        if(this==obj){
            return true;
        }
        
        //为了提供程序的健壮性
        //我先判断一下,obj是不是学生的一个对象,如果是,再做向下转型,如果不是,直接返回false。
        //这个时候,我们要判断的是对象是否是某个类的对象?
        //记住一个格式:对象名 instanceof 类名。表示:判断该对象是否是该类的一个对象       
        if(!(obj instanceof Student)){        
            return false;                
        }
        
        //如果是就继续
        Student s = (Student)obj;//强制转换,即向下转型(毕竟Object类型没有具体的对象属性)        
        return this.name.equals(s.name) && this.age == s.age && this.address.equals(s.address);//判断两个对象的属性值是否相等
    }
}

上述代码中,首先判断传递进来的对象与当前对象的地址是否相等,如果相等,则肯定是同一个堆内存中的对象。因为传递进来的参数是Object类型,所以任何对象都可以接收。一旦接收进来,就将Object类型的对象向下转型,然后判断具体的属性值。

 运行效果:

五、equals()的重写规则

前面我们已经知道如何去重写equals方法来实现我们自己的需求了,但是我们在重写equals方法时,还是需要注意如下几点规则的。

  • 自反性。对于任何非null的引用值x,x.equals(x)应返回true。

  • 对称性。对于任何非null的引用值x与y,当且仅当:y.equals(x)返回true时,x.equals(y)才返回true。

  • 传递性。对于任何非null的引用值x、y与z,如果y.equals(x)返回true,y.equals(z)返回true,那么x.equals(z)也应返回true。

  • 一致性。对于任何非null的引用值x与y,假设对象上equals比较中的信息没有被修改,则多次调用x.equals(y)始终返回true或者始终返回false。

  • 对于任何非空引用值x,x.equal(null)应返回false。

六、为什么重写equals()的同时还得重写hashCode()

我们知道equals()和hashCode()是java Object中两个基本方法,有时候由于业务的需求,需要我们重写equals()方法,比如对于Person类中,业务的需要让我们当Person对象的cardID一致的时候,就认为两个对象equals,此时就需要在Person类中重写equals()方法,如下:

public class Person
{

    public String name;
    public int age;
    public String cardID;

    .....// 省略

    @Override
    public boolean equals(Object o)
    {
        if (o instanceof Person)
        {
            Person p = (Person) o;
            return this.cardID.equals(p.cardID);
        } else
        {
            return false;
        }
    }

    @Override
    public int hashCode()
    {
        return this.cardID.hashCode();
    }

    ......// 省略


}

保证相同对象的hashCode一定相同,不同对象的hashCode基本相同。

阅读HashMap的源码,我们可以看到,HashMap中实现了一个Entry[]数组,数组的每个item是一个单项链表的结构,当我们put(key, value)的时候,HashMap首先会newItem.key.hashCode()作为该newItem在Entry[]中存储的下标,要是对应的下标的位置上没有任何item,则直接存储上去,要是已经有oldItem存储在了上面,那就会判断oldItem.key.equals(newItem.key),那么要是我们把上面的Person作为key进行存储的时候,重写了equals()方法,但没重写hashCode()方法,当我们去put()的时候,首先会通过hashCode() 计算下标,由于没有重写hashCode(),那么实质是完整的Object的hashCode(),会受到Object多个属性的影响,本来equals的两个Person对象,反而得到了两个不同的下标。

同样的,HashMap在get(key)的过程中,也是首先调用hashCode()计算item的下标,然后在对应下标的地方找,要是为null,就返回null,要是 != null,会去调用equals()方法,比较key是否一致,只有当key一致的时候,才会返回value,要是我们没有重写hashCode()方法,本来有的item,反而会找不到,返回null结果。

所以,要是你重写了equals()方法,而你的对象可能会放入到散列(HashMap,HashTable或HashSet等)中,那么还必须重写hashCode(), 如果你的对象有可能放到有序队列(实现了Comparable)中,那么还需要重写compareTo()的方法。

总结:以上就是本篇文的全部内容,希望能对大家的学习有所帮助。更多相关教程请访问Java视频教程java开发图文教程bootstrap视频教程

Das obige ist der detaillierte Inhalt vonWas sind equal und == in Java? Was sind die Unterschiede?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen