Java中Object類(lèi)的理解和使用
如何理解根父類(lèi)
類(lèi)java.lang.Object是類(lèi)層次結(jié)構(gòu)的根類(lèi),即所有其它類(lèi)的父類(lèi)。每個(gè)類(lèi)都使用Object作為超類(lèi)。

- Object類(lèi)型的變量與除Object以外的任意引用數(shù)據(jù)類(lèi)型的對(duì)象都存在多態(tài)引用
method(Object obj){…} //可以接收任何類(lèi)作為其參數(shù)
Person o = new Person();
method(o);- 所有對(duì)象(包括數(shù)組)都實(shí)現(xiàn)這個(gè)類(lèi)的方法
- 一個(gè)類(lèi)沒(méi)有特別指定父類(lèi),那么默認(rèn)則繼承自O(shè)bject類(lèi)
public class Person {
...
}
//上面和下面是等價(jià)的
public class Person extends Object {
...
}Object類(lèi)的方法
根據(jù)JDK源代碼及Object類(lèi)的API文檔,Object類(lèi)中包含的方法有11個(gè),但是今天只看其中主要的5個(gè)。
equals()
所有類(lèi)都繼承了Object,那么也就獲得了equals()方法,且還可以重寫(xiě)方法。 equals():
- 只能比較引用類(lèi)型,比較是否指向同一個(gè)對(duì)象
- 格式:
obj1.equals(obj2) - 特例:當(dāng)用equals()方法進(jìn)行比較時(shí),對(duì)類(lèi)File、String、Date及包裝類(lèi)來(lái)說(shuō),是比較類(lèi)型及內(nèi)容而不考慮引用的是否是同一個(gè)對(duì)象,因?yàn)樵谶@些類(lèi)中重寫(xiě)了Object類(lèi)的equals()方法
- 當(dāng)自定義equals()方法時(shí),可以重寫(xiě)方法,用來(lái)比較兩個(gè)對(duì)象的內(nèi)容是否一樣
重寫(xiě)equals()方法的原則:
- 對(duì)稱(chēng)性:如果x.equals(y)返回是true,那么y.equals(x)也應(yīng)該返回是true
- 自反性:x.equals(x)必須返回是true
- 傳遞性:如果x.equals(y)返回是true,且y.equals(z)返回是true,那么z.equals(x)也應(yīng)該返回true
- 一致性:如果x.equals(y)返回是true,只要x和y內(nèi)容不變,無(wú)論重復(fù)x.equals(y)多少次,都是返回true
- 任何情況下,x.equals(null)都是返回false,x.equals(和x是不同類(lèi)型的對(duì)象)都是返回false
重寫(xiě)舉例:
class User{
private String host;
private String username;
private String password;
public User(String host, String username, String password) {
super();
this.host = host;
this.username = username;
this.password = password;
}
public User() {
super();
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User [host=" + host + ", username=" + username + ", password=" + password + "]";
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (host == null) {
if (other.host != null)
return false;
} else if (!host.equals(other.host))
return false;
if (password == null) {
if (other.password != null)
return false;
} else if (!password.equals(other.password))
return false;
if (username == null) {
if (other.username != null)
return false;
} else if (!username.equals(other.username))
return false;
return true;
}
}= =:
- 基本類(lèi)型比較的是值:只要兩個(gè)變量的值相等,即為true
- 引用類(lèi)型比較引用(是否指向同一個(gè)對(duì)象):只有指向同一個(gè)對(duì)象時(shí),才返回true
注意: 用來(lái)進(jìn)行比較時(shí),符號(hào)兩邊的數(shù)據(jù)類(lèi)型必須兼容(可自動(dòng)轉(zhuǎn)換的基本數(shù)據(jù)類(lèi)型除外),否則編譯報(bào)錯(cuò)。
= =和equals的區(qū)別:
- = =即可以比較基本數(shù)據(jù)類(lèi)型也可以比較引用類(lèi)型,對(duì)于基本類(lèi)型就是比較數(shù)值,對(duì)于引用類(lèi)型就是比較內(nèi)存地址
- equals是屬于java.lang.Object類(lèi)里面的方法,如果該方法沒(méi)有被重寫(xiě),默認(rèn)也是= =,String等類(lèi)的equals方法是被重寫(xiě)過(guò)的,而且String類(lèi)在日常開(kāi)發(fā)中用的較多,形成了equals是比較值的錯(cuò)誤觀點(diǎn),這點(diǎn)要注意
- 具體要看自定義類(lèi)型里有沒(méi)有重寫(xiě)Object的equals方法來(lái)判斷
- 通常情況下,重寫(xiě)equals方法,會(huì)比較類(lèi)中的相應(yīng)屬性是否都相等
toString()
public String toString():默認(rèn)情況下toString()返回的是對(duì)象的運(yùn)行時(shí)類(lèi)型@對(duì)象的hashCode值的十六進(jìn)制形式。
在進(jìn)行String與其他類(lèi)型數(shù)據(jù)的連接操作時(shí),自動(dòng)調(diào)用toString方法,比如:
Date now=new Date();
System.out.println("now="+now); //相當(dāng)于"now="+now.toString()如果直接打印對(duì)象,默認(rèn)會(huì)調(diào)用該對(duì)象的toString()方法(Java的引用數(shù)據(jù)類(lèi)型的變量中存儲(chǔ)的實(shí)際上是對(duì)象的內(nèi)存地址,但是Java對(duì)外隱藏了內(nèi)存地址信息,所以不能直接將內(nèi)存地址顯示出來(lái),所以當(dāng)打印對(duì)象時(shí),JVM會(huì)調(diào)用對(duì)象的toString()方法)。
可以根據(jù)需要在用戶(hù)自定義類(lèi)型中重寫(xiě)toString()方法。
getClass()
public final Class<?> getClass():獲取對(duì)象的運(yùn)行時(shí)類(lèi)型。
由于Java有多態(tài)現(xiàn)象,所以一個(gè)引用數(shù)據(jù)類(lèi)型的變量編譯時(shí)類(lèi)型與運(yùn)行時(shí)類(lèi)型可能不一致,因此如果需要查看這個(gè)變量實(shí)際指向的對(duì)象的類(lèi)型,就需要用getClass()方法。
public static void main(String[] args) {
Object obj = new Person();
System.out.println(obj.getClass()); //獲取運(yùn)行時(shí)類(lèi)型
}hashCode()
public int hashCode():返回每個(gè)對(duì)象的hash值。
如果重寫(xiě)equals,那么通常會(huì)一起重寫(xiě)hashCode()方法,hashCode()方法主要是為了當(dāng)對(duì)象存儲(chǔ)到哈希表等容器中時(shí)提高存儲(chǔ)和查詢(xún)性能用的,這是因?yàn)殛P(guān)于hashCode()有兩個(gè)常規(guī)協(xié)定:
- 如果兩個(gè)對(duì)象的hash值不同,那么這兩個(gè)對(duì)象一定不相等
- 如果兩個(gè)對(duì)象的hash值是相同的,那么這兩個(gè)對(duì)象不一定相等
重寫(xiě)equals()和hashCode()方法時(shí),要保證滿(mǎn)足如下要求:
- 如果兩個(gè)對(duì)象調(diào)用equals返回true,那么要求這兩個(gè)對(duì)象的hashCode值一定是相等的
- 如果兩個(gè)對(duì)象的hashCode值不同,那么要求這兩個(gè)對(duì)象調(diào)用equals方法一定是false
- 如果兩個(gè)對(duì)象的hashCode值相同,那么這兩個(gè)對(duì)象調(diào)用equals可能是true,也可能是false
public static void main(String[] args) {
System.out.println("Aa".hashCode()); //2112
System.out.println("BB".hashCode()); //2112
}clone()
clone()方法將對(duì)象復(fù)制了一份并返回給調(diào)用者,clone()的作用在于復(fù)制對(duì)象,在復(fù)制對(duì)象的過(guò)程中,首先要分配一個(gè)和源對(duì)象同樣大小的空間,在這個(gè)空間中創(chuàng)建一個(gè)新的對(duì)象。
示例:
public class CloneTest {
public static void main(String[] args) {
Animal a1 = new Animal("小黑");
try {
Animal a2 = (Animal) a1.clone();
System.out.println("原始對(duì)象:" + a1);
a2.setName("小黃");
System.out.println("clone的對(duì)象:" + a2);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
class Animal implements Cloneable{
private String name;
public Animal() {
super();
}
public Animal(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Animal [name=" + name + "]";
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}finalize()
當(dāng)對(duì)象被回收時(shí),系統(tǒng)自動(dòng)調(diào)用該對(duì)象的finalize()方法,子類(lèi)可以重寫(xiě)該方法,做一些釋放資源的操作。如果重寫(xiě)該方法,讓一個(gè)新的引用變量重新引用該對(duì)象,則會(huì)重新激活對(duì)象。
永遠(yuǎn)不要主動(dòng)調(diào)用某個(gè)對(duì)象的finalize方法,應(yīng)該交給垃圾回收機(jī)制調(diào)用。
什么時(shí)候被回收:
當(dāng)某個(gè)對(duì)象沒(méi)有任何引用時(shí),JVM就認(rèn)為這個(gè)對(duì)象是垃圾對(duì)象,就會(huì)在之后不確定的時(shí)間使用垃圾回收機(jī)制來(lái)銷(xiāo)毀該對(duì)象,在銷(xiāo)毀該對(duì)象前,會(huì)先調(diào)用finalize()方法(垃圾回收發(fā)生具有不可預(yù)知性,程序無(wú)法精確控制垃圾回收機(jī)制的執(zhí)行)。
垃圾回收機(jī)制的調(diào)用是由系統(tǒng)來(lái)決定的,也可以通過(guò)System.gc()或者Runtime.getRuntime().gc()來(lái)通知系統(tǒng)進(jìn)行垃圾回收,會(huì)有一些效果,但是系統(tǒng)是否進(jìn)行垃圾回收依然是不確定的。
public class FinalizeTest {
public static void main(String[] args) {
Person p = new Person("Peter", 12);
System.out.println(p);
p = null; //此時(shí)對(duì)象實(shí)體就是垃圾對(duì)象,等待被回收,但時(shí)間不確定
System.gc();//強(qiáng)制性釋放空間
}
}
class Person{
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//子類(lèi)重寫(xiě)此方法,可在釋放對(duì)象前進(jìn)行某些操作
@Override
protected void finalize() throws Throwable {
System.out.println("對(duì)象被釋放--->" + this);
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}native關(guān)鍵字的理解
使用native關(guān)鍵字說(shuō)明這個(gè)方法是原生函數(shù),也就是這個(gè)方法是用c/c++等非Java語(yǔ)言實(shí)現(xiàn)的,并且被編譯成了dll,由Java去調(diào)用,在定義一個(gè)native方法時(shí),并不提供實(shí)現(xiàn)體。
為什么要用native方法
雖然Java使用起來(lái)非常方便,然而有些層次的任務(wù)用Java實(shí)現(xiàn)起來(lái)不易,或?qū)Τ绦虻男屎茉谝鈺r(shí)就會(huì)考慮native方法。
例如:有時(shí)Java應(yīng)用需要與Java外面的環(huán)境交互,這是本地方法存在的主要原因,當(dāng)Java需要與一些底層系統(tǒng)如操作系統(tǒng)或某些硬件交換信息時(shí)的情況,本地方法正是這樣的一種交流機(jī)制,它提供了一個(gè)非常簡(jiǎn)潔的接口,而且無(wú)需我們?nèi)チ私釰ava應(yīng)用之外的繁瑣細(xì)節(jié)。
native聲明的方法,對(duì)于調(diào)用者可以當(dāng)做其他Java方法一樣使用
一個(gè)native方法可以返回任何Java類(lèi)型,包括非基本類(lèi)型,而且同樣可以進(jìn)行異??刂?。
native方法的存在并不會(huì)對(duì)其他類(lèi)調(diào)用這些本地方法產(chǎn)生任何的影響,實(shí)際上調(diào)用這些方法的其他類(lèi)甚至不知道它調(diào)用的是一個(gè)本地方法,JVM將控制調(diào)用本地方法的所有細(xì)節(jié)。
如果一個(gè)含有本地方法的類(lèi)被繼承,子類(lèi)會(huì)繼承這個(gè)本地方法并且可以用Java在需要的時(shí)候重寫(xiě)該方法。
以上就是Java中Object類(lèi)的理解和使用的詳細(xì)內(nèi)容,更多關(guān)于Java Object類(lèi)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JAVA JDK8 List分組獲取第一個(gè)元素的方法
今天小編就為大家分享一篇關(guān)于JAVA JDK8 List分組獲取第一個(gè)元素的方法,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12
Java?spring?boot實(shí)現(xiàn)批量刪除功能詳細(xì)示例
這篇文章主要給大家介紹了關(guān)于Java?spring?boot實(shí)現(xiàn)批量刪除功能的相關(guān)資料,文中通過(guò)代碼以及圖文將實(shí)現(xiàn)的方法介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-08-08
jdbc連接數(shù)據(jù)庫(kù)實(shí)例詳解
在本篇內(nèi)容里小編給大家分享了關(guān)于jdbc如何連接數(shù)據(jù)庫(kù)的相關(guān)知識(shí)點(diǎn)內(nèi)容,需要的朋友們學(xué)習(xí)下。2019-02-02
使用sharding-jdbc實(shí)現(xiàn)水平分表的示例代碼
本文主要介紹了sharding-jdbc實(shí)現(xiàn)水平分表,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11
SpringBoot參數(shù)校驗(yàn)之@Validated的使用詳解
這篇文章主要通過(guò)示例為大家詳細(xì)介紹一下介紹了SpringBoot參數(shù)校驗(yàn)中@Validated的使用方法,文中的示例代碼講解詳細(xì),需要的可以參考一下2022-06-06
MyBatis-Plus自定義SQL的詳細(xì)過(guò)程記錄
Java開(kāi)發(fā)使用mybatis-plus來(lái)執(zhí)行sql操作,往往比mybatis能夠省時(shí)省力,下面這篇文章主要給大家介紹了關(guān)于MyBatis-Plus自定義SQL的相關(guān)資料,需要的朋友可以參考下2022-02-02
利用JDBC的PrepareStatement打印真實(shí)SQL的方法詳解
PreparedStatement是預(yù)編譯的,對(duì)于批量處理可以大大提高效率. 也叫JDBC存儲(chǔ)過(guò)程,下面這篇文章主要給大家介紹了關(guān)于利用JDBC的PrepareStatement打印真實(shí)SQL的方法,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-07-07
java連接mysql數(shù)據(jù)庫(kù)實(shí)現(xiàn)單條插入和批量插入
這篇文章主要為大家詳細(xì)介紹了java連接mysql數(shù)據(jù)庫(kù)實(shí)現(xiàn)單條插入和批量插入,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08

