国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專(zhuān)注于服務(wù)器技術(shù)及軟件下載分享
分類(lèi)導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - Java教程 - Java中如何正確重寫(xiě)equals方法

Java中如何正確重寫(xiě)equals方法

2022-01-26 12:42寧海沒(méi)有七號(hào)公園 Java教程

Object類(lèi)中equals方法比較的是兩個(gè)對(duì)象的引用地址,只有對(duì)象的引用地址指向同一個(gè)地址時(shí),才認(rèn)為這兩個(gè)地址是相等的,否則這兩個(gè)對(duì)象就不相等

重寫(xiě)equals方法的正確打開(kāi)方式

正文開(kāi)始@Assassin

 

1. 什么是equals方法?

我們首先得知道,Object類(lèi)Java中所有類(lèi)的父類(lèi)(超類(lèi)/基類(lèi)),也就是說(shuō),在Java中,所有的類(lèi)都是默認(rèn)繼承自Object類(lèi)的,換言之,Object類(lèi)中所實(shí)現(xiàn)的方法我們都可以直接拿來(lái)用。而equals方法便是Object類(lèi)所實(shí)現(xiàn)的眾多方法之一。

以下截圖自Java11 API

Java中如何正確重寫(xiě)equals方法

Object類(lèi)的所有方法:

Java中如何正確重寫(xiě)equals方法

1.1 equals方法:

  • equals:是Object類(lèi)中的方法,只能判斷引用類(lèi)型,等下可以帶大伙看看jdk源碼
  • 默認(rèn)判斷的是地址是否相等(因?yàn)橐妙?lèi)型變量底層本質(zhì)就是來(lái)存儲(chǔ)對(duì)象地址的,有C/C++知識(shí)的小伙伴應(yīng)該很了解 ),在子類(lèi)中往往會(huì)重寫(xiě)該方法,用于判斷對(duì)象的內(nèi)容是否相等。比如等下會(huì)簡(jiǎn)單了解到的IntegerString(在IDEA里看源碼實(shí)現(xiàn) )

 

2. 為什么要重寫(xiě)equals方法?

我們有Object類(lèi)實(shí)現(xiàn)的equals方法能用不就行了?為啥還得重寫(xiě)equals方法呢?這就要看看Object類(lèi)equals方法實(shí)現(xiàn)機(jī)制了。

Java中如何正確重寫(xiě)equals方法

我們可以清楚地看到,Object類(lèi)equals方法底層是用 == 來(lái)實(shí)現(xiàn)的,也就是說(shuō)它的用法跟我們平常用來(lái)比較基本數(shù)據(jù)類(lèi)型的 == 用法一致。我們首先來(lái)看一下 == 的語(yǔ)法:

  • == 只能用來(lái)比較基本數(shù)據(jù)類(lèi)型是否相等,也就是單純的值比較;
  • == 在比較浮點(diǎn)數(shù)的時(shí)候也可能存在失效的情況,這是因?yàn)楦↑c(diǎn)數(shù)的存儲(chǔ)機(jī)制跟整型家族不一樣,浮點(diǎn)數(shù)本身就不能表示一個(gè)精確的值(具體原因可自行查看IEEE 754規(guī)則,這里不再展開(kāi))

所以我們?cè)趩渭兊倪M(jìn)行基本數(shù)據(jù)類(lèi)型的值比較時(shí)可以用 == ,而比較引用數(shù)據(jù)類(lèi)型就不能這么做,前面有提到,引用數(shù)據(jù)類(lèi)型本質(zhì)上是來(lái)引用/存儲(chǔ)對(duì)象的地址的,所有你完全可以把它當(dāng)做C/C++的指針來(lái)看待(這里杠一句說(shuō)Java沒(méi)有指針的,個(gè)人覺(jué)得只是叫法不同罷了
注: 不要把Java引用跟C++引用搞混了,C++引用其實(shí)是指針常量,即int* const,這也是C++的引用只能作為一個(gè)變量的別名的原因。

2.1 舉個(gè)例子吧~

比較兩個(gè)int時(shí)可以直接用 == ,當(dāng)它們相等時(shí)結(jié)果為true,而當(dāng)new了兩個(gè)屬性完全一樣的對(duì)象時(shí),再用 == 來(lái)進(jìn)行比較就會(huì)出現(xiàn)錯(cuò)誤,如我們所見(jiàn),明明我們應(yīng)該想要得到true的,結(jié)果卻是false
源碼:

Java中如何正確重寫(xiě)equals方法

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

Java中如何正確重寫(xiě)equals方法

到這里,我們應(yīng)該大致清楚為啥要在比較對(duì)象時(shí)重寫(xiě)equals方法了,因?yàn)?code>Object類(lèi)提供給我們的不好使~~

 

3. 分析equals源碼:

在進(jìn)行重寫(xiě)之前,我們依舊來(lái)看看Java API中的定義:
public boolean equals?(Object obj)
作用:指示某個(gè)其他對(duì)象是否“等于”此對(duì)象。

equals方法在非null對(duì)象引用上實(shí)現(xiàn)等價(jià)關(guān)系:

  • 自反性 :對(duì)于任何非空的參考值xx.equals(x)應(yīng)該返回true
  • 對(duì)稱(chēng)性 :對(duì)于任何非空引用值xyx.equals(y)應(yīng)該返回true當(dāng)且僅當(dāng)y.equals(x)回報(bào)true
  • 傳遞性 :對(duì)于任何非空引用值xyz ,如果x.equals(y)回報(bào)true個(gè)y.equals(z)回報(bào)true ,然后x.equals(z)應(yīng)該返回true
  • 一致性 :對(duì)于任何非空引用值xy ,多次調(diào)用x.equals(y)始終返回true或始終返回false ,前提是未修改對(duì)象上的equals比較中使用的信息。
  • 對(duì)于任何非空的參考值xx.equals(null)應(yīng)該返回false

類(lèi)Object的equals方法實(shí)現(xiàn)了對(duì)象上最具區(qū)別的可能等價(jià)關(guān)系; 也就是說(shuō),對(duì)于任何非空引用值x和y ,當(dāng)且僅當(dāng)x和y引用同一對(duì)象( x == y具有值true )時(shí),此方法返回true 。

注意:通常需要在重寫(xiě)此方法時(shí)覆蓋hashCode方法,以便維護(hù)hashCode方法的常規(guī)協(xié)定,該方法聲明相等對(duì)象必須具有相等的哈希代碼。

Java中如何正確重寫(xiě)equals方法

接下來(lái)看看String類(lèi)中重寫(xiě)的equals方法和Integer類(lèi)中重寫(xiě)的equals方法:

Java中如何正確重寫(xiě)equals方法

//String類(lèi)equals源代碼:
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;
  }

簡(jiǎn)單解讀一下就是當(dāng)對(duì)比的是同一個(gè)對(duì)象時(shí),直接返回true,提高效率。當(dāng)傳進(jìn)來(lái)的對(duì)象是當(dāng)前類(lèi)的實(shí)例時(shí),進(jìn)入進(jìn)一步的判斷,一個(gè)for循環(huán)依次遍歷字符串每一個(gè)字符,只要有一個(gè)字符不同就返回false

繼續(xù)來(lái)看看Integer類(lèi)的equals源代碼:

Java中如何正確重寫(xiě)equals方法

//Integer類(lèi)的equals源代碼:
public boolean equals(Object obj) {
      if (obj instanceof Integer) {
          return value == ((Integer)obj).intValue();
      }
      return false;
  }

Integer類(lèi)equals源碼簡(jiǎn)單許多,只要傳入的對(duì)象是當(dāng)前類(lèi)的實(shí)例,就進(jìn)行進(jìn)一步的判斷:當(dāng)它們的值相等時(shí),就返回true,不相等就返回false

這里還是來(lái)實(shí)際演示一下⑧,就以Integer類(lèi)為例:

Java中如何正確重寫(xiě)equals方法

很明顯,我們知道Integer類(lèi)重寫(xiě)了equals方法且是引用類(lèi)型。當(dāng)直接用 == 來(lái)比較引用類(lèi)型變量時(shí),結(jié)果是false,而用equals判斷結(jié)果為true。這便很好地說(shuō)明了重寫(xiě)equals方法的必要性。String類(lèi)大伙自己驗(yàn)證一哈⑧。

 

4. 正確重寫(xiě)equals方法:

(先說(shuō)結(jié)論,getClass()instanceof更安全)

到這里,我們基本把equals方法的各種源碼都分析了一遍,接下來(lái)就是我們自己要來(lái)實(shí)現(xiàn)equals方法了。

這里提供兩個(gè)比較常見(jiàn)的equals重寫(xiě)方法:

  • instanceof實(shí)現(xiàn)重寫(xiě)equals方法
  • getClass實(shí)現(xiàn)重寫(xiě)equals方法

假設(shè)有此場(chǎng)景:

在已經(jīng)創(chuàng)建好的長(zhǎng)方形類(lèi)中重寫(xiě)Object類(lèi)中的equals方法為當(dāng)長(zhǎng)方形的長(zhǎng)和寬相等時(shí),返回TRUE,同時(shí)重寫(xiě)hashCode方法,重寫(xiě)toString方法為顯示長(zhǎng)方形的長(zhǎng)寬信息。并測(cè)試類(lèi)。

package com.test10_04;

import java.util.Objects;

class Rectangle {
  private double length;
  private double wide;

  public Rectangle() {
      //空實(shí)現(xiàn)
  }
  public Rectangle(double length, double wide) {
      setLength(length);
      setWide(wide);
  }

  public double getLength() {
      return length;
  }

  public void setLength(double length) {
      assert length > 0.0 : "您的輸入有誤,長(zhǎng)方形的長(zhǎng)不能小于0";
      this.length = length;
  }

  public double getWide() {
      return wide;
  }

  public void setWide(double wide) {
      assert wide > 0.0 : "您的輸入有誤,長(zhǎng)方形的寬不能小于0";
      this.wide = wide;
  }

  public double area() {
      return this.length * this.wide;

  }
  public double circumference() {
      return 2 * (this.wide + this.length);
  }

  public boolean equals(Object obj) {
      if (this == obj) { //判斷一下如果是同一個(gè)對(duì)象直接返回true,提高效率
          return true;
      }
      if (obj == null || obj.getClass() != this.getClass()) { //如果傳進(jìn)來(lái)的對(duì)象為null或者二者為不同類(lèi),直接返回false
          return false;
      }
      //也可以以下方法:
//        if (obj == null || !(obj instanceof Rectangle)) { //如果傳進(jìn)來(lái)的對(duì)象為null或者二者為不同類(lèi),直接返回false
//            return false;
//        }
      Rectangle rectangle = (Rectangle) obj; //向下轉(zhuǎn)型
      //比較長(zhǎng)寬是否相等,注意:浮點(diǎn)數(shù)的比較不能簡(jiǎn)單地用==,會(huì)有精度的誤差,用Math.abs或者Double.compare
      return Double.compare(rectangle.length, length) == 0 && Double.compare(rectangle.wide, wide) == 0;
  }

  public int hashCode() { //重寫(xiě)equals的同時(shí)也要重寫(xiě)hashCode,因?yàn)橥粚?duì)象的hashCode永遠(yuǎn)相等
      return Objects.hash(length, wide); //調(diào)用Objects類(lèi),這是Object類(lèi)的子類(lèi)
  }

  public String toString() {
      return "Rectangle{" + "length=" + length + ", wide=" + wide + '}';
  }
}

public class TestDemo {
  public static void main(String[] args) {

      Rectangle rectangle1 = new Rectangle(3.0, 2.0);
      Rectangle rectangle2 = new Rectangle(3.0, 2.0);
      
      System.out.println(rectangle1.equals(rectangle2));
      System.out.println("rectangle1哈希碼:" + rectangle1.hashCode() +
              "\nrectangle2哈希碼:" + rectangle2.hashCode());
      System.out.println("toString打印信息:" + rectangle1.toString());
  }
}

具體實(shí)現(xiàn)思路在代碼中講的很清楚了,我們這里重點(diǎn)分析一下getClassinstanceof兩種實(shí)現(xiàn)方法的優(yōu)缺點(diǎn):

Java中如何正確重寫(xiě)equals方法

將代碼邏輯簡(jiǎn)化一下:
我們就重點(diǎn)看這段簡(jiǎn)單的代碼

//getClass()版本
public class Student {
	private String name;
	
  public void setName(String name) {
      this.name = name;
  }
	@Override
	public boolean equals(Object object){
		if (object == this)
			return true;
		// 使用getClass()判斷對(duì)象是否屬于該類(lèi)
		if (object == null || object.getClass() != getClass())
			return false;
		Student student = (Student)object;
		return name != null && name.equals(student.name);
}

//instanceof版本
public class Student {
	private String name;
	
  public void setName(String name) {
     this.name = name;
 }
	@Override
	public boolean equals(Object object){
		if (object == this)
			return true;
		// 通過(guò)instanceof來(lái)判斷對(duì)象是否屬于類(lèi)
		if (object == null || !(object instanceof Student))
			return false;
		Student student = (Student)object;
		return name!=null && name.equals(student.name);
	}
}

事實(shí)上兩種方案都是有效的,區(qū)別就是getClass()限制了對(duì)象只能是同一個(gè)類(lèi),而instanceof卻允許對(duì)象是同一個(gè)類(lèi)或其子類(lèi),這樣equals方法就變成了父類(lèi)與子類(lèi)也可進(jìn)行equals操作了,這時(shí)候如果子類(lèi)重定義了equals方法,那么就可能變成父類(lèi)對(duì)象equlas子類(lèi)對(duì)象為true,但是子類(lèi)對(duì)象equlas父類(lèi)對(duì)象就為false了,如下所示:

class GoodStudent extends Student {

  @Override
  public boolean equals(Object object) {
      return false;
  }

  public static void main(String[] args) {
      GoodStudent son = new GoodStudent();
      Student father = new Student();

      son.setName("test");
      father.setName("test");

		// 當(dāng)使用instance of時(shí)
      System.out.println(son.equals(father)); // 這里為false
      System.out.println(father.equals(son)); // 這里為true

		// 當(dāng)使用getClass()時(shí)
      System.out.println(son.equals(father)); // 這里為false
      System.out.println(father.equals(son)); // 這里為false	
  }
}

注意看這里用的是getClass()

Java中如何正確重寫(xiě)equals方法

返回值兩個(gè)都是false,符合我們的預(yù)期,(連類(lèi)都不一樣那肯定得為false啊)

Java中如何正確重寫(xiě)equals方法

而換成instanceof試試看咯:

Java中如何正確重寫(xiě)equals方法

運(yùn)行結(jié)果:一個(gè)為true一個(gè)為false,很明顯出現(xiàn)問(wèn)題了。

Java中如何正確重寫(xiě)equals方法

這里的原因如下:
instanceof的語(yǔ)法是這樣的:
當(dāng)一個(gè)對(duì)象為一個(gè)類(lèi)的實(shí)例時(shí),結(jié)果才為true。但它還有一個(gè)特點(diǎn)就是,如果當(dāng)這個(gè)對(duì)象時(shí)其子類(lèi)的實(shí)例時(shí),結(jié)果也會(huì)為true。這便導(dǎo)致了上述的bug。也就是說(shuō)當(dāng)比較的兩個(gè)對(duì)象,他們的類(lèi)是父子關(guān)系時(shí),instanceof可能會(huì)出現(xiàn)問(wèn)題。**需要深究的小伙伴可以自己去了解一哈,所以在這里建議在實(shí)現(xiàn)重寫(xiě)equals方法時(shí),盡量使用getClass來(lái)實(shí)現(xiàn)。

在重寫(xiě)equals方法的同時(shí)需要重寫(xiě)hashCode方法,具體原因可能后續(xù)會(huì)講到~~

到此這篇關(guān)于Java中如何正確重寫(xiě)equals方法的文章就介紹到這了,更多相關(guān)Java 重寫(xiě) equals方法內(nèi)容請(qǐng)搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!

原文鏈接:https://blog.csdn.net/b_ingram/article/details/120614766

延伸 · 閱讀

精彩推薦
  • Java教程Java BufferWriter寫(xiě)文件寫(xiě)不進(jìn)去或缺失數(shù)據(jù)的解決

    Java BufferWriter寫(xiě)文件寫(xiě)不進(jìn)去或缺失數(shù)據(jù)的解決

    這篇文章主要介紹了Java BufferWriter寫(xiě)文件寫(xiě)不進(jìn)去或缺失數(shù)據(jù)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程20個(gè)非常實(shí)用的Java程序代碼片段

    20個(gè)非常實(shí)用的Java程序代碼片段

    這篇文章主要為大家分享了20個(gè)非常實(shí)用的Java程序片段,對(duì)java開(kāi)發(fā)項(xiàng)目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程xml與Java對(duì)象的轉(zhuǎn)換詳解

    xml與Java對(duì)象的轉(zhuǎn)換詳解

    這篇文章主要介紹了xml與Java對(duì)象的轉(zhuǎn)換詳解的相關(guān)資料,需要的朋友可以參考下...

    Java教程網(wǎng)2942020-09-17
  • Java教程Java實(shí)現(xiàn)搶紅包功能

    Java實(shí)現(xiàn)搶紅包功能

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)搶紅包功能,采用多線程模擬多人同時(shí)搶紅包,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關(guān)于小米推送Java代碼,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧...

    富貴穩(wěn)中求8032021-07-12
  • Java教程升級(jí)IDEA后Lombok不能使用的解決方法

    升級(jí)IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級(jí),尋思已經(jīng)有好久沒(méi)有升過(guò)級(jí)了。升級(jí)完畢重啟之后,突然發(fā)現(xiàn)好多錯(cuò)誤,本文就來(lái)介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程Java8中Stream使用的一個(gè)注意事項(xiàng)

    Java8中Stream使用的一個(gè)注意事項(xiàng)

    最近在工作中發(fā)現(xiàn)了對(duì)于集合操作轉(zhuǎn)換的神器,java8新特性 stream,但在使用中遇到了一個(gè)非常重要的注意點(diǎn),所以這篇文章主要給大家介紹了關(guān)于Java8中S...

    阿杜7482021-02-04
主站蜘蛛池模板: 久久久婷婷一区二区三区不卡 | 色婷婷网 | 午夜精品福利在线观看 | 伊人精品在线 | 精品影院 | 成人在线免费 | 精品国产一区二区三区性色av | 亚洲精品片 | 精品一区二区不卡 | 精品国精品国产自在久不卡 | 亚洲视频一区二区三区 | 精品国产髙清在线看国产毛片 | 久久久久久久国产视频 | 国内毛片毛片 | 欧美成人精品一区 | 国产一区二区三区在线免费 | 精品久久97 | 日韩一区二区三区福利视频 | 色毛片 | 黄色一级网站视频 | 伊人久久在线 | 精品国产一区二区三区久久 | 日本精品一区二区三区在线观看 | 美女久久| 国产午夜精品久久久久久久 | 久久久www成人免费精品 | 久久久亚洲 | 国产在线观看一区二区 | 狠狠人人| 99热在线精品免费 | 亚洲视频免费 | 国产在线a | 亚洲 欧美 精品 | 国产欧美在线 | 美女久久久久 | 亚洲人成网站999久久久综合 | 国产免费一区二区三区 | 天天色av | 中文字幕高清在线播放 | 色www精品视频在线观看 | 黄色影视在线免费观看 |