程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java中斷定對象能否相等的equals()辦法應用教程

Java中斷定對象能否相等的equals()辦法應用教程

編輯:關於JAVA

Java中斷定對象能否相等的equals()辦法應用教程。本站提示廣大學習愛好者:(Java中斷定對象能否相等的equals()辦法應用教程)文章只能為提供參考,不一定能成為您想要的結果。以下是Java中斷定對象能否相等的equals()辦法應用教程正文


Object類中的equals辦法用於檢測一個對象能否等於另外一個對象。在Object類中,這個辦法斷定兩個對象能否具有雷同的援用,假如兩個對象具有雷同的援用,它們必定是相等的。從這點上看,將其作為默許操作也是符合道理的。但是,關於多半類類說,這類斷定並沒有甚麼意義,例如,采取這類方法比擬兩個PrintStream能否相等就完整沒成心義。但是,常常須要檢測兩個對象狀況的相等性,假如兩個對象的狀況相等,就以為這兩個對象是相等的。所以普通在自界說類中都要重寫equals比擬。

上面給出編寫一個完善equals()辦法的建議:

(1)顯式參數定名為otherObject,稍後須要將轉換成一個叫other的變量

(2)檢測this與otherObject能否援用統一個對象:

if(this==otherObject) return true;

這條語句只是一個優化。現實上,這是一種常常采取的情勢。由於盤算這個等式要比一個一個地比擬類中的域所支付的價值小的多。

(3)檢測otherObject能否為null,假如為null,前往false。這項檢測是很需要的。

if(otherObject==null) return false;

(4)比擬this和otherObject能否屬於統一個類,假如equals的語義在每一個子類中有所轉變,就應用getClass()檢測,它將本身作為目的類

if(getClass()!=otherObject.getClass()) return false;

假如一切的子類都具有統一的語義,就應用instanceof檢測

if(!(otherObject instanceof ClassName)) return false;

(5)將otherObject轉換為響應類型的變量:

ClassName other=(ClassName)otherObject;

(6)如今開端對一切須要比擬的域停止比擬。應用==比擬根本類型域,應用equals比擬對象域。假如一切域都婚配,就前往true,不然前往false;

return field1==other.field1&&field2.equals(other.field2)

假如在子類中從新界說equals,就要在個中包括挪用super.equals(other)。假如檢測掉敗,就弗成能相等。假如超類中的域相等,就比擬子類中的實例域。

關於數組類型的域,可使用靜態的Arrays.equals辦法檢測響應的元素能否相等。

來看幾個字符串比擬例子:

String a = "abc"; 
String b = "abc"; 
String c = new String("abc"); 
String d = new String("abc"); 
System.out.println(a == b); // true 由於JAVA中字符串常量是同享的,只要一個拷貝 
System.out.println(a == c); // false a和c屬於2個分歧的對象 
System.out.println(a.equals(c)); // true 因為String對象的equals辦法比擬的是對象中的值,所以前往true。(和Object的equals辦法分歧) 
System.out.println(c==d); // false c和d固然對象內的值雷同,但屬於2個分歧的對象,所以不相等 
System.out.println(c.equals(d)); // true 

簡略的說,當比擬字符串常量時,等於和equals前往的成果一樣,當想比擬字符串對象的值時用equals。

看一個equals的應用例子:

package chapter05.EqualsTest; 
 
import java.util.*; 
 
public class EqualsTest { 
 public static void main(String[] args) { 
  Employee alice1 = new Employee("Alice Adams", 75000, 1987, 12, 15); 
  Employee alice2 = alice1; // reference the same object 
  Employee alice3 = new Employee("Alice Adams", 75000, 1987, 12, 15); 
  Employee bob = new Employee("Bob Brandson", 50000, 1989, 10, 1); 
 
  System.out.println("alice1 == alice2: " + (alice1 == alice2)); 
 
  System.out.println("alice1 == alice3: " + (alice1 == alice3)); 
 
  System.out.println("alice1.equals(alice3): " + (alice1.equals(alice3))); 
 
  System.out.println("alice1.equals(bob): " + (alice1.equals(bob))); 
 
  System.out.println(bob.toString()); 
 } 
} 
 
class Employee { 
 public Employee(String n, double s, int year, int month, int day) { 
  name = n; 
  salary = s; 
  GregorianCalendar calendar = new GregorianCalendar(year, month, day); 
  hireDay = calendar.getTime(); 
 } 
 
 public String getName() { 
  return name; 
 } 
 
 public double getSalary() { 
  return salary; 
 } 
 
 public Date getHireDay() { 
  return hireDay; 
 } 
 
 public void raiseSalary(double byPercent) { 
  double raise = salary * byPercent / 100; 
  salary += raise; 
 } 
 
 @Override 
 public boolean equals(Object otherObject) { 
  // a quick test to see if the objects are identical 
  if (this == otherObject) 
   return true; 
 
  // must return false if the explicit parameter is null 
  if (otherObject == null) 
   return false; 
 
  // if the classed don't match,they can't be equal 
  if (getClass() != otherObject.getClass()) 
   return false; 
 
  // now we know otherObject is a non-null Employee 
  Employee other = (Employee) otherObject; 
 
  // test whether the fields hava identical values 
  return name.equals(other.name) && salary == other.salary 
    && hireDay.equals(other.hireDay); 
 
 } 
 
 @Override 
 public int hashCode() { 
  return 7 * name.hashCode() + 11 * new Double(salary).hashCode() + 13 
    * hireDay.hashCode(); 
 } 
 
 @Override 
 public String toString() { 
  return getClass().getName() + "[name=" + name + ",salary=" + salary 
    + ",hireDay=" + hireDay + "]"; 
 } 
 
 private String name; 
 private double salary; 
 private Date hireDay; 
} 
 
class Manager extends Employee { 
 public Manager(String n, double s, int year, int month, int day) { 
  super(n, s, year, month, day); 
  bouns = 0; 
 } 
 
 @Override 
 public double getSalary() { 
  double baseSalary = super.getSalary(); 
  return baseSalary + bouns; 
 } 
 
 public void setBouns(double b) { 
  bouns = b; 
 } 
 
 @Override 
 public boolean equals(Object otherObject) { 
  if (!super.equals(otherObject)) 
   return false; 
  Manager other = (Manager) otherObject; 
  // super equals checked that this and other belong to the same class 
  return bouns == other.bouns; 
 } 
 
 @Override 
 public int hashCode() { 
  return super.hashCode() + 17 * new Double(bouns).hashCode(); 
 } 
 
 @Override 
 public String toString() { 
  return super.toString() + "[bouns=" + bouns + "]"; 
 } 
 
 private double bouns; 
} 

深刻
上面依據“類能否籠罩equals()辦法”,將它分為2類。
(1) 若某個類沒有籠罩equals()辦法,當它的經由過程equals()比擬兩個對象時,現實上是比擬兩個對象是否是統一個對象。這時候,等價於經由過程“==”去比擬這兩個對象。
(2) 我們可以籠罩類的equals()辦法,來讓equals()經由過程其它方法比擬兩個對象能否相等。平日的做法是:若兩個對象的內容相等,則equals()辦法前往true;不然,前往fasle。
上面,舉例對下面的2種情形停止解釋。
1. “沒有籠罩equals()辦法”的情形
代碼以下 (EqualsTest1.java):

import java.util.*;
import java.lang.Comparable;

/**
 * @desc equals()的測試法式。

 */
public class EqualsTest1{

 public static void main(String[] args) {
  // 新建2個雷同內容的Person對象,
  // 再用equals比擬它們能否相等
  Person p1 = new Person("eee", 100);
  Person p2 = new Person("eee", 100);
  System.out.printf("%s\n", p1.equals(p2));
 }

 /**
  * @desc Person類。
  */
 private static class Person {
  int age;
  String name;

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

  public String toString() {
   return name + " - " +age;
  }
 }
}

運轉成果:
false
成果剖析
我們經由過程 p1.equals(p2) 來“比擬p1和p2能否相等時”。現實上,挪用的Object.java的equals()辦法,即挪用的 (p1==p2) 。它是比擬“p1和p2能否是統一個對象”。
而由 p1 和 p2 的界說可知,它們固然內容雷同;但它們是兩個分歧的對象!是以,前往成果是false。

2. "籠罩equals()辦法"的情形
我們修正下面的EqualsTest1.java:籠罩equals()辦法。
代碼以下 (EqualsTest2.java):

import java.util.*;
import java.lang.Comparable;

/**
 * @desc equals()的測試法式。
 */
public class EqualsTest2{

 public static void main(String[] args) {
  // 新建2個雷同內容的Person對象,
  // 再用equals比擬它們能否相等
  Person p1 = new Person("eee", 100);
  Person p2 = new Person("eee", 100);
  System.out.printf("%s\n", p1.equals(p2));
 }

 /**
  * @desc Person類。
  */
 private static class Person {
  int age;
  String name;

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

  public String toString() {
   return name + " - " +age;
  }

  /** 
   * @desc 籠罩equals辦法 
   */ 
  @Override
  public boolean equals(Object obj){ 
   if(obj == null){ 
    return false; 
   } 

   //假如是統一個對象前往true,反之前往false 
   if(this == obj){ 
    return true; 
   } 

   //斷定能否類型雷同 
   if(this.getClass() != obj.getClass()){ 
    return false; 
   } 

   Person person = (Person)obj; 
   return name.equals(person.name) && age==person.age; 
  } 
 }
}

運轉成果:
true
成果剖析:
我們在EqualsTest2.java 中重寫了Person的equals()函數:當兩個Person對象的 name 和 age 都相等,則前往true。
是以,運轉成果前往true。
講到這裡,趁便說一下java對equals()的請求。有以下幾點:
對稱性:假如x.equals(y)前往是"true",那末y.equals(x)也應當前往是"true"。
反射性:x.equals(x)必需前往是"true"。
類推性:假如x.equals(y)前往是"true",並且y.equals(z)前往是"true",那末z.equals(x)也應當前往是"true"。
分歧性:假如x.equals(y)前往是"true",只需x和y內容一向不變,不論你反復x.equals(y)若干次,前往都是"true"。
非空性,x.equals(null),永久前往是"false";x.equals(和x分歧類型的對象)永久前往是"false"。
如今,再回想一下equals()的感化:斷定兩個對象能否相等。當我們重寫equals()的時刻,可萬萬欠好將它的感化給轉變了!


equals() 與 == 的差別是甚麼?
== : 它的感化是斷定兩個對象的地址是否是相等。即,斷定兩個對象是否是統一個對象。
equals() : 它的感化也是斷定兩個對象能否相等。但它普通有兩種應用情形(後面第1部門已具體引見過):
     情形1,類沒有籠罩equals()辦法。則經由過程equals()比擬該類的兩個對象時,等價於經由過程“==”比擬這兩個對象。
     情形2,類籠罩了equals()辦法。普通,我們都籠罩equals()辦法來兩個對象的內容相等;若它們的內容相等,則前往true(即,以為這兩個對象相等)。
上面,經由過程示例比擬它們的差別。
代碼以下:

import java.util.*;
import java.lang.Comparable;

/**
 * @desc equals()的測試法式。
 */
public class EqualsTest3{

 public static void main(String[] args) {
  // 新建2個雷同內容的Person對象,
  // 再用equals比擬它們能否相等
  Person p1 = new Person("eee", 100);
  Person p2 = new Person("eee", 100);
  System.out.printf("p1.equals(p2) : %s\n", p1.equals(p2));
  System.out.printf("p1==p2 : %s\n", p1==p2);
 }

 /**
  * @desc Person類。
  */
 private static class Person {
  int age;
  String name;

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

  public String toString() {
   return name + " - " +age;
  }

  /** 
   * @desc 籠罩equals辦法 
   */ 
  @Override
  public boolean equals(Object obj){ 
   if(obj == null){ 
    return false; 
   } 

   //假如是統一個對象前往true,反之前往false 
   if(this == obj){ 
    return true; 
   } 

   //斷定能否類型雷同 
   if(this.getClass() != obj.getClass()){ 
    return false; 
   } 

   Person person = (Person)obj; 
   return name.equals(person.name) && age==person.age; 
  } 
 }
}

運轉成果:

p1.equals(p2) : true
p1==p2 : false

成果剖析:
在EqualsTest3.java 中:
(1) p1.equals(p2)
這是斷定p1和p2的內容能否相等。由於Person籠罩equals()辦法,而這個equals()是用來斷定p1和p2的內容能否相等,恰好p1和p2的內容又相等;是以,前往true。
(2) p1==p2
這是斷定p1和p2能否是統一個對象。因為它們是各改過建的兩個Person對象;是以,前往false。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved