成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java equals 和 == 完全解析

mikasa / 1097人閱讀

摘要:所以在對(duì)象沒有重寫這個(gè)方法時(shí),默認(rèn)使用此方法,即比較對(duì)象的內(nèi)存地址值。結(jié)果為可以發(fā)現(xiàn)不管對(duì)象的內(nèi)存地址是否相同并不影響其結(jié)果,所以類型比較的是數(shù)據(jù)值而不是內(nèi)存地址值。

今天朋友突然問到一個(gè)問題:

兩個(gè)對(duì)象使用x.equals(y)判斷結(jié)果為true時(shí),兩個(gè)對(duì)象的hashCode可以不同嗎?

在Java編程中,判斷兩個(gè)對(duì)象是否相等常常使用equals()或是==,但是其中的區(qū)別和原理可能很多人并不完全清楚。今天就借著上面這個(gè)問題來看看equals()==的區(qū)別和原理。

1. 數(shù)據(jù)類型與==的含義

Java中的數(shù)據(jù)類型分為基本數(shù)據(jù)類型和引用數(shù)據(jù)類型:

基本類型:編程語言中內(nèi)置的最小粒度的數(shù)據(jù)類型。它包括四大類八種類型

4種整數(shù)類型:byte、short、int、long

2種浮點(diǎn)數(shù)類型:float、double

1種字符類型:char

1種布爾類型:boolean

引用類型:引用也叫句柄,引用類型,是編程語言中定義的在句柄中存放著實(shí)際內(nèi)容所在地址的地址值的一種數(shù)據(jù)形式

接口

數(shù)組

對(duì)于基本類型來說,== 比較的是它們的值

對(duì)于引用類型來說,== 比較的是它們?cè)趦?nèi)存中存放的地址(堆內(nèi)存地址)

例:

public void test(){
    int num1 = 100;
    int num2 = 100;

    String str1 = "James";
    String str2 = "James";

    String str3 = new String("James");
    String str4 = new String("James");

    System.out.println("num1 == num2 : " + (num1 == num2));
    System.out.println("str1 address : " + System.identityHashCode(str1) + ";
str2 address : " + System.identityHashCode(str1) + ";
str1 == str2 : " + (str1 == str2));
    System.out.println("str3 address : " + System.identityHashCode(str3) + ";
str4 address : " + System.identityHashCode(str4) + ";
str3 == str4 : " + (str3 == str4));
}

運(yùn)行上面的代碼,可以得到以下結(jié)果:

num1 == num2 : true

str1 address : 1174290147;
str2 address : 1174290147;
str1 == str2 : true

str3 address : 1289696681;
str4 address : 1285044316;
str3 == str4 : false

可以看到str1和str2的內(nèi)存地址都是1174290147,所以使用==判斷為true,但是str3和str4的地址是不同的,所以判斷為false。

2. equals() 方法解析

在Java語言中,所有類都是繼承于Object這個(gè)超類的,在這個(gè)類中也有一個(gè)equals()方法,那么我們先來看一下這個(gè)方法。

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

可以看得出,這個(gè)方法很簡單,就是比較對(duì)象的內(nèi)存地址的。所以在對(duì)象沒有重寫這個(gè)方法時(shí),默認(rèn)使用此方法,即比較對(duì)象的內(nèi)存地址值。但是類似于String、Integer等類均已重寫了equals()。下面以String為例。

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = length();
            if (n == anotherString.length()) {
                int i = 0;
                while (n-- != 0) {
                    if (charAt(i) != anotherString.charAt(i))
                            return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

很明顯,String的equals()方法僅僅是對(duì)比它的 數(shù)據(jù)值,而不是對(duì)象的 內(nèi)存地址 。

String 為例測(cè)試一下。

public void test() {

    String str1 = "James";
    String str2 = "James";

    String str3 = new String("James");
    String str4 = new String("James");

    System.out.println("str1 address : " + System.identityHashCode(str1) + ";
str2 address : " + System.identityHashCode(str1) + ";
str1.equals(str2) : " + str1.equals(str2));
    System.out.println("str3 address : " + System.identityHashCode(str3) + ";
str4 address : " + System.identityHashCode(str4) + ";
str3.equals(str4) : " + str3.equals(str4));
}

結(jié)果為:

str1 address : 1174290147;
str2 address : 1174290147;
str1.equals(str2) : true

str3 address : 1289696681;
str4 address : 1285044316;
str3.equals(str4) : true

可以發(fā)現(xiàn)不管對(duì)象的內(nèi)存地址是否相同并不影響其結(jié)果,所以String類型比較的是 數(shù)據(jù)值, 而不是 內(nèi)存地址值

所以總結(jié)一下equals()== 的區(qū)別:

==

基本類型:對(duì)比它們的值是否相等

引用類型:對(duì)比它們的內(nèi)存地址是否相等

equals()

基本類型:使用==進(jìn)行比較

引用類型:默認(rèn)情況下,對(duì)比它們的地址是否相等;如果equals()方法被重寫,則根據(jù)重寫的要求來比較。

3. equals() 與 hashCode()

在詳細(xì)的了解了==equals()的作用和區(qū)別后,現(xiàn)在來研究一下之前的那個(gè)問題:

兩個(gè)對(duì)象使用x.equals(y)判斷結(jié)果為true時(shí),兩個(gè)對(duì)象的hashCode可以不同嗎?

首先我們需要知道hashCode到底是什么?還是從Object這個(gè)超類來看一下。

public int hashCode() {
    return identityHashCode(this); // 此處返回對(duì)象的內(nèi)存地址值
}

代碼也很簡單,看來默認(rèn)情況下,hashCode就等于對(duì)象的 內(nèi)存地址值(注:System.identityHashCode(Object obj)方法用于獲取對(duì)象的內(nèi)存地址,之前的樣例代碼中有使用)。和equals()方法一樣重寫之后,hashCode()方法方法也是可以被重寫的,而且兩者一般情況下都是成對(duì)出現(xiàn)。

簡單測(cè)試一下String類型重寫hashCode()方法之后有什么變化。

public void test() {
    String str1 = "James";
    System.out.println("str1 address : " + System.identityHashCode(str1) + "
str1 hashCode : " + str1.hashCode());
}

結(jié)果為:

str1 address : 1174290147
str1 hashCode : 71338276

很明顯,hashCode 已經(jīng)不是內(nèi)存地址了。

那么總結(jié)一下:

equals():默認(rèn)情況下比較的是對(duì)象的 內(nèi)存地址值,被重寫后按照重寫要求進(jìn)行比較,一般是比較對(duì)象的 數(shù)據(jù)值

hashCode(): 默認(rèn)情況下為對(duì)象的 內(nèi)存地址值,被重寫后按照重寫要求生成新的值。

到此對(duì)于剛開始提出的問題應(yīng)該很好解決了。對(duì)于這兩個(gè)對(duì)象,只要我們重寫equals()方法,就可以比較對(duì)象的 數(shù)據(jù)值,而不重寫hashCode()方法,此時(shí)兩個(gè)對(duì)象的 hashCode 就默認(rèn)為內(nèi)存地址值了,只要將兩個(gè)對(duì)象指向不同的地址即可。

驗(yàn)證環(huán)節(jié),先創(chuàng)建一個(gè)類:

public class CustomBean {
    private String name;
    private int age;

    public CustomBean(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        CustomBean that = (CustomBean) o;
        return age == that.age &&
                Objects.equals(name, that.name);
    }

    // @Override
    // public int hashCode() {
    //     return Objects.hash(name, age);
    // }
}

創(chuàng)建測(cè)試方法:

@Test
public void test() {
    CustomBean x = new CustomBean("James", 18);
    CustomBean y = new CustomBean("James", 18);

    System.out.println("x.hashCode: " + x.hashCode());
    System.out.println("x address : " + System.identityHashCode(x));
    System.out.println("y.hashCode: " + y.hashCode());
    System.out.println("x address : " + System.identityHashCode(y));

    System.out.println("x and y is equals : " + x.equals(y));
}

運(yùn)行結(jié)果為:

x.hashCode: 1174290147
x address : 1174290147

y.hashCode: 1289696681
x address : 1289696681

x and y is equals : true

很明顯,這就是問題中所描述的那種情況:兩個(gè)對(duì)象使用x.equals(y)判斷結(jié)果為true時(shí),兩個(gè)對(duì)象的hashCode不相同。

4. 總結(jié)

至此,==equals()的區(qū)別及作用,equals()hashCode的關(guān)系及使用已經(jīng)了解清楚了。下面再總結(jié)一下:

對(duì)于equals()== 的區(qū)別:

==

基本類型:對(duì)比它們的值是否相等

引用類型:對(duì)比它們的內(nèi)存地址是否相等

equals()

基本類型:使用==進(jìn)行比較

引用類型:默認(rèn)情況下,對(duì)比它們的地址是否相等;如果equals()方法被重寫,則根據(jù)重寫的要求來比較

對(duì)于equals()hashCode()的關(guān)系:

根據(jù)Object超類中的文檔說明,equals()hashCode()兩個(gè)方法應(yīng)該 同進(jìn)同退。上面的例子只是舉例說明存在那種情況,但那并不是一個(gè)很好的應(yīng)用。

所以一定要記住equals()hashCode()兩個(gè)方法應(yīng)該 同進(jìn)同退。

所以一定要記住equals()hashCode()兩個(gè)方法應(yīng)該 同進(jìn)同退。

所以一定要記住equals()hashCode()兩個(gè)方法應(yīng)該 同進(jìn)同退。

重要的事情說三遍。

歡迎您關(guān)注我的博客主頁:James Blog

閱讀原文

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/73908.html

相關(guān)文章

  • Java雜記17—String全面解析

    摘要:所以也就是說在沒有的基礎(chǔ)上,執(zhí)行代碼會(huì)在串池中創(chuàng)建一個(gè),也會(huì)在堆內(nèi)存中再出來一個(gè)。不可變性的優(yōu)點(diǎn)安全性字符串不可變安全性的考慮處于兩個(gè)方面,數(shù)據(jù)安全和線程安全。 摘要: String基本特性,String源碼,為什么String不可變? 前言 基于字符串String在java中的地位,關(guān)于String的常識(shí)性知識(shí)就不多做介紹了,我們先來看一段代碼 public class Test {...

    jeffrey_up 評(píng)論0 收藏0
  • 重拾-MyBatis-配置文件解析

    摘要:前言我們知道在使用時(shí),我們需要通過去創(chuàng)建實(shí)例,譬如為的配置文件那么我們看下方法的具體實(shí)現(xiàn)創(chuàng)建實(shí)例并執(zhí)行解析主要通過執(zhí)行對(duì)配置文件的解析,具體實(shí)現(xiàn)如下文配置文件解析解析標(biāo)簽解析標(biāo)簽解析別名標(biāo)簽解析插件標(biāo)簽解析標(biāo)簽解析標(biāo)簽解析標(biāo)簽從的方法實(shí)現(xiàn)我 前言 我們知道在使用 Mybatis 時(shí),我們需要通過 SqlSessionFactoryBuild 去創(chuàng)建 SqlSessionFactory ...

    王晗 評(píng)論0 收藏0
  • Java+Windows+ffmpeg實(shí)現(xiàn)視頻轉(zhuǎn)換

    摘要:最近由于項(xiàng)目需要,研究了一下如何用實(shí)現(xiàn)視頻轉(zhuǎn)換,著實(shí)廢了點(diǎn)心思,整理整理,寫出給自己備忘下。支持的類型有,,,,,,,,等,這些類型,可以利用進(jìn)行直接轉(zhuǎn)換。 舊文,源地址見這里。 最近由于項(xiàng)目需要,研究了一下如何用Java實(shí)現(xiàn)視頻轉(zhuǎn)換,著實(shí)廢了點(diǎn)心思,整理整理,寫出給自己備忘下。 思路 由于之前沒有沒法過相關(guān)功能的經(jīng)驗(yàn),一開始來真不知道從哪里入手。當(dāng)然,這個(gè)解決,google...

    YuboonaZhang 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

mikasa

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<