初識Object
位於Java.lang.Object 中,編譯時會自動導入:
(1)超類,所有類都直接或間接地繼承這個類;
(2)所有對象(包括數組)都實現這個類的方法;
(3)Object 類型的變量,可以裝載任何類型的對象。
Object方法(共11種)
簡單介紹常用的5個方法
(1) public String toString()
return getClass().getName() + “@” + Integer.toHexString(hashCode());
默認返回的是一個類名@對象的hashcode值的十六進制(0~ffffff)
將一個對象轉成一個字符串,建議所有子類重寫該方法
特別說明:
當我們打印一個對象==>System.out.println(Object)的時候,JVM會自動調用這個對象的toString()方法
(2)public final native Class<?> getClass();
==>返回的是Object的運行時類
**(3)protected void finalize() **
在實際中,不是程序員調用,而是JVM幫我們自動調用
這個方法一般在該對象被GC回收之前一刻調用==>臨終遺言
如果你的類不是系統類型,不需要重寫,像FileInputStream等和操作系統底層資源有關係的類型才需要重寫,爲什麼呢?
因爲系統資源往往是和操作系統底層的東西有關,而底層,大多是用C/C++實現,C/C++對象的回收,就需要我們手動回收
特別說明:
每一個對象的finalize()只會調用一次,若在finalize()中,有某句代碼,使得當前對象被重新引用,會使得這個對象復活
那麼等他再次成爲垃圾的時候就會直接被回收,不會再調用這個方法。
面試題final.finalize,finally的區別
finalize()是對象被確認爲垃圾(不再有對該對象的引用時),由垃圾回收器去調用,每個對象調用一次
(4)public int hashCode()
返回對象的哈希碼值
==》每個對象都會有一個數字代表這個對象,理想狀態下是一個對象對應一個哈希值
支持這種方法是爲了散列表,如HashMap提供的那樣 。
規定:
A:如果一個對象的內容沒用改變。在執行Java應用程序時,多次在同一個對象上調用該方法, hashCode方法必須始終返回相同的整數,前提是修改了對象中equals比較中的信息。
B:如果equals(Object)方法兩個對象相等,則在調用hashCode方法必須產生相同的整數結果。
C:如果兩個對象equals(Object)不相等,那麼調用hashCode方法產生不同的整數結果,也可能相同。
equals(Object)不等,hashCode相等的特例如下:
System.out.println("Aa".hashCode());//2112
System.out.println("BB".hashCode());//2112
(但是,程序員應該意識到,爲不等對象生成不同的整數結果會提高哈希表的性能。 )
(5)public boolean equals(Object obj)
- 1:建議子類重寫是,要一起將hashCode也重寫,保證equals()方法兩個對象相等,則在調用hashCode方法必須產生相同的整數結果
- 2:重寫遵循原則:
自反性: x.equals(x) 爲true
對稱的 :x.equals(y) 爲true,則y.equals(x) 爲true(對於任何非空引用值x和y )
傳遞性 :x.equals(y) 爲true,y.equals(z) 爲true,則z.equals(x) 爲true(對於任何非空引用值x和y,z )
一致性 :對於任何非空引用值x和y ,多次調用x.equals(y)始終返回true或始終返回false ,沒有設置中使用的信息equals比較上的對象被修改。
對於任何非空的參考值x , x.equals(null)應該返回false 。
例子:
public static class Student {
private String name;
private int id;
public Student(String name, int id) {
super();
this.name = name;
this.id = id;
}
public Student() {
super();
}
@Override
public String toString() {
return "Student [name=" + name + ", id=" + id + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
//result = prime * result + getEnclosingInstance().hashCode();
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
/*
* s1.equals(s2)
* this ->s1
* obj ->s2
*/
@Override
public boolean equals(Object obj) {
if (this == obj)//地址相同,直接返回
return true;
if (obj == null) //既然能進入到該方法,則表明s1必定不爲空,否則會報空指針異常
//當obj==null,則兩者內容必然不相等
return false;
/*
* 既然能進入到該方法,則表明s1必然爲student類型,而obj可能不是Student類型,因此要獲取obj的運行時類型
*/
if (getClass() != obj.getClass())
return false;
//obj向下轉型,否則,obj爲Object類型,無法訪問到Student的成員變量id,name
//不需要instanceof來判斷obj類型,因爲,如obj不是Student,上一個判斷已經返回false
Student other = (Student) obj;
if (id != other.id)
return false;
if (name == null) {//this.name ==null
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
/*
* 不可以if(name == other.name)
* 因爲這樣就就比較的是對象的地址,而不是內容,
* if(name.equals(other.name))
* 這樣的話,如果name爲空,就會報空指針異常
* equals()的調用者要確保是不爲空的。
*/
return true;
}
}