您好,登錄后才能下訂單哦!
11、復(fù)制對象和復(fù)制引用的區(qū)別?
有如下程序:
Person p = new Person(23,"zhang");
Person p1 = p;
System.out.println(p);
System.out.println(p1);
程序執(zhí)行后看打印結(jié)果:
com.xidian.Person@2f4ee1ac
com.xidian.Person@2f4ee1ac
可以看出,兩個對象的地址相同,所以執(zhí)行“Person p1 = p;”并不是創(chuàng)建了一個新對象,p和p1是同一個引用,他們都指向了一個相同的對象Person(23,"zhang")。我們把這種現(xiàn)象叫做引用的復(fù)制,上面的代碼執(zhí)行完成之后,內(nèi)存中的情形如下圖所示:
而下面的代碼才是實現(xiàn)真正克隆了一個對象:
Person p = new Person(23,"zhang");
Person p1 = (Person) p.clone();
System.out.println(p);
System.out.println(p1);
打印結(jié)果如下:
com.xidian.Person@2f4ee1ac
com.xidian.Person@67f1fba0
從打印結(jié)果可以看出,兩個對象地址是不同的,也就說創(chuàng)建了新的對象,而不是把原來的對象地址賦值給一個新的引用變量。執(zhí)行完以上打碼后,內(nèi)存中的情形如下圖所示:
12、什么是深拷貝什么是淺拷貝?
11題示例代碼中,Person有兩個成員變量,分別是name和age,name是String類型,age是int類型,代碼非常簡單,如下所示:
public class Person implements Cloneable {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return (Person)super.clone();
}
}
由于age是基本數(shù)據(jù)類型,那么對它的拷貝沒什么疑義,直接講一個4字節(jié)的整數(shù)值拷貝過來就行了。但是name是String類型,他只是一個引用,指向一個真正的String對象,所以對他的拷貝方式有兩種,分別是:直接將原對象中的name的引用值拷貝給新對象的name字段,或者是根據(jù)原對象的name指向的字符串對象創(chuàng)建一個新的,相同的字符串對象,將這個新字符串對象的引用賦值給新拷貝的Person對象的name字段。這兩種方式分別叫做淺拷貝和深拷貝。深拷貝和淺拷貝示例圖如下所示:
總結(jié):如果兩個Person對象的name的地址值相同,說明兩個對象的name都指向同一個String對象,也就是淺拷貝,而如果兩個對象的name地址值不相同,那么就說明指向不同的String對象了,也就是說在拷貝Person對象的時候,同時拷貝了name引用的String對象,也就是深拷貝。如果想要深拷貝一個對象,這個對象必須要實現(xiàn)Cloneable接口,實現(xiàn)clone方法,并且在clone方法內(nèi)部,把該對象引用的其他對象也要clone一份,這就要求這個被引用的對象也必須要實現(xiàn)Cloneable接口并且實現(xiàn)clone方法。
13、兩個對象值相同(即x.equals(y) == true)是否可以有不同的hashCode?
不可以。如果兩個對象x和y滿足x.equals(y) == true,他們的hashCode應(yīng)當(dāng)相同。
Java對于equals方法和hashCode方法是這樣規(guī)定的:(1)如果兩個對象相同(equals方法返回true),那么他們的hashCode值一定相同。(2)如果兩個對象的hashCode相同,他們并不一定相同。當(dāng)然了,我們可以違背以上兩個原則,但是如果違背了這兩個原則,我們就會發(fā)現(xiàn),再使用容器的時候,相同的對象可以同時出現(xiàn)在Set集合中,對于使用哈希存儲的系統(tǒng),哈希碰撞的概率會大大提升。
關(guān)于equals方法,首先equals方法必須要滿足自反性:x.equals(x) == true ;對稱性:x.equals(y) == true ==> y.equals(x) == true;傳遞性:x.equals(y) == true && y.equals(z) == true ==> x.equals(z) == true;一致性:x和y如果沒有做任何修改時,多次調(diào)用x.equals(y)應(yīng)該得到相同的值。
實現(xiàn)高質(zhì)量equals方法的訣竅有:
使用“==”操作符檢查參數(shù)是否為這個對象的引用;
使用instanceof操作符檢查參數(shù)是否為正確的類型;
對于類中的關(guān)鍵屬性,檢查參數(shù)傳入對象的屬性是否與之相匹配;
編寫完equals方法后,檢查是否滿足對稱性、一致性、傳遞性;
重寫equals方法時,總是要重寫hashCode;
不要將equals方法參數(shù)中Object對象替換成其他類型,在重寫時不要忘記加上@Override注解。
14、是否可以繼承String類?
不可以。String是final類,所以不可以繼承。
15、String s = "Hello"; s = s + "World";執(zhí)行完這兩行代碼后,原始String對象的內(nèi)容變了嗎?
沒有,因為String被設(shè)計成不可變類(immutable),所以它的所有對象都是不可變對象,在這兩句代碼中,s原先指向一個String對象,對象內(nèi)容為Hello,然后我們對s進(jìn)行了“+”操作,這時候,s不指向原來那個對象了,轉(zhuǎn)而指向另外一個String對象了,這個對象的內(nèi)容是“HelloWorld”,原來那個對象仍然存在于內(nèi)存中,只是s這個引用變量不再指向它了。
所以,如果經(jīng)常需要對字符串進(jìn)行各種修改操作,那么使用String對象來代表字符串的話會引起很大的內(nèi)存開銷。因為String對象建立之后就不能再修改了,對一個不同的String就需要一個不同的String對象來表示。面對這種情況,應(yīng)該考慮使用StringBuffer類,它允許修改,而不是每一個不同的字符串都要新創(chuàng)建一個對象來表示,并且這兩種類的對象很容易進(jìn)行轉(zhuǎn)換。另外,如果要使用內(nèi)容相同的字符串,不必每一次都new一個String,因為String對象不可變,所以對于內(nèi)容相同的字符串,只要一個String對象來表示就可以了。
對于字符串常量,如果內(nèi)容相同,Java認(rèn)為他們代表同一個String對象,但是使用關(guān)鍵字new調(diào)用構(gòu)造器的時候,無論內(nèi)容是否相同,總是會創(chuàng)建一個新對象。至于為什么要把String對象設(shè)計成不可變類呢,這是由于它的用途決定的,不可變類有一個優(yōu)點,比如因為他的對象是只讀的,所以多線程并發(fā)訪問的時候也不會有任何問題。
16、Java中實現(xiàn)多態(tài)的機制是什么?
Java中實現(xiàn)多態(tài)的機制靠的是父類或者接口定義的引用變量可以指向子類或者具體實現(xiàn)類的實例對象,而程序調(diào)用的方法在運行期才動態(tài)綁定,就是引用變量所指向的具體事例對象的方法,也就是內(nèi)存里正在運行的那個對象的方法,而不是引用變量的類型中定義的方法。
17、Math.round(11.5)等于多少?Math.round(-11.5)等于多少?
Math.round(11.5)的返回值是12,Math.round(-11.5)的返回值是-11,四舍五入的原理是在參數(shù)上加0.5然后進(jìn)行取整。
18、數(shù)組有沒有l(wèi)ength()方法?String有沒有l(wèi)ength()方法?
數(shù)組沒有l(wèi)ength()方法,但是有l(wèi)ength屬性。String有l(wèi)ength()方法。
19、Java中的異常分類?
按照異常需要處理的時機可以將異常分為編譯時異常(也稱為強制異常)也叫做CheckedException和運行時異常(也稱為非強制異常)也叫做RunntimeException。
只有Java語言提供了Checked異常。Java認(rèn)為Checked異常都是可以處理的異常,所以Java程序必須顯式的處理,如果程序中存在Checked異常,該程序在編譯的時候就會發(fā)出錯誤,無法通過。這體現(xiàn)了Java的設(shè)計哲學(xué):沒有完善錯誤處理的代碼根本沒有運行的機會。對Checked異常通常有兩種處理方法,第一是當(dāng)前方法知道如何處理該異常,則使用try...catch塊來處理該異常,第二是不知道該如何處理,則在定義該方法的時候聲明拋出該異常。
運行時異常只有當(dāng)代碼在運行的時候才發(fā)出的異常,編譯時不需要try...catch塊,RunntimeException比如除數(shù)是0和數(shù)組下標(biāo)越界,其產(chǎn)生頻繁,處理麻煩,若要聲明或者捕獲將會對程序的可讀性和運行效率產(chǎn)生很大影響,所以交由系統(tǒng)自動檢測并將它們交給缺省的異常處理程序。
20、說出常見的RunntimeException?
java.lang.NullPointerException 空指針異常:原因是出現(xiàn)了未經(jīng)初始化的對象或者是不存在的對象。
java.lang.ClassNotFoundException:指定的類找不到:類的名稱或者路徑加載錯誤。
java.lang.NumberFormatException:字符串轉(zhuǎn)換為數(shù)字異常:字符串?dāng)?shù)據(jù)中包含非數(shù)字字符
java.lang.IndexOutOfBoundsException:數(shù)組角標(biāo)越界
java.lang.IllegalArgumentException:方法傳遞參數(shù)錯誤
java.lang.ClassCastException:數(shù)據(jù)類型轉(zhuǎn)換異常。
java.lang.NoClassDefFoundException:未找到類定義錯誤
java.lang.NoSuchMethodException:方法不存在異常
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。