JAVA研發面試題(基礎)
JAVA基礎(目錄): Object類的方法,逐個解釋一下(clone,hashCode,equals,wait,finalize,notify) Java的Exception類型 Integer和int有啥差別,integer中有哪些特殊的函數? 說一下String實作 intern final 關鍵字 序列化,遠端方法調用
Object類的方法
public class Object {
private static native void registerNatives();
static {
registerNatives();
}
public final native Class<?> getClass();
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
protected native Object clone() throws CloneNotSupportedException;
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
public final native void notify();
public final native void notifyAll();
public final native void wait(long timeout) throws InterruptedException;
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 > 0) {
timeout++;
}
wait(timeout);
}
public final void wait() throws InterruptedException {
wait(0);
}
protected void finalize() throws Throwable { }
}
隻有繼承了Object類的對象
clone–native方法/可以重寫
protected native Object clone() throws CloneNotSupportedException;
基本資料類型(八種:byte-1個位元組、short-2個位元組、int-4個位元組、long-8個位元組、float-4個位元組、double-8個位元組、boolean-4個位元組/數組1個位元組、char-2個位元組)
boolean 4個位元組理由來源是《Java虛拟機規範》一書中的描述:“雖然定義了boolean這種資料類型,但是隻對它提供了非常有限的支援。在Java虛拟機中沒有任何供boolean值專用的位元組碼指令,Java語言表達式所操作的boolean值,在編譯之後都使用Java虛拟機中的int資料類型來代替,而boolean數組将會被編碼成Java虛拟機的byte數組,每個元素boolean元素占8位”。這樣我們可以得出boolean類型占了單獨使用是4個位元組,在數組中又是1個位元組。顯然第三條是更準确的說法,那虛拟機為什麼要用int來代替boolean呢?為什麼不用byte或short,這樣不是更節省記憶體空間嗎。大多數人都會很自然的這樣去想,我同樣也有這個疑問,經過查閱資料發現,使用int的原因是,對于當下32位的處理器(CPU)來說,一次處理資料是32位(這裡不是指的是32/64位系統,而是指CPU硬體層面),具有高效存取的特點。 (本段話來自https://www.jianshu.com/p/2f663dc820d0)
/*
需要實作Cloneable接口,否則抛出異常:
Exception in thread "main" java.lang.NullPointerException
*/
public class ObjectCloneTest implements Cloneable{
int a = 0;
int[] b = {0,1,2,3};
public static void main(String [] args){
ObjectCloneTest obj = new ObjectCloneTest();
ObjectCloneTest oo=null;
try {
oo = (ObjectCloneTest)obj.clone();
}catch(CloneNotSupportedException e){
System.out.println("clone出錯" + e.getMessage());
}
obj.a = 1;
obj.b = new int[]{01,11,21,31};
System.out.println(" 基本資料類型 " + oo.a +" clone的是值 "+ obj.a);
System.out.println(" 引用資料類型 " + oo.b +" clone的是位址--對象的引用 "+ obj.b);
int a=0;
//a.clone();基本資料類型沒有object的方法
int[] aa = new int[]{0,0,0};
int[] bb = aa.clone();
System.out.println("數組 " + aa.toString() + " clone的是值而不是引用 " + bb.toString());
aa[1] = 2;
System.out.println("原數組變化 " + aa[1] + " clone數組不變 " + bb[1]);
}
}
輸出:
基本資料類型 0 clone的是值 1
引用資料類型 [[email protected] clone的是位址--對象的引用 [[email protected]
數組 [[email protected] clone的是值而不是引用 [[email protected]
原數組變化 2 clone數組不變 0
淺複制:對于基本資料類型來說,淺複制和深複制效果相同,都是複制的值,對于引用資料類型,object預設方法就是淺複制,即複制的是引用對象的位址。
深複制:對于引用資料類型,深複制要實作将每個引用類型裡面的各個基本類型都複制一遍,即深入到每個屬性裡面的基本類型都拷貝一遍。我們可以重寫對象的clone方法,以實作引用對象的深複制。
@Override
protected Object clone() throws CloneNotSupportedException {
ObjectCloneTest ooo = new ObjectCloneTest();
ooo.a = this.a;
int [] b = new int [this.b.length];
for(int i=0;i<this.b.length;i++){
b[i] = this.b[i];
}
ooo.b = b;
return ooo;
}
hashCode–native方法/可以重寫
public native int hashCode();
底層調用了c++實作的本地方法庫,hashCode()是一個native方法,傳回值類型是整數;
看了很多部落格,沒有看到有說c++是怎麼實作的,之後了解了再補上
我們就先這樣了解吧:這個native方法将對象在記憶體中的位址作為哈希碼傳回,保證了不同對象的傳回值不同。
擴充:
基本上兩個相同的對象,equals方法傳回相同,則hashCode的傳回值也最好相同;
但是當兩個對象的hashCode的傳回值相同,還要再去equals比較一下确認是否相同。
這個思想可以參考hashmap判斷兩個對象相同的源碼(如果你重寫了equals()方法,那麼一定要記得重寫hashCode()方法)
通常我們如果要用到hashcode都會重寫這個方法
@Override
public int hashCode() {
int result = 17;
result = result * 31 + b.hashCode();
result = result * 31 + a;
return result;
}//(自動生成的)
equals–可重寫
public boolean equals(Object obj) {
return (this == obj);
}
可以從源碼中看出:equals方法直接使用的是“ == ” 來實作的 ( “==”和clone方法類似,對于基本資料類型比較的是值是否相等,對于引用資料類型比較的是引用類型的位址是否相等)
我們可以重寫這個方法來實作比較一個引用對象的各個屬性/單個屬性 相等來代替對象相等。
@Override
public boolean equals(Object obj) {
return this.a==obj.a;
}
String重寫了equals方法,使得最終比較的是各個字元相等即為相等
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
擴充:
一般重寫equals方法就要重寫hashCode方法
建議使用自動生成的

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ObjectCloneTest that = (ObjectCloneTest) o;
return a == that.a &&
Arrays.equals(b, that.b);
}
@Override
public int hashCode() {
int result = 17;
result = result * 31 + b.hashCode();
result = result * 31 + a;
return result;
}
為什麼重寫equals一定要重寫hashcode?
現在有兩個Student對象:
Student s1=new Student("小明",18);
Student s2=new Student("小明",18);
此時s1.equals(s2)一定傳回true
假如隻重寫equals而不重寫hashcode,那麼Student類的hashcode方法就是Object預設的hashcode方法,由于預設的hashcode方法是根據對象的記憶體位址經雜湊演算法得來的,顯然此時s1!=s2,故兩者的hashcode不一定相等。
然而重寫了equals,且s1.equals(s2)傳回true,根據hashcode的規則,兩個對象相等其哈希值一定相等,是以沖突就産生了,是以重寫equals一定要重寫hashcode,而且從Student類重寫後的hashcode方法中可以看出,重寫後傳回的新的哈希值與Student的兩個屬性有關。
以下是關于hashcode的一些規定:
兩個對象相等,hashcode一定相等
兩個對象不等,hashcode不一定不等
hashcode相等,兩個對象不一定相等
(例子及下面解釋來自https://blog.csdn.net/xl_1803/article/details/80445481 )
toString-可重寫
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
getClass()是native方法,toString()方法調用了hashCode方法,傳回記憶體位址,可以重寫傳回具體的屬性值
建議自動生成:
@Override
public String toString() {
return "ObjectCloneTest{" +
"a=" + a +
", b=" + Arrays.toString(b) +
'}';
}
wait/notify/notifyAll–本地方法/不可重寫(final)
finalize-可重寫,子類可通路
protected void finalize() throws Throwable { }
垃圾對象/不可達對象:沒有引用的對象
可達對象:有引用引着的對象
此方法主要用于GC在回收垃圾對象時給對象一次“等一下”的機會,看看有沒有可能複活
GC在回收這個類的執行個體對象時,先會調用這個方法,如果重寫了這個方法,并為其添加了新的引用,則對象就不再是不可達對象了,GC就不會将其加入回收隊列,但是下一次失去引用時就沒有“等一下”機會了,此方法每個對象僅能調用一次,下一次會直接加到回收隊列中。
部落客小白,如有哪塊寫的不妥,歡迎評論~~
參考資料:
https://blog.csdn.net/xl_1803/article/details/80445481
https://baijiahao.baidu.com/s?id=1567910969491375&wfr=spider&for=pc