­

面試官:對象可能會遲到,但它永遠不會缺席

問題一:簡單聊一下關於你對Object的理解

在 Java 中,只有基本數據類型不是對象,比如,數值,布爾和字元類型的值都不是對象。而其餘的數據類型都是繼承自一個名為Object的類,這個類是所有類的始祖,每個類都是由Object類擴展而來。

如果一個類繼承自Object類,我們可以將extends Object給省略掉,如果在一個類的定義中沒有明確的指出哪個是它的父類,那麼Object類就認為是這個類的父類。

=
=

問題二:Object類中有一個registerNatives方法,對此你了解多少?

從方法的命名上我們就可以看出,該方法是用於註冊本地(native)方法,主要是為了服務於JNI的,它主要是提供了 java 類中的方法與對應 C++ 程式碼中的方法的映射,方便jvm去查找調用 C++ 中的方法。

img
img

問題三:Object類中有clone方法,聊聊你對這個方法的認識

clone方法是Object類的一個protected的方法,我們可以這樣去應用這個方法

  1. 實現Cloneable介面

  2. 重寫clone方法,並指定public修飾符。

問題四:為什麼我們一定要去實現Cloneable介面,而不是直接去重寫這個方法呢?

我們通過源碼可以發現這是一個空的介面,clone是從Object類繼承的。這個介面只是作為一個標記,指示類設計者了解克隆繼承。對象對於克隆也很”偏執”,如果一個對象請求克隆,但沒有實現這個介面,就會生成一個異常。

在 Java 中,Cloneable這樣的介面叫做標記介面,標記介面不包括任何方法,它的唯一作用就是允許在類型查詢的時候使用instanceof

  • ounter(line
  • ounter(line
  • ounter(line
if (obj instanceof Cloneable){    //TODO}

問題五:說一說你對關於深克隆和淺克隆的認識

首先來說一下Object類是如何實現clone,它對這個對象一無所知,所以只能逐個域的進行拷貝。如果對象中的所有數據域都是數值或其他基本類型,拷貝這些域沒有任何問題,但是如果對象中包含子對象的引用,拷貝域就會得到相同子對象的另一個引用,這樣一來,原對象和克隆對象仍然會去共享一些資訊。這種Object類默認實現的clone方法稱為淺拷貝(Shallow Clone)。

這裡需要注意,關於淺克隆的安全性,如果原對象和淺克隆對象共享的子對象是不可變的,那麼這種共享就是安全的。如果子對象屬於一個不可變的類,如String,就是這種情況。或者在對象的生命期中,子對象一直包含不變的常量 ,沒有更改器方法會改變它,也沒有方法會生成它的引用,這種情況同樣是安全的。

不過子類對象通常是可變的,這時我們就需要定義深拷貝(Deep Clone),來克隆這個類的所有子對象。

具體實現方法如下:

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
public Test clone() throws CloneNotSupportedException{     //拷貝該對象    Test cloned = (Test)super.clone();     //拷貝該對象中的可變域    cloned.time = (Date) time.clone();    return cloned;}

這裡需要提到的一點是:

雖然我們已經學習了clone的兩種用法,但是在實際的編碼中還是盡量少用這個方法,它具有天生的不穩定性,僅僅了解即可。即使是Java的標準庫中也只有5%的類實現了這個方法。

我們可以使用Java的對象串列化特性來實現克隆對象,雖然效率不高,但是很安全,而且很容易實現。

問題六: 關於equals方法,說說是什麼?

Object類中的equals方法用於檢測一個對象是否等於另一個對象。在Object類中,這個方法將判斷兩個對象是否具有相同的引用。如果兩個對象具有相同的引用,它們一定是相等的。

問題七:有沒有自己去重寫過equals方法呢?

當然,這個我有筆記~

問題八:不限於Object,聊聊hashCode

在Java中,hash code是由對象導出的一個整型值,以下是幾個常見哈希值的演算法:

  1. Object類的hashCode()。返回對象的記憶體地址經過處理後的結構,由於每個對象的記憶體地址都不一樣,所以哈希碼也不一樣。

  2. String類的hashCode()。根據String類包含的字元串的內容,根據一種特殊演算法返回哈希碼,只要字元串所在的堆空間相同,返回的哈希碼也相同。

  3. Integer類,返回的哈希碼就是Integer對象里所包含的那個整數的數值,例如Integer i1=new Integer(100),i1.hashCode的值就是100 。由此可見,2個一樣大小的Integer對象,返回的哈希碼也一樣。

問題九:說說EqualsHashcode的關係

這兩個其實確切意義上並沒有什麼聯繫,前提是我們不會在HashSet,HashMap這種本質是散列表的數據結構中使用,如果我們要在HashSet,HashMap這種本質是散列表的數據結構中使用,在重寫equals方法的同時也要重寫hashCode方法,以便用戶將對象插入到散列表中,否則會導致數據不唯一,記憶體泄漏等各種問題。

1.hashCode是為了提高在散列結構存儲中查找的效率,在線性表中沒有作用。

2.equals()hashCode()需要同時覆蓋,而且定義必須一致,也就是說equals比較了哪些域,hashCode就會對哪些域進行hash值的處理。

3.若兩個對象equals()返回true,則hashCode()有必要也返回相同的值。

4.若兩個對象equals()返回false,則hashCode()不一定返回不同的值。

5.若兩個對象hashCode()返回相同的值,則equals()不一定返回true。

6.若兩個對象hashCode()返回不同值,則equals()一定返回false。

7.同一對象在執行期間若已經存儲在集合中,則不能修改影響hashCode值的相關資訊,否則會導致記憶體泄露問題。