日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

java.lang包【Object类】

發(fā)布時(shí)間:2023/12/20 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java.lang包【Object类】 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

基本描述:

  (1)Object類位于java.lang包中,java.lang包包含著Java最基礎(chǔ)和核心的類,在編譯時(shí)會(huì)自動(dòng)導(dǎo)入;

  (2)Object類是所有Java類的祖先。每個(gè)類都使用 Object 作為超類。所有對(duì)象(包括數(shù)組)都實(shí)現(xiàn)這個(gè)類的方法。可以使用類型為Object的變量指向任意類型的對(duì)象

Object的主要方法介紹:

package java.lang; public class Object { /* 一個(gè)本地方法,具體是用C(C++)在DLL中實(shí)現(xiàn)的,然后通過JNI調(diào)用。*/ private static native void registerNatives(); /* 對(duì)象初始化時(shí)自動(dòng)調(diào)用此方法*/ static { registerNatives(); } /* 返回此 Object 的運(yùn)行時(shí)類。*/ public final native Class<?> getClass(); public native int hashCode();

hashCode()方法:

hash值:Java中的hashCode方法就是根據(jù)一定的規(guī)則將與對(duì)象相關(guān)的信息(比如對(duì)象的存儲(chǔ)地址,對(duì)象的字段等)映射成一個(gè)數(shù)值,這個(gè)數(shù)值稱作為散列值。

情景:考慮一種情況,當(dāng)向集合中插入對(duì)象時(shí),如何判別在集合中是否已經(jīng)存在該對(duì)象了?(注意:集合中不允許重復(fù)的元素存在)。

大多數(shù)人都會(huì)想到調(diào)用equals方法來逐個(gè)進(jìn)行比較,這個(gè)方法確實(shí)可行。但是如果集合中已經(jīng)存在一萬條數(shù)據(jù)或者更多的數(shù)據(jù),如果采用equals方法去逐一比較,效率必然是一個(gè)問題。此時(shí)hashCode方法的作用就體現(xiàn)出來了,當(dāng)集合要添加新的對(duì)象時(shí),先調(diào)用這個(gè)對(duì)象的hashCode方法,得到對(duì)應(yīng)的hashcode值。實(shí)際上在HashMap的具體實(shí)現(xiàn)中會(huì)用一個(gè)table保存已經(jīng)存進(jìn)去的對(duì)象的hashcode值,如果table中沒有該hashcode值,它就可以直接存進(jìn)去,不用再進(jìn)行任何比較了;如果存在該hashcode值, 就調(diào)用它的equals方法與新元素進(jìn)行比較,相同的話就不存了,不相同就散列其它的地址。

重寫hashCode()方法的基本規(guī)則:

· 在程序運(yùn)行過程中,同一個(gè)對(duì)象多次調(diào)用hashCode()方法應(yīng)該返回相同的值。

·?當(dāng)兩個(gè)對(duì)象通過equals()方法比較返回true時(shí),則兩個(gè)對(duì)象的hashCode()方法返回相等的值。

· 對(duì)象用作equals()方法比較標(biāo)準(zhǔn)的Field,都應(yīng)該用來計(jì)算hashCode值。

Object本地實(shí)現(xiàn)的hashCode()方法計(jì)算的值是底層代碼的實(shí)現(xiàn),采用多種計(jì)算參數(shù),返回的并不一定是對(duì)象的(虛擬)內(nèi)存地址,具體取決于運(yùn)行時(shí)庫(kù)和JVM的具體實(shí)現(xiàn)。

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

equals()方法:比較兩個(gè)對(duì)象是否相等

我們知道所有的對(duì)象都擁有標(biāo)識(shí)(內(nèi)存地址)和狀態(tài)(數(shù)據(jù)),同時(shí)“==”比較兩個(gè)對(duì)象的的內(nèi)存地址,所以說使用Object的equals()方法是比較兩個(gè)對(duì)象的內(nèi)存地址是否相等,即若object1.equals(object2)為true,則表示equals1和equals2實(shí)際上是引用同一個(gè)對(duì)象。雖然有時(shí)候Object的equals()方法可以滿足我們一些基本的要求,但是我們必須要清楚我們很大部分時(shí)間都是進(jìn)行兩個(gè)對(duì)象的比較,這個(gè)時(shí)候Object的equals()方法就不可以了,實(shí)際上JDK中,String、Math等封裝類都對(duì)equals()方法進(jìn)行了重寫。

protected native Object clone() throws CloneNotSupportedException;

?clone()方法:快速創(chuàng)建一個(gè)已有對(duì)象的副本

第一:Object類的clone()方法是一個(gè)native方法,native方法的效率一般來說都是遠(yuǎn)高于Java中的非native方法。這也解釋了為什么要用Object中clone()方法而不是先new一個(gè)類,然后把原始對(duì)象中的信息復(fù)制到新對(duì)象中,雖然這也實(shí)現(xiàn)了clone功能。

第二:Object類中的?clone()方法被protected修飾符修飾。這也意味著如果要應(yīng)用?clone()方?法,必須繼承Object類。

第三:Object.clone()方法返回一個(gè)Object對(duì)象。我們必須進(jìn)行強(qiáng)制類型轉(zhuǎn)換才能得到我們需要的類型。

克隆的步驟:1:創(chuàng)建一個(gè)對(duì)象; ? 2:將原有對(duì)象的數(shù)據(jù)導(dǎo)入到新創(chuàng)建的數(shù)據(jù)中。

clone方法首先會(huì)判對(duì)象是否實(shí)現(xiàn)了Cloneable接口,若無則拋出CloneNotSupportedException, 最后會(huì)調(diào)用internalClone. intervalClone是一個(gè)native方法,一般來說native方法的執(zhí)行效率高于非native方法。

復(fù)制對(duì)象 or 復(fù)制引用

Person p = new Person(23, "zhang"); Person p1 = p; System.out.println(p); System.out.println(p1); 打印出來: com.pansoft.zhangjg.testclone.Person@2f9ee1ac com.pansoft.zhangjg.testclone.Person@2f9ee1ac

 

可已看出,打印的地址值是相同的,既然地址都是相同的,那么肯定是同一個(gè)對(duì)象。p和p1只是引用而已,他們都指向了一個(gè)相同的對(duì)象Person(23, "zhang") 。 可以把這種現(xiàn)象叫做引用的復(fù)制。

Person p = new Person(23, "zhang"); Person p1 = (Person) p.clone(); System.out.println(p); System.out.println(p1); 打印出: com.pansoft.zhangjg.testclone.Person@2f9ee1ac com.pansoft.zhangjg.testclone.Person@67f1fba0

  

從打印結(jié)果可以看出,兩個(gè)對(duì)象的地址是不同的,也就是說創(chuàng)建了新的對(duì)象, 而不是把原對(duì)象的地址賦給了一個(gè)新的引用變量:

深拷貝 or 淺拷貝

public class Person implements Cloneable{ private int age ; private String name; public Person(int age, String name) { this.age = age; this.name = name; } public Person() {} public int getAge() { return age; } public String getName() { return name; } @Override protected Object clone() throws CloneNotSupportedException { return (Person)super.clone(); } } Person中有兩個(gè)成員變量,分別是name和age, name是String類型, age是int類型

由于age是基本數(shù)據(jù)類型, 那么對(duì)它的拷貝沒有什么疑議,直接將一個(gè)4字節(jié)的整數(shù)值拷貝過來就行。但是name是String類型的, 它只是一個(gè)引用, 指向一個(gè)真正的String對(duì)象,那么對(duì)它的拷貝有兩種方式: 直接將源對(duì)象中的name的引用值拷貝給新對(duì)象的name字段, 或者是根據(jù)原Person對(duì)象中的name指向的字符串對(duì)象創(chuàng)建一個(gè)新的相同的字符串對(duì)象,將這個(gè)新字符串對(duì)象的引用賦給新拷貝的Person對(duì)象的name字段。這兩種拷貝方式分別叫做淺拷貝和深拷貝。

通過下面代碼進(jìn)行驗(yàn)證。如果兩個(gè)Person對(duì)象的name的地址值相同, 說明兩個(gè)對(duì)象的name都指向同一個(gè)String對(duì)象, 也就是淺拷貝, 而如果兩個(gè)對(duì)象的name的地址值不同, 那么就說明指向不同的String對(duì)象, 也就是在拷貝Person對(duì)象的時(shí)候, 同時(shí)拷貝了name引用的String對(duì)象, 也就是深拷貝。

Person p = new Person(23, "zhang"); Person p1 = (Person) p.clone(); String result = p.getName() == p1.getName() ? "clone是淺拷貝的" : "clone是深拷貝的"; System.out.println(result); 打印出:clone是淺拷貝的

對(duì)于對(duì)象的淺拷貝和深拷貝還有更深的細(xì)節(jié),可以參考:詳解Java中的clone方法 -- 原型模式

public String toString() {return getClass().getName() + "@" + Integer.toHexString(hashCode()); }

toString()方法:toString?方法會(huì)返回一個(gè)“以文本方式表示”此對(duì)象的字符串。結(jié)果應(yīng)是一個(gè)簡(jiǎn)明但易于讀懂的信息表達(dá)式。建議所有子類都重寫此方法。

?Object?類的?toString?方法返回一個(gè)字符串,該字符串由類名(對(duì)象是該類的一個(gè)實(shí)例)、at 標(biāo)記符“@”和此對(duì)象哈希碼的無符號(hào)十六進(jìn)制表示組成。

?

/*喚醒在此對(duì)象監(jiān)視器上等待的單個(gè)線程。*/ public final native void notify();/*喚醒在此對(duì)象監(jiān)視器上等待的所有線程。*/ public final native void notifyAll();/*在其他線程調(diào)用此對(duì)象的 notify() 方法或 notifyAll() 方法,或者超過指定的時(shí)間量前,導(dǎo)致當(dāng)前線程等待。*/ public final native void wait(long timeout) throws InterruptedException;/* 在其他線程調(diào)用此對(duì)象的 notify() 方法或 notifyAll() 方法,或者其他某個(gè)線程中斷當(dāng)前線程,或者已超過某個(gè)實(shí)際時(shí)間量前,導(dǎo)致當(dāng)前線程等待。*/ public final void wait(long timeout, int nanos) throws InterruptedException {if (timeout < 0) {throw new IllegalArgumentException("timeout value is negative");}if (nanos < 0 || nanos > 999999) {throw new IllegalArgumentException("nanosecond timeout value out of range");}if (nanos >= 500000 || (nanos != 0 && timeout == 0)) {timeout++;}wait(timeout);}/*在其他線程調(diào)用此對(duì)象的 notify() 方法或 notifyAll() 方法前,導(dǎo)致當(dāng)前線程等待。換句話說,此方法的行為就好像它僅執(zhí)行 wait(0) 調(diào)用一樣。 當(dāng)前線程必須擁有此對(duì)象監(jiān)視器。該線程發(fā)布對(duì)此監(jiān)視器的所有權(quán)并等待,直到其他線程通過調(diào)用 notify 方法,或 notifyAll 方法通知在此對(duì)象的監(jiān)視器上等待的線程醒來。然后該線程將等到重新獲得對(duì)監(jiān)視器的所有權(quán)后才能繼續(xù)執(zhí)行。*/ public final void wait() throws InterruptedException {wait(0);}

?

protected void finalize() throws Throwable { }

finalize()方法:垃圾回收器準(zhǔn)備釋放內(nèi)存的時(shí)候,會(huì)先調(diào)用finalize()。

  (1). ?對(duì)象不一定會(huì)被回收。

?????? (2).垃圾回收不是析構(gòu)函數(shù)。

?????? (3).垃圾回收只與內(nèi)存有關(guān)。

?????? (4).垃圾回收和finalize()都是靠不住的,只要JVM還沒有快到耗盡內(nèi)存的地步,它是不會(huì)浪費(fèi)時(shí)間進(jìn)行垃圾回收的。

?

轉(zhuǎn)載于:https://www.cnblogs.com/myseries/p/7435395.html

總結(jié)

以上是生活随笔為你收集整理的java.lang包【Object类】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。