標籤:正是 迴圈 作用 ace 回調 理論 檔案的 console 表示
21.在Java中,如何跳出當前的多重嵌套迴圈?
答:在最外層迴圈前加一個標記如A,然後用break A;可以跳出多重迴圈。(Java中支援帶標籤的break和continue語句,作用有點類似於C和C++中的goto語句,但是就像要避免使用goto一樣,應該避免使用帶標籤的break和continue,因為它不會讓你的程式變得更優雅,很多時候甚至有相反的作用,所以這種文法其實不知道更好)
22.構造器(constructor)是否可被重寫(override)?
答:構造器不能被繼承,因此不能被重寫,但可以被重載。
23.兩個對象值相同(x.equals(y) == true),但卻可有不同的hash code,這句話對不對?
答:不對,如果兩個對象x和y滿足x.equals(y) == true,它們的雜湊碼(hash code)應當相同。Java對於eqauls方法和hashCode方法是這樣規定的:
(1)如果兩個對象相同(equals方法返回true),那麼它們的hashCode值一定要相同;
(2)如果兩個對象的hashCode相同,它們並不一定相同。
當然,你未必要按照要求去做,但是如果你違背了上述原則就會發現在使用容器時,相同的對象可以出現在Set集合中,同時增加新元素的效率會大大下降(對於使用雜湊儲存的系統,如果雜湊碼頻繁的衝突將會造成存取效能急劇下降)。
補充:關於equals和hashCode方法,很多Java程式都知道,但很多人也就是僅僅知道而已,在Joshua Bloch的大作《Effective Java》(很多軟體公司,《Effective Java》、《Java編程思想》以及《重構:改善既有代碼品質》是Java程式員必看書籍,如果你還沒看過,那就趕緊去亞馬遜買一本吧)中是這樣介紹equals方法的:首先equals方法必須滿足自反性(x.equals(x)必須返回true)、對稱性(x.equals(y)返回true時,y.equals(x)也必須返回true)、傳遞性(x.equals(y)和y.equals(z)都返回true時,x.equals(z)也必須返回true)和一致性(當x和y引用的對象資訊沒有被修改時,多次調用x.equals(y)應該得到同樣的傳回值),而且對於任何非null值的引用x,x.equals(null)必須返回false。實現高品質的equals方法的訣竅包括:1.使用==操作符檢查"參數是否為這個對象的引用";2.使用instanceof操作符檢查"參數是否為正確的類型";3.對於類中的關鍵屬性,檢查參數傳入對象的屬性是否與之相匹配;4.編寫完equals方法後,問自己它是否滿足對稱性、傳遞性、一致性;5.重寫equals時總是要重寫hashCode;6.不要將equals方法參數中的Object對象替換為其他的類型,在重寫時不要忘掉@Override註解。
24.是否可以繼承String類?
答:String 類是final類,不可以被繼承。
補充:繼承String本身就是一個錯誤的行為,對String類型最好的重用方式是關聯關係(Has-A)和依賴關係(Use-A)而不是繼承關係(Is-A)。
25.當一個對象被當作參數傳遞到一個方法後,此方法可改變這個對象的屬性,並可返回變化後的結果,那麼這裡到底是值傳遞還是引用傳遞?
答:是值傳遞。Java語言的方法調用只支援參數的值傳遞。當一個對象執行個體作為一個參數被傳遞到方法中時,參數的值就是對該對象的引用。對象的屬性可以在被調用過程中被改變,但對對象引用的改變是不會影響到調用者的。C++和C#中可以通過傳引用或傳輸出參數來改變傳入的參數的值。在C#中可以編寫如下所示的代碼,但是在Java中卻做不到。
namespace CS01 {
class Program { public static void swap(ref int x, ref int y) { int temp = x; x = y; y = temp; } public static void Main (string[] args) { int a = 5, b = 10; swap (ref a, ref b); // a = 10, b = 5; Console.WriteLine ("a = {0}, b = {1}", a, b); }}
}
說明:Java中沒有傳引用實在是非常的不方便,這一點在Java 8中仍然沒有得到改進,正是如此在Java編寫的代碼中才會出現大量的Wrapper類(將需要通過方法調用修改的引用置於一個Wrapper類中,再將Wrapper對象傳入方法),這樣的做法只會讓代碼變得臃腫,尤其是讓從C和C++轉型為Java程式員的開發人員無法容忍。
26.String和StringBuilder、StringBuffer的區別?
答:(1)String和StringBuffer、StringBuider:
①String:是不可變字元序列;②StringBuffer、StringBuider:是可變字元序列;
③String覆蓋了equals方法和hashCode方法,而StringBuffer沒有覆蓋equals方法和hashCode方法,所以,將StringBufferObject Storage Service進Java集合類中時會出現問題。
(2)StringBuffer和StringBuider:
①StringBuffer:是JDK1.0版本的,安全執行緒,效率低;②StringBuilder:是JDK1.5版本的,線程不安全,效率高;
③如果一個字串變數是在方法裡面定義,這種情況只可能有一個線程訪問它,不存在不安全的因素了,則用StringBuilder。如果要在類裡面定義成員變數,並且這個類的執行個體對象會在多線程環境下使用,那麼最好用StringBuffer。
27.描述一下JVM載入class檔案的原理機制?
答:JVM中類的裝載是由類載入器(ClassLoader)和它的子類來實現的,Java中的類載入器是一個重要的Java運行時系統組件,它負責在運行時尋找和裝入類檔案中的類。
由於Java的跨平台性,經過編譯的Java來源程式並不是一個可執行程式,而是一個或多個類檔案。當Java程式需要使用某個類時,JVM會確保這個類已經被載入、串連(驗證、準備和解析)和初始化。類的載入是指把類的.class檔案中的資料讀入到記憶體中,通常是建立一個位元組數組讀入.class檔案,然後產生與所載入類對應的Class對象。載入完成後,Class對象還不完整,所以此時的類還不可用。當類被載入後就進入串連階段,這一階段包括驗證、準備(為靜態變數分配記憶體並設定預設的初始值)和解析(將符號引用替換為直接引用)三個步驟。最後JVM對類進行初始化,包括:1)如果類存在直接的父類並且這個類還沒有被初始化,那麼就先初始化父類;2)如果類中存在初始化語句,就依次執行這些初始化語句。
類的載入是由類載入器完成的,類載入器包括:根載入器(BootStrap)、擴充載入器(Extension)、系統載入器(System)和使用者自訂類載入器(java.lang.ClassLoader的子類)。從Java 2(JDK 1.2)開始,類載入過程採取了父親委託機制(PDM)。PDM更好的保證了Java平台的安全性,在該機制中,JVM內建的Bootstrap是根載入器,其他的載入器都有且僅有一個父類載入器。類的載入首先請求父類載入器載入,父類載入器無能為力時才由其子類載入器自行載入。JVM不會向Java程式提供對Bootstrap的引用。下面是關於幾個類載入器的說明:
Bootstrap:一般用本地代碼實現,負責載入JVM基礎核心類庫(rt.jar);
Extension:從java.ext.dirs系統屬性所指定的目錄中載入類庫,它的父載入器是Bootstrap;
System:又叫應用類載入器,其父類是Extension。它是應用最廣泛的類載入器。它從環境變數classpath或者系統屬性java.class.path所指定的目錄中記載類,是使用者自訂載入器的預設父載入器。
28.抽象類別(abstract class)和介面(interface)有什麼異同?
答:(1)成員特點:
①構造方法:介面沒有;抽象類別有;
②成員變數:介面中只有常量;抽象類別中常量、變數都可;
③成員方法:介面只有抽象方法;抽象類別中抽象方法、非抽象方法都可;
(2)關係特點:
①類與類:只有單繼承,但可以多層繼承;
②類與介面:實現關係,可以單實現,也可以多實現;
③介面與介面:繼承關係,可以單繼承,也可以多繼承;
(3)設計理念:
①介面是簡單工廠設計模式,like a的關係 ,介面中定義的是該繼承體系的擴充功能;
③抽象類別是模板設計模式,is a的關係,抽象類別中定義的是繼承體系的共×××;
29.Java中會存在記憶體流失嗎,請簡單描述?
答:理論上Java因為有記憶體回收機制(GC)不會存在記憶體泄露問題(這也是Java被廣泛使用於伺服器端編程的一個重要原因);然而在實際開發中,可能會存在無用但可達的對象,這些對象不能被GC回收,因此也會導致記憶體泄露的發生。例如Hibernate的Session(一級緩衝)中的對象屬於持久態,記憶體回收行程是不會回收這些對象的,然而這些對象中可能存在無用的垃圾對象,如果不及時關閉(close)或清空(flush)一級緩衝就可能導致記憶體泄露。
30.抽象的(abstract)方法是否可同時是靜態(static),是否可同時是本地方法(native),是否可同時被synchronized修飾?
答:都不能。抽象方法需要子類重寫,而靜態方法是無法被重寫的,因此二者是矛盾的。本地方法是由本地代碼(如C代碼)實現的方法,而抽象方法是沒有實現的,也是矛盾的。synchronized和方法的實現細節有關,抽象方法不涉及實現細節,因此也是相互矛盾的。
31.是否可以從一個靜態(static)方法內部發出對非靜態(non-static)方法的調用?
答:不可以,靜態方法只能訪問靜態成員,因為非靜態方法的調用要先建立對象,在調用靜態方法時可能對象並沒有被初始化。
32.GC是什嗎?為什麼要有GC?
答:GC是垃圾收集的意思,Java提供的GC功能可以自動監測對象是否超過範圍從而達到自動回收記憶體的目的,從而有效防止記憶體泄露。要請求垃圾收集,可以調用下面的方法之一:System.gc()或Runtime.getRuntime().gc(),但JVM可以屏蔽掉顯示的記憶體回收調用。
33.String st = null和 String st =“ ”的區別?String s = new String("xyz")建立了幾個對象?
答:(1)String st = null表示聲明了一個String對象的引用str,但是沒有為其分配存記憶體空間。
(2)String st =“ ”表示建立了一個長度等於0的Null 字元串,並在記憶體中分配了記憶體空間。
(3)String st = new String(“xyz”);表示建立了兩個對象:
①堆記憶體中一個new String; ②常量池中一個字串。
34.介面是否可繼承(extends)介面?抽象類別是否可實現(implements)介面?抽象類別是否可繼承具體類(concrete class)?
答:介面可以繼承介面,而且支援多重繼承。抽象類別可以實現(implements)介面,抽象類別可繼承具體類也可以繼承抽象類別。
35.Anonymous Inner Class(匿名內部類)是否可以繼承其它類?是否可以實現介面?
答:可以繼承其他類或實現其他介面,在Swing編程和Android開發中常用此方式來實現事件監聽和回調。
36.內部類可以引用它的包含類(外部類)的成員嗎?有沒有什麼限制?
答:一個內部類對象可以訪問建立它的外部類對象的成員,包括私人成員。
37.final、finally和finalized的區別?
答:(1)final:被final修飾的類,不被能繼承;被final修飾的方法,不能被重寫;被fianl修飾的量,為常量,只能被賦值一次;
(2)finally:異常處理,和try、catch結合使用,可加可不加,用於執行一些必須執行的代碼,如釋放資源等;
(3)finalized:Object類中的方法,其中定義了對象要被記憶體回收行程回收之前,要做的一些清理工作。
38.資料類型之間的轉換?
答:(1)如何將字串轉換為基礎資料型別 (Elementary Data Type)?
調用基礎資料型別 (Elementary Data Type)對應的封裝類中的方法parseXXX(String)或valueOf(String)即可返回相應基本類型;
(2)如何將基礎資料型別 (Elementary Data Type)轉換為字串?
一種方法是將基礎資料型別 (Elementary Data Type)與Null 字元串("")串連(+)即可獲得其所對應的字串;另一種方法是調用String類中的valueOf()方法返回相應字串
39.如何?字串的反轉及替換?
答:方法很多,可以自己寫實現也可以使用String或StringBuffer/StringBuilder中的方法。有一道很常見的面試題是用遞迴實現字串反轉,代碼如下所示:
public static String reverse(String originStr) { if(originStr == null || originStr.length() <= 1) return originStr; return reverse(originStr.substring(1)) + originStr.charAt(0);}
40.怎樣將GB2312編碼的字串轉換為ISO-8859-1編碼的字串?
答:代碼如下所示:
String s1 = "你好";
String s2 = new String(s1.getBytes("GB2312"), "ISO-8859-1");
【JAVA秒會技術之秒殺面試官】JavaSE常見面試題(二)