100道JAVA面試題+JAVA面試題參考答案

夏末18844發表於2018-10-23


(一)Java部分

1、列舉出JAVA中6個比較常用的包【天威誠信面試題】

【參考答案】

java.lang;java.util;java.io;java.sql;java.awt;java.net;javax.swing

2、JDK中哪些類是不能繼承的?【信雅達面試題】

【參考答案】

不能繼承的是類是那些用final關鍵字修飾的類。一般比較基本的型別或防止擴充套件類無意間破壞原來方法的實現的型別都應該是final的。

3、String是最基本的資料型別嗎?【天能智健面試題】

【參考答案】

基本資料型別包括byte、int、char、long、float、double、boolean和short。

所以String不屬於基本資料型別範疇內,但String屬於最常見一種引用型別。

4、short s1 = 1; s1 = s1 + 1;有什麼錯? short s1 = 1; s1 += 1;有什麼錯?【博炎科技面試題】

【參考答案】

對於short s1 = 1; s1 = s1 + 1;由於s1+1運算時會自動提升表示式的型別,所以結果是int型,再賦值給short型別s1時,編譯器會提示錯誤,需要強制轉換型別。

對於short s1 = 1; s1 += 1;由於+=是java語言規定的運算子,Java編譯器會對它進行特殊處理,因此可以正確編譯。

【分析】

主要考查幾種基本資料型別在運算時的,由低到高會自動轉換,而由高到低時會強制轉換。

5、Java物件初始化順序?【騰鵬科技面試題】

【參考答案】

分為兩種,一種是本類的初始化,一種是含有父類的初始化順序。這裡分開來說,

本類的初始化順序是:靜態變數、靜態初始化塊、變數、初始化塊、建構函式

繼承類的初始化順序是:父類靜態變數、父類靜態初始化塊、子類靜態變數、子類靜態初始塊、父類變數、父類初始化塊、父類建構函式、子類變數、子類初始化塊、子類建構函式。

【分析】

static{

System.out.println("靜態塊");

}

{

System.out.println("初始化模組"); }

public ClassName() {

System.out.println("構造方法");

}

說明:

原則上回答全面的話,應該是完整的說出帶有繼承的這種類的初始化過程,下面有個步驟可以參考:

1.裝載程式的時候首先找到的是它的基(父)類,如果有多層基(父)類則會一級一級的往上找最後找到根基(父)類。

2.執行根基礎(父)類中的static初始化,再執行下一個衍生類中的static,依此類推,一直保持這個順序。

3.此時類已經裝載完畢,開始建立物件,所有的基本資料型別都會設成它們的預設值,物件控制程式碼設為null

4.呼叫基礎(父)類的構造方法,基礎(父)類的構建採用與衍生類構造方法完全相同的處理過程。

5.構造方法初始完之後,進行變數的初始化。

6.執行構造方法中剩餘的部分。

6、寫幾個執行緒安全類,不安全的,支援排序的類名?【軟通動力面試題】

【參考答案】

Ø執行緒安全類:Vector、Hashtable、Stack。

Ø執行緒不安全的類:ArrayList、Linkedlist、HashSet、TreeSet、HashMap、TreeMap等。

Ø支援排序的類有HashSet、LinkedHashSet、TreeSet等(Set介面下的實現都支援排序)

【分析】

此題主要考查集合框架的知識。在集合框架中Collection介面為集合的根型別,提供集合操作的常用API方法,該介面下派生出兩個子介面,一個是不支援排序的List介面,一個是有自身排序的Set介面,所以回答排序與不排序分別從兩介面的實現中在作答。執行緒安全上來說,Vector類比同屬於List介面的ArrayList要早,是一個執行緒安全的類,在JDK1.2以後才推出一個非同步的ArrayList類,比Vector類效率高。同理Stack繼承自Vector也執行緒安全的類,另外在在Map介面的實現在Hashtable也是個執行緒安全的類。

7、哪幾個方法可以實現一個執行緒?【上海華信面試題】

【參考答案】

一是繼承Thread,重寫Thread類的方法run方法;另種是實現runnable介面並實現run方法。

【分析】

考查執行緒的基本實現,很多公司喜歡考查這方面知識,另外補充一下關於執行緒的run方法,在多執行緒API中啟動一個執行緒是呼叫start()方法,執行緒進入就緒狀態。

8、STOP()和SUSPEND()不推薦使用的原因?

【參考答案】

stop()是因為它不安全。它會解除由執行緒獲取的所有鎖定,當在一個執行緒物件上呼叫stop()方法時,這個執行緒物件所執行的執行緒就會立即停止,假如一個執行緒正在執行:synchronized void { x = 3; y = 4;}由於方法是同步的,多個執行緒訪問時總能保證x,y被同時賦值,而如果一個執行緒正在執行到x = 3;時,被呼叫了stop()方法,即使在同步塊中,它也乾脆地stop了,這樣就產生了不完整的殘廢資料。而多執行緒程式設計中最最基礎的條件要保證資料的完整性,所以請忘記執行緒的stop方法,以後我們再也不要說“停止執行緒”了。而且如果物件處於一種不連貫狀態,那麼其他執行緒能在那種狀態下檢查和修改它們。

suspend()方法容易發生死鎖。呼叫suspend()的時候,目標執行緒會停下來,但卻仍然持有在這之前獲得的鎖定。此時,其他任何執行緒都不能訪問鎖定的資源,除非被"掛起"的執行緒恢復執行。對任何執行緒來說,如果它們想恢復目標執行緒,同時又試圖使用任何一個鎖定的資源,就會造成死鎖。所以不應該使用suspend(),而應在自己的Thread類中置入一個標誌,指出執行緒應該活動還是掛起。若標誌指出執行緒應該掛起,便用wait()命其進入等待狀態。若標誌指出執行緒應當恢復,則用一個notify()重新啟動執行緒。

【分析】

9、"=="和equals方法有什麼區別?【中科軟】

【參考答案】

==運算子專門用來比較兩個變數的值是否相等,也就是用於比較變數所對應的記憶體中所儲存的數值是否相同,要比較兩個基本型別的資料或兩個引用變數是否相等,只能用==運算子。

如果一個變數指向的資料是物件型別的,那麼,這時候涉及了兩塊記憶體,物件本身佔用一塊記憶體(堆記憶體),變數也佔用一塊記憶體,例如Objet obj = new Object();變數obj是一個記憶體,new Object()是另一個記憶體,此時,變數obj所對應的記憶體中儲存的數值就是物件佔用的那塊記憶體的首地址。對於指向物件型別的變數,如果要比較兩個變數是否指向同一個物件,即要看這兩個變數所對應的記憶體中的數值是否相等,這時候就需要用==運算子進行比較。

equals方法是用於比較兩個獨立物件的內容是否相同,就好比去比較兩個人的長相是否相同,它比較的兩個物件是獨立的。例如,對於下面的程式碼:

String a=new String("foo");

String b=new String("foo");

兩條new語句建立了兩個物件,然後用a,b這兩個變數分別指向了其中一個物件,這是兩個不同的物件,它們的首地址是不同的,即a和b中儲存的數值是不相同的,所以,表示式a==b將返回false,而這兩個物件中的內容是相同的,所以,表示式a.equals(b)將返回true。

在實際開發中,我們經常要比較傳遞進行來的字串內容是否等,例如,String input =…;input.equals(“quit”),如果一個類沒有自己定義equals方法,那麼它將繼承Object類的equals方法,Object類的equals方法的實現程式碼如下:

boolean equals(Object o){

return this==o;

}

這說明,如果一個類沒有自己定義equals方法,它預設的equals方法(從Object類繼承的)就是使用==運算子,也是在比較兩個變數指向的物件是否是同一物件,這時候使用equals和使用==會得到同樣的結果,如果比較的是兩個獨立的物件則總返回false。如果你編寫的類希望能夠比較該類建立的兩個例項物件的內容是否相同,那麼你必須覆蓋equals方法,由你自己寫程式碼來決定在什麼情況即可認為兩個物件的內容是相同的。

10、靜態變數和例項變數的區別?

【參考答案】

在語法定義上的區別:靜態變數前要加static關鍵字,而例項變數前則不加。

在程式執行時的區別:例項變數屬於某個物件的屬性,必須建立了例項物件,其中的例項變數才會被分配空間,才能使用這個例項變數。靜態變數不屬於某個例項物件,而是屬於類,所以也稱為類變數,只要程式載入了類的位元組碼,不用建立任何例項物件,靜態變數就會被分配空間,靜態變數就可以被使用了。總之,例項變數必須建立物件後才可以透過這個物件來使用,靜態變數則可以直接使用類名來引用。

例如,對於下面的程式,無論建立多少個例項物件,永遠都只分配了一個staticVar變數,並且每建立一個例項物件,這個staticVar就會加1;但是,每建立一個例項物件,就會分配一個instanceVar,即可能分配多個instanceVar,並且每個instanceVar的值都只自加了1次。

public class VariantTest

{

public static int staticVar = 0;

public int instanceVar = 0;

public VariantTest()

{

staticVar++;

instanceVar++;

System.out.println(“staticVar=”+ staticVar +”,instanceVar=”+ instanceVar);

}

}

備註:這個解答除了說清楚兩者的區別外,最後還用一個具體的應用例子來說明兩者的差異,體現了自己有很好的解說問題和設計案例的能力,思維敏捷,超過一般程式設計師,有寫作能力!

11、構造器的名能不能和類的名字相同?

【參考答案】

構造器的名稱必須與類名相同。

【分析】

構造器或建構函式(有些書這樣叫)主要用來對類的成員變數進行初始化,當類建立例項時呼叫。

12、在一個主方法類可不可以呼叫一個非靜態的方法?

【參考答案】

可以呼叫。因為Java的主方法(main)方法本身也是static型別方法,一個static型別方法,發起對另一個static方法的呼叫沒有問題。

【分析】

靜態方法可以呼叫其它的靜態方法,但是不能呼叫非靜態方法,這個好比Java中的類變數與例項變數的關係。類變數是被所有類成員共享,而例項變數只被該例項共享,

13、一個類中可不可以有2個公共的方法?

【參考答案】

可以。Java中對公共方法的個數沒有約束,但是對公共的類有約束,一個Java原始檔中只能定義一個public型別的類。

14、GC是什麼,為什麼要使用它?【阿斯拓】

【參考答案】

GC是垃圾收集的意思(Gabage Collection),記憶體處理是程式設計人員容易出現問題的地方,忘記或者錯誤的記憶體回收會導致程式或系統的不穩定甚至崩潰,Java提供的GC功能可以自動監測物件是否超過作用域,從而達到自動回收記憶體的目的,Java語言沒有提供釋放已分配記憶體的顯示操作方法。

【分析】

15、說一下垃圾回收的原理,可以直接從記憶體中回收嗎?

【參考答案】

Java語言中一個顯著的特點就是引入了垃圾回收機制,使c++程式設計師最頭疼的記憶體管理的問題迎刃而解,它使得Java程式設計師在編寫程式的時候不再需要考慮記憶體管理。垃圾回收可以有效的防止記憶體洩露,有效的使用可以使用的記憶體。垃圾回收器通常是作為一個單獨的低階別的執行緒執行,不可預知的情況下對記憶體堆中已經死亡的或者長時間沒有使用的物件進行清除和回收,程式設計師不能實時的呼叫垃圾回收器對某個物件或所有物件進行垃圾回收,因為Java語言規範並不保證GC一定會執行。回收機制有分代複製垃圾回收和標記垃圾回收,增量垃圾回收。

【分析】

16、Java的異常有哪幾種,有什麼區別?

【參考答案】

兩大類,一般異常和執行時異常。一般異常,這些異常是在定義方法時宣告丟擲的,這些異常必需用try catch丟擲,或throws處理,如果不處理,程式將編譯失敗。比如:IOException、FileNotFoundException、SQLException等。

執行時異常是程式執行時可能報出的異常。可以用try catch抓取,也可以不做任何處理。例如:NullPointerException異常就是一種比較常見的執行時異常。

【分析】

17、switch語句能否作用在byte上,能否作用在long上,能否作用在String上?

【參考答案】

在switch(表示式)中,括號表示式只能是一個整數表示式或者列舉常量(更大字型),整數表示式可以是int基本型別或Integer包裝型別,由於,byte,short,char都可以隱含轉換為int,所以,這些型別以及這些型別的包裝型別也是可以的。顯然,long和String型別都不符合switch的語法規定,並且不能被隱式轉換成int型別,所以,它們不能作用於swtich語句中。

18、Integer與int的區別?

【參考答案】

int是java提供的8種原始資料型別之一,另外Java為每個原始型別提供了封裝類,Integer是java為int提供的封裝類。int的預設值為0,而Integer的預設值為null,即Integer可以區分出未賦值和值為0的區別,int則無法表達出未賦值的情況。

19、Java Reflection是什麼?【】

【參考答案】

JAVA反射,Reflection是Java程式開發語言的特徵之一,它允許執行中的Java程式對自身進行檢查,或者說"自審",並能直接操作程式的內部屬性。

【分析】

20、寫幾個java.lang.Object類中的方法名稱。

【參考答案】

主要有equals()、toString()、getClass()、hashCode()、clone()、notify()、wait()、notify()方法。

【分析】

這種題能記多少個就說多少個,不一定要求你所有的都記住,但是要理解其中部分重要方法的含義和作用。

21、&和&&的區別?

【參考答案】

&和&&都可以用作邏輯與的運算子,表示邏輯與(and),當運算子兩邊的表示式的結果都為true時,整個運算結果才為true,否則,只要有一方為false,則結果為false。

&&還具有短路的功能,即如果第一個表示式為false,則不再計算第二個表示式。

&還可以用作位運算子,當&運算子兩邊的表示式不是boolean型別時,&表示按位與操作,我們通常使用0x0f來與一個整數進行&運算,來獲取該整數的最低4個bit位。

【分析】

先說分別說兩者的作用,再說出&&和&各自的不同之處。

22、陣列有沒有length()這個方法,String有沒有length()這個方法。

【參考答案】

陣列沒有length()方法,但有length屬性

String有length()方法。

【分析】

考查平時使用陣列和字串的一些細節,一般在使用

23、String s=new String(“xyz”)建立了幾個物件

【參考答案】

2個string物件,一個是=null的s,一個是=“xyz”的string

兩個或一個”xyz”對應一個物件,這個物件放在字串常量緩衝區,常量”xyz”不管出現多少遍,都是緩衝區中的那一個。New String每寫一遍,就建立一個新的物件,它一句那個常量”xyz”物件的內容來建立出一個新String物件。如果以前就用過’xyz’,這句代表就不會建立”xyz”自己了,直接從緩衝區拿。

【分析】

24、能不能自己寫個類,也叫java.lang.String?

可以,但在應用的時候,需要用自己的類載入器去載入,否則,系統的類載入器永遠只是去載入jre.jar包中的那個java.lang.String。由於在tomcat的web應用程式中,都是由webapp自己的類載入器先自己載入WEB-INF/classess目錄中的類,然後才委託上級的類載入器載入,如果我們在tomcat的web應用程式中寫一個java.lang.String,這時候Servlet程式載入的就是我們自己寫的java.lang.String,但是這麼幹就會出很多潛在的問題,原來所有用了java.lang.String類的都將出現問題。

雖然java提供了endorsed技術,可以覆蓋jdk中的某些類,具體做法是….。但是,能夠被覆蓋的類是有限制範圍,反正不包括java.lang這樣的包中的類。

例如,執行下面的程式:

package java.lang;

public class String {

/**

* @param args

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

System.out.println("string");

}

}

報告的錯誤如下:

java.lang.NoSuchMethodError: main

Exception in thread "main"

這是因為載入了jre自帶的java.lang.String,而該類中沒有main方法。

25、你對物件導向思想的理解?

【參考答案】

物件導向程式設計(Object-Oriented Programming)簡稱OOP技術,是開發計算機應用程式的一種新方法、新思想。過去的程式導向程式設計中常常會導致所有的程式碼都包含在幾個模組中,使程式難以閱讀和維護,在做一些修改時常常牽一動百,使以後的開發和維護難以為繼。而使用OOP技術,使用許多程式碼模組,每個模組都只提供特定的功能,它們是彼此獨立的,可以增加程式碼重用的機率,更加有利於軟體的開發、維護和升級。另外OOP的三大核心特性:繼承、封裝、多型的特性,使得在面物件編上能夠設計出高內聚、低耦合的系統結構,使得系統更靈活、更容易擴充套件,而且成本較低,所以這一程式設計思想是目前一種應用最為普遍的軟體設計思想。

【分析】

26、最常見的runtime exception執行時異常?

【參考答案】

ClassCastException(型別轉換異常)、NumberFormatException(格式化異常)、

ArrayIndexOutOfBoundsException(陣列越界異常)、ArithmeticException(算術異常)、NullPointerException(空指標異常)等等

【分析】

這道題主要考查大家平時在專案開發過程中經常遇到的一些異常型別資訊,透過這些異常來考查大家的專案經驗與專案排錯能力。

27、用JDBC來實現訪問資料庫記錄可以採用下面的幾個步驟:

【參考答案】

1、透過驅動器管理器獲取連線介面(Connection)。

2、獲得Statement或它的子類。

3、指定Statement中的引數。

4、透過Statement傳送SQL語句。

5、檢查並處理返回的結果。

6、關閉Statement。

7、關閉連線接

【分析】

28、Error和exception的區別與聯絡?

【參考答案】

error表示恢復不是不可能,但很困難的情況下的一種嚴重問題。比如說記憶體溢,網路故障等,不可能指望程式能處理的一類錯誤。

Exception表示一種由程式設計或實現問題,像我們常說的異常處理,就是屬於這類,一般程式可以捕獲和處理這些異常。

【分析】

這道題的難點在Error很多時候由於我們無法重現這種Error導致很多同學甚至不知道Error到底是什麼,所以很容易把題目中的兩種錯誤劃上等號。

29、String s = "Hello";s = s + " world!";這兩行程式碼執行後,原始的String物件中的內容到底變了沒有?

【參考答案】

沒有。因為String被設計成不可變(immutable)類,所以它的所有物件都是不可變物件。在這段程式碼中,s原先指向一個String物件,內容是"Hello",然後我們對s進行了+操作,那麼s所指向的那個物件是否發生了改變呢?答案是沒有。這時,s不指向原來那個物件了,而指向了另一個String物件,內容為"Hello world!",原來那個物件還存在於記憶體之中,只是s這個引用變數不再指向它了。

透過上面的說明,我們很容易匯出另一個結論,如果經常對字串進行各種各樣的修改,或者說,不可預見的修改,那麼使用String來代表字串的話會引起很大的記憶體開銷。因為String物件建立之後不能再改變,所以對於每一個不同的字串,都需要一個String物件來表示。這時,應該考慮使用StringBuffer類,它允許修改,而不是每個不同的字串都要生成一個新的物件。並且,這兩種類的物件轉換十分容易。

同時,我們還可以知道,如果要使用內容相同的字串,不必每次都new一個String。例如我們要在構造器中對一個名叫s的String引用變數進行初始化,把它設定為初始值,應當這樣做:

public class Demo {

private String s;

...

public Demo {

s = "Initial Value";

}

...

}

而非

s = new String("Initial Value");

後者每次都會呼叫構造器,生成新物件,效能低下且記憶體開銷大,並且沒有意義,因為String物件不可改變,所以對於內容相同的字串,只要一個String物件來表示就可以了。也就說,多次呼叫上面的構造器建立多個物件,他們的String型別屬性s都指向同一個物件。

上面的結論還基於這樣一個事實:對於字串常量,如果內容相同,Java認為它們代表同一個String物件。而用關鍵字new呼叫構造器,總是會建立一個新的物件,無論內容是否相同。

至於為什麼要把String類設計成不可變類,是它的用途決定的。其實不只String,很多Java標準類庫中的類都是不可變的。在開發一個系統的時候,我們有時候也需要設計不可變類,來傳遞一組相關的值,這也是物件導向思想的體現。不可變類有一些優點,比如因為它的物件是隻讀的,所以多執行緒併發訪問也不會有任何問題。當然也有一些缺點,比如每個不同的狀態都要一個物件來代表,可能會造成效能上的問題。所以Java標準類庫還提供了一個可變版本,即StringBuffer。

30、Jdk1.5的新特性?

【參考答案】

JDK1.5的一個重要主題就是透過新增一些特性來簡化開發,這些特性主要包括:泛型、ForEach迴圈、自動裝包/拆包、列舉、可變引數、靜態匯入這些。

【分析】

31、物件導向的特徵有哪些方面?

【參考答案】

物件導向的程式語言有封裝、繼承、多型等3個主要的特徵。

u封裝

封裝是保證軟體部件具有優良的模組性的基礎,封裝的目標就是要實現軟體部件的“高內聚、低耦合”,防止程式相互依賴性而帶來的變動影響。物件導向的封裝就是把描述一個物件的屬性和行為的程式碼封裝在一個“模組”中,也就是一個類中,屬性用變數定義,行為用方法進行定義,方法可以直接訪問同一個物件中的屬性。

u繼承

在定義和實現一個類的時候,可以在一個已經存在的類的基礎之上來進行,把這個已經存在的類所定義的內容作為自己的內容,並可以加入若干新的內容,或修改原來的方法使之更適合特殊的需要,這就是繼承。繼承是子類自動共享父類資料和方法的機制,這是類之間的一種關係,提高了軟體的可重用性和可擴充套件性。

u多型

多型是指程式中定義的引用變數所指向的具體型別和透過該引用變數發出的方法呼叫在程式設計時並不確定,而是在程式執行期間才確定,即一個引用變數倒底會指向哪個類的例項物件,該引用變數發出的方法呼叫到底是哪個類中實現的方法,必須在由程式執行期間才能決定。因為在程式執行時才確定具體的類,這樣,不用修改源程式程式碼,就可以讓引用變數繫結到各種不同的類實現上,從而導致該引用呼叫的具體方法隨之改變,即不修改程式程式碼就可以改變程式執行時所繫結的具體程式碼,讓程式可以選擇多個執行狀態,這就是多型性。多型性增強了軟體的靈活性和擴充套件性。

32、JVM工作原理?

執行jvm字元碼的工作是由直譯器來完成的。解釋執行過程分三步進行:

程式碼的裝入、程式碼的校驗、和程式碼的執行。

裝入程式碼的工作由“類裝載器class loader”完成。類裝載器負責裝入執行一個程式需要的所有程式碼,這也包括程式程式碼中的類所繼承的類和被呼叫的類。當類裝載器裝入一個類時,該類被放在自己的名字空間中。除了透過符號引用自己名字空間以外的類,類之間沒有其他辦法可以影響其他類。在本臺計算機的所有類都在同一地址空間中,而所有從外部引進的類,都有一個自己獨立的名字空間。這使得本地類透過共享相同的名字空間獲得較高的執行效率,同時又保證它們與從外部引進的類不會相互影響。當裝入了執行程式需要的所有類後,直譯器便可確定整個可執行程式的記憶體佈局。直譯器為符號引用與特定的地址空間建立對應關係及查詢表。透過在這一階段確定程式碼的內佈局,java很好地解決了由超類改變而使子類

崩潰的問題,同時也防止了程式碼的非法訪問。隨後,被裝入的程式碼由位元組碼校驗器進行檢查。校驗器可以發現運算元棧益處、非法資料型別轉化等多種錯誤。透過校驗後,程式碼便開始執行了。

Java位元組碼的執行有兩種方式:

1)即時編譯方式:直譯器先將位元組編譯成機器碼,然後再執行該機器碼。

2)解釋執行方式:直譯器透過每次解釋並執行一小段程式碼來完成java位元組。

碼程式的所有操作。

33、說說Java中的記憶體分配?

Java把記憶體分成兩種,一種叫做棧記憶體,一種叫做堆記憶體

在函式中定義的一些基本型別的變數和物件的引用變數都是在函式的棧記憶體中分配。當在一段程式碼塊中定義一個變數時,java就在棧中為這個變數分配記憶體空間,當超過變數的作用域後,java會自動釋放掉為該變數分配的記憶體空間,該記憶體空間可以立刻被另作它用。

堆記憶體用於存放由new建立的物件和陣列。在堆中分配的記憶體,由java虛擬機器自動垃圾回收器來管理。在堆中產生了一個陣列或者物件後,還可以在棧中定義一個特殊的變數,這個變數的取值等於陣列或者物件在堆記憶體中的首地址,在棧中的這個特殊的變數就變成了陣列或者物件的引用變數,以後就可以在程式中使用棧記憶體中的引用變數來訪問堆中的陣列或者物件,引用變數相當於為陣列或者物件起的一個別名,或者代號。

引用變數是普通變數,定義時在棧中分配記憶體,引用變數在程式執行到作用域外釋放。而陣列&物件本身在堆中分配,即使程式執行到使用new產生陣列和物件的語句所在地程式碼塊之外,陣列和物件本身佔用的堆記憶體也不會被釋放,陣列和物件在沒有引用變數指向它的時候,才變成垃圾,不能再被使用,但是仍然佔著記憶體,在隨後的一個不確定的時間被垃圾回收器釋放掉。這個也是java比較佔記憶體的主要原因。但是在寫程式的時候,可以人為的控制。

34、final, finally, finalize的區別。

【參考答案】

final用於宣告屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,類不可繼承。

內部類要訪問區域性變數,區域性變數必須定義成final型別,例如,一段程式碼……

finally是異常處理語句結構的一部分,表示總是執行。

finalize是Object類的一個方法,在垃圾收集器執行的時候會呼叫被回收物件的此方法,可以覆蓋此方法提供垃圾收集時的其他資源回收,例如關閉檔案等。JVM不保證此方法總被呼叫

35、Extends和Implement的不同?

【參考答案】

extends是繼承父類,只要那個類不是宣告為final或者那個類定義為abstract的就能繼承,JAVA中不支援多重繼承,但是可以用介面來實現,這樣就要用到implements,繼承只能繼承一個類,但implements可以實現多個介面,用逗號分開就行了

比如class A extends B implements C,D,E

36、抽象類是否可以沒有抽象方法?為什麼?

【參考答案】

可以在java中用abstract關鍵字來修飾一個類時,這個類叫做抽象類。

抽象類中不一定要包含abstract方法,但一個類中包含了abstract方法,則這個類必須宣告為abstract類。

37、靜態的多型和動態的多型的區別?

【參考答案】

靜態的多型:即為過載;方法名相同,引數個數或型別不相同。(overloading)

動態的多型:即為重寫;子類覆蓋父類的方法,將子類的例項傳與父類的引用呼叫的是子類的方法實現介面的例項傳與介面的引用呼叫的實現類的方法。

38、說出一些常用的類,包,介面,請各舉5個?

【參考答案】

常用的類:String、StringBuffer、Integer、Vector、ArrayList、Hashtable等

常用的包:java.lang java.io java.util、java.sql。

常用的介面:集合中的List、Set、Map介面;與Servlet API相關的Servlet介面、HttpServletRequest,HttpServletResponse,HttpSession介面等。

39、Collections和Collection的區別【天晟科技】

【參考答案】

Collection是個java.util下的介面,它是各種集合結構的父介面,定義了集合物件的基本操作方法。Collections是個java.util下的工具類,它包含有各種有關集合操作的靜態方法,主要是針對集合類的一個幫助類或者叫包裝類,它提供一系列對各種集合的搜尋,排序,執行緒安全化等操作方法。

40、Class.forName的作用?為什麼要用?

【參考答案】

按引數中指定的字串形式的類名去搜尋並載入相應的類,如果該類位元組碼已經被載入過,則返回代表該位元組碼的Class例項物件,否則,按類載入器的委託機制去搜尋和載入該類,如果所有的類載入器都無法載入到該類,則丟擲ClassNotFoundException。載入完這個Class位元組碼後,接著就可以使用Class位元組碼的newInstance方法去建立該類的例項物件了。有時候,我們程式中所有使用的具體類名在設計時(即開發時)無法確定,只有程式執行時才能確定,這時候就需要使用Class.forName去動態載入該類,這個類名通常是在配置檔案中配置的,例如,spring的ioc中每次依賴注入的具體類就是這樣配置的,jdbc的驅動類名通常也是透過配置檔案來配置的,以便在產品交付使用後不用修改源程式就可以更換驅動類名。

41、Socket如何獲取本地ip地址?

【參考答案】

InetAddress類提供的API來訪問。InetAddress.getLocalAddress()

【分析】

42、介面是否可繼承介面?抽象類是否可實現(implements)介面?抽象類是否可繼承具體類【天威誠信面試題】

【參考答案】

介面可以繼承介面。抽象類可以實現(implements)介面,抽象類是否可繼承具體類。抽象類中可以有靜態的main方法。

備註:只要明白了介面和抽象類的本質和作用,這些問題都很好回答,你想想,如果你是java語言的設計者,你是否會提供這樣的支援,如果不提供的話,有什麼理由嗎?如果你沒有道理不提供,那答案就是肯定的了。

只有記住抽象類與普通類的唯一區別就是不能建立例項物件和允許有abstract方法。

43、用最有效率的方法算出2乘以8等於幾?

【參考答案】

2 << 3

【分析】

因為將一個數左移n位,就相當於乘以了2的n次方,那麼,一個數乘以8只要將其左移3位即可,而位運算cpu直接支援的,效率最高,所以2乘以8等於幾的最效率的方法是2 << 3。

44、char型變數中能不能存貯一箇中文漢字?為什麼?

【參考答案】

char型變數是用來儲存Unicode編碼的字元的,unicode編碼字符集中包含了漢字,所以,char型變數中當然可以儲存漢字啦。不過,如果某個特殊的漢字沒有被包含在unicode編碼字符集中,那麼,這個char型變數中就不能儲存這個特殊漢字。補充說明:unicode編碼佔用兩個位元組,所以,char型別的變數也是佔用兩個位元組。

45、寫clone()方法時,通常都有一行程式碼,是什麼?

【參考答案】

clone有預設行為,super.clone();因為首先要把父類中的成員複製到位,然後才是複製自己的成員。

46、說說常用集合類有哪些?有哪些方法?

【參考答案】

通常我們使用的集合類都大多是由List、Set、Map這三類介面派生出來的類,例如:

ArrayList、Vector、LinkedList、Stack、TreeSet、Hashtable、HashMap等

集合類的大部分方法都是由Collection介面定義的,主要包括有:

add(Ee)、remove(Object e)、addAll(),remove()、contains(Object obj)、clear()等

47、請說出作用域public,private,protected,以及不寫時的區別?【天威誠信面試題】

【參考答案】

這四個作用域的可見範圍如下表所示。

說明:如果在修飾的元素上面沒有寫任何訪問修飾符,則表示friendly。

作用域同一類同一package子孫類其他package

public√√√√

protected√√√×

friendly√√××

private√×××

備註:只要記住了有4種訪問許可權,4個訪問範圍,然後將全選和範圍在水平和垂直方向上分別按排從小到大或從大到小的順序排列,就很容易畫出上面的圖了。

48、構造器Constructor是否可被override?【億陽通訊面試題】

【參考答案】

構造器Constructor不能被繼承,因此不能重寫Override,但可以被過載Overload。

49、是否可以從一個static方法內部發出對非static方法的呼叫?【世承軟體面試題】

【參考答案】

不可以。因為非static方法是要與物件關聯在一起的,必須建立一個物件後,才可以在該物件上進行方法呼叫,而static方法呼叫時不需要建立物件,可以直接呼叫。

50、Math.round(11.5)等於多少? Math.round(-11.5)等於多少?【霧隱美地傳媒】

【參考答案】

Math類中提供了三個與取整有關的方法:ceil、floor、round,這些方法的作用與它們的英文名稱的含義相對應,例如,ceil的英文意義是天花板,該方法就表示向上取整,所以,Math.ceil(11.3)的結果為12,Math.ceil(-11.3)的結果是-11;floor的英文意義是地板,該方法就表示向下取整,所以,Math.floor(11.6)的結果為11,Math.floor(-11.6)的結果是-12;最難掌握的是round方法,它表示“四捨五入”,演算法為Math.floor(x+0.5),即將原來的數字加上0.5後再向下取整,所以,Math.round(11.5)的結果為12,Math.round(-11.5)的結果為-11。

51、abstract class(抽象類)和interface(介面)有什麼區別?【百度應用中心面試題】

【參考答案】

含有abstract修飾符的class即為抽象類,abstract類不能建立的例項物件。含有abstract方法的類必須定義為abstract class,abstract class類中的方法不必是抽象的。abstract class類中定義抽象方法必須在具體(Concrete)子類中實現,所以,不能有抽象構造方法或抽象靜態方法。如果的子類沒有實現抽象父類中的所有抽象方法,那麼子類也必須定義為abstract型別。

介面(interface)可以說成是抽象類的一種特例,介面中的所有方法都必須是抽象的。介面中的方法定義預設為public abstract型別,介面中的成員變數型別預設為public static final。

下面比較一下兩者的語法區別:

1.抽象類可以有構造方法,介面中不能有構造方法。

2.抽象類中可以有普通成員變數,介面中沒有普通成員變數

3.抽象類中可以包含非抽象的普通方法,介面中的所有方法必須都是抽象的,不能有非抽象的普通方法。

4.抽象類中的抽象方法的訪問型別可以是public,protected和(預設型別,雖然

eclipse下不報錯,但應該也不行),但介面中的抽象方法只能是public型別的,並且預設即為public abstract型別。

5.抽象類中可以包含靜態方法,介面中不能包含靜態方法

6.抽象類和介面中都可以包含靜態成員變數,抽象類中的靜態成員變數的訪問型別可以任意,但介面中定義的變數只能是public static final型別,並且預設即為public static final型別。

7.一個類可以實現多個介面,但只能繼承一個抽象類。

下面接著再說說兩者在應用上的區別:

【分析】

這道題的思路是先從總體解釋抽象類和介面的基本概念,然後再比較兩者的語法細節,最後再說兩者的應用區別。比較兩者語法細節區別的條理是:先從一個類中的構造方法、普通成員變數和方法(包括抽象方法),靜態變數和方法,繼承性等方面來回答。

52、Collection框架中實現比較要實現什麼介面?

【參考答案】

Comparable、Comparator介面

53、是否可以繼承String類?

【參考答案】

String類是final類故不可以繼承。

54、String和StringBuffer的區別

【參考答案】

JAVA平臺提供了兩個類:String和StringBuffer,它們可以儲存和操作字串,即包含多個字元的字元資料。String類表示內容不可改變的字串。而StringBuffer類表示內容可以被修改的字串。當你知道字元資料要改變的時候你就可以使用StringBuffer。典型地,你可以使用StringBuffers來動態構造字元資料。另外,String實現了equals方法,new String(“abc”).equals(new String(“abc”)的結果為true,而StringBuffer沒有實現equals方法,所以,new StringBuffer(“abc”).equals(new StringBuffer(“abc”)的結果為false。

String覆蓋了equals方法和hashCode方法,而StringBuffer沒有覆蓋equals方法和hashCode方法,所以,將StringBuffer物件儲存進Java集合類中時會出現問題。

55、StringBuffer與StringBuilder的區別

【參考答案】

StringBuffer和StringBuilder類都表示內容可以被修改的字串,StringBuilder是執行緒不安全的,執行效率高,如果一個字串變數是在方法裡面定義,這種情況只可能有一個執行緒訪問它,不存在不安全的因素了,則用StringBuilder。如果要在類裡面定義成員變數,並且這個類的例項物件會在多執行緒環境下使用,那麼最好用StringBuffer。

56、try {}裡有一個return語句,那麼緊跟在這個try後的finally {}裡的code會不會被執行,什麼時候被執行,在return前還是後?【杭州天眼科技】

【參考答案】

答案是在return之前。

【分析】

程式程式碼的執行結果:

public class Test {

public static void main(String[] args) {

// TODO Auto-generated method stub

System.out.println(new Test().test());;

}

static int test()

{

int x = 1;

try

{

return x;

}

finally

{

++x;

}

}

}

---------執行結果---------

1

執行結果是1,為什麼呢?主函式呼叫子函式並得到結果的過程,好比主函式準備一個空罐子,當子函式要返回結果時,先把結果放在罐子裡,然後再將程式邏輯返回到主函式。所謂返回,就是子函式說,我不執行了,你主函式繼續執行吧,這沒什麼結果可言,結果是在說這話之前放進罐子裡的。

下面的程式程式碼輸出的結果是多少?

public class smallT

{

public static void main(String args[])

{

smallT t = new smallT();

int b = t.get();

System.out.println(b);

}

public int get()

{

try

{

return 1 ;

}

finally

{

return 2 ;

}

}

}

返回的結果是2。

我可以透過下面一個例子程式來幫助我解釋這個答案,從下面例子的執行結果中可以發現,try中的return語句呼叫的函式先於finally中呼叫的函式執行,也就是說return語句先執行,finally語句後執行,所以,返回的結果是2。Return並不是讓函式馬上返回,而是return語句執行後,將把返回結果放置進函式棧中,此時函式並不是馬上返回,它要執行finally語句後才真正開始返回。

在講解答案時可以用下面的程式來幫助分析:

public class Test {

/**

* @param args add by zxx ,Dec 9, 2008

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

System.out.println(new Test().test());;

}

int test()

{

try

{

return func1();

}

finally

{

return func2();

}

}

int func1()

{

System.out.println("func1");

return 1;

}

int func2()

{

System.out.println("func2");

return 2;

}

}

-----------執行結果-----------------

func1

func2

2

結論:finally中的程式碼比return和break語句後執行。

57、Java中的異常處理機制的簡單原理和應用。

【參考答案】

異常是指java程式執行時(非編譯)所發生的非正常情況或錯誤,與現實生活中的事件很相似,現實生活中的事件可以包含事件發生的時間、地點、人物、情節等資訊,可以用一個物件來表示,Java使用物件導向的方式來處理異常,它把程式中發生的每個異常也都分別封裝到一個物件來表示的,該物件中包含有異常的資訊。

Java對異常進行了分類,不同型別的異常分別用不同的Java類表示,所有異常的根類為java.lang.Throwable,Throwable下面又派生了兩個子類:Error和Exception,Error表示應用程式本身無法克服和恢復的一種嚴重問題,程式只有死的份了,例如,說記憶體溢位和執行緒死鎖等系統問題。Exception表示程式還能夠克服和恢復的問題,其中又分為系統異常和普通異常,系統異常是軟體本身缺陷所導致的問題,也就是軟體開發人員考慮不周所導致的問題,軟體使用者無法克服和恢復這種問題,但在這種問題下還可以讓軟體系統繼續執行或者讓軟體死掉,例如,陣列指令碼越界(ArrayIndexOutOfBoundsException),空指標異常(NullPointerException)、類轉換異常(ClassCastException);普通異常是執行環境的變化或異常所導致的問題,是使用者能夠克服的問題,例如,網路斷線,硬碟空間不夠,發生這樣的異常後,程式不應該死掉。

java為系統異常和普通異常提供了不同的解決方案,編譯器強制普通異常必須try..catch處理或用throws宣告繼續拋給上層呼叫方法處理,所以普通異常也稱為checked異常,而系統異常可以處理也可以不處理,所以,編譯器不強制用try..catch處理或用throws宣告,所以系統異常也稱為unchecked異常。

58、多執行緒有幾種實現方法?同步有幾種實現方法?

【參考答案】

多執行緒有兩種實現方法,分別是繼承Thread類與實現Runnable介面。

同步的實現方面有兩種,分別是synchronized,wait與notify。

a.wait():使一個執行緒處於等待狀態,並且釋放所持有的物件的lock。

b.sleep():使一個正在執行的執行緒處於睡眠狀態,是一個靜態方法,呼叫此方法要捕捉InterruptedException異常。

c.notify():喚醒一個處於等待狀態的執行緒,注意的是在呼叫此方法的時候,並不能確切的喚醒某一個等待狀態的執行緒,而是由JVM確定喚醒哪個執行緒,而且不是按優先順序。

d.allnotity():喚醒所有處入等待狀態的執行緒,注意並不是給所有喚醒執行緒一個物件的鎖,而是讓它們競爭。

59、啟動一個執行緒是用run()還是start()?

【參考答案】

啟動一個執行緒是呼叫start()方法,使執行緒就緒狀態,以後可以被排程為執行狀態,一個執行緒必須關聯一些具體的執行程式碼,run()方法是該執行緒所關聯的執行程式碼。

60、內部類可以引用外部類的成員嗎?有沒有什麼限制?

【參考答案】

完全可以。如果不是靜態內部類,那沒有什麼限制!

如果你把靜態巢狀類當作內部類的一種特例,那在這種情況下不可以訪問外部類的普通成員變數,而只能訪問外部類中的靜態成員。

61、List和Map區別?【軟通動力】

【參考答案】

一個是儲存單列資料的集合,另一個是儲存鍵和值這樣的雙列資料的集合,List中儲存的資料是有順序,並且允許重複;Map中儲存的資料是沒有順序的,其鍵是不能重複的,它的值是可以有重複的。

62、ArrayList和Vector的區別【博炎科技】

【參考答案】

這兩個類都實現了List介面(List介面繼承了Collection介面),他們都是有序集合,即儲存在這兩個集合中的元素的位置都是有順序的,相當於一種動態的陣列,我們以後可以按位置索引號取出某個元素,並且其中的資料是允許重複的。

接著說ArrayList與Vector的區別,這主要包括兩個方面:

1、同步性:

Vector是執行緒安全的,也就是說是它的方法之間是執行緒同步的,而ArrayList是執行緒序不安全的,它的方法之間是執行緒不同步的。如果只有一個執行緒會訪問到集合,那最好是使用ArrayList,因為它不考慮執行緒安全,效率會高些;如果有多個執行緒會訪問到集合,那最好是使用Vector,因為不需要我們自己再去考慮和編寫執行緒安全的程式碼。

備註:對於Vector&ArrayList、Hashtable&HashMap,要記住執行緒安全的問題,記住Vector與Hashtable是舊的,是java一誕生就提供了的,它們是執行緒安全的,ArrayList與HashMap是java2時才提供的,它們是執行緒不安全的。

2、資料增長:

ArrayList與Vector都有一個初始的容量大小,當儲存進它們裡面的元素的個數超過了容量時,就需要增加ArrayList與Vector的儲存空間,每次要增加儲存空間時,不是隻增加一個儲存單元,而是增加多個儲存單元,每次增加的儲存單元的個數在記憶體空間利用與程式效率之間要取得一定的平衡。Vector預設增長為原來兩倍,而ArrayList的增長為原來的1.5倍。ArrayList與Vector都可以設定初始的空間大小,Vector還可以設定增長的空間大小,而ArrayList沒有提供設定增長空間的方法。

63、heap和stack有什麼區別。

【參考答案】

Java的記憶體分為兩類,一類是棧記憶體,一類是堆記憶體。棧記憶體是指程式進入一個方法時,會為這個方法單獨分配一塊私屬儲存空間,用於儲存這個方法內部的區域性變數,當這個方法結束時,分配給這個方法的棧會釋放,這個棧中的變數也將隨之釋放。

堆是與棧作用不同的記憶體,一般用於存放不放在當前方法棧中的那些資料,例如,使用

new建立的物件都放在堆裡,所以,它不會隨方法的結束而消失。方法中的區域性變數使

用final修飾後,放在堆中,而不是棧中。

64、Java類實現序列化的方法(二種)?如在collection框架中實現排序,要實現什麼樣的介面

【參考答案】

java.io.Serializable介面或實現Externalizable介面。

Collection框架中實現比較要實現Comparable介面或Comparator介面,並實現比較方法

65、JAVA實現向資料庫新增一列。

【參考答案】

Connection con = null;

ResultSet rs = null;

Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");

String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=db_name";

Connection con = DriverManager.getConnection(url,"","");

StateManager sm =con.createStateMent();

String sql = " alter table student add age int; ";

rs = sm.excute(sql);

66、什麼是Java序列化,如何實現java序列化?或者請解釋Serializable介面的作用。【東軟國際】

【參考答案】

序列化就是一種用來處理物件流的機制,所謂物件流也就是將物件的內容進行流化。可以對流化後的物件進行讀寫操作,也可將流化後的物件傳輸於網路之間。序列化是為了解決在對物件流進行讀寫操作時所引發的問題。

序列化的實現:將需要被序列化的類實現Serializable介面,該介面沒有需要實現的方法,implements Serializable只是為了標註該物件是可被序列化的,然後使用一個輸出流(如:FileOutputStream)來構造一個ObjectOutputStream(物件流)物件,使用ObjectOutputStream物件的writeObject(Object obj)方法就可以將引數為obj的物件寫出,那麼在另一端,透過ObjectInputStream物件的readObject(Object obj)獲取到位元組流資料後,要將位元組流轉換成原物件,這叫反序列化,以便將資料儲存在檔案中或在網路傳輸。

Serializable介面描述啟用其序列化功能,未實現此介面的類將無法使其任何狀態序列化或反序列化。Serializable介面沒有方法或欄位,僅用於標識可序列化的語義,標識實現了該介面的物件屬性可被序列化。

67、Java中有幾種型別的流?JDK為每種型別的流提供了一些抽象類以供繼承,請說出他們分別是哪些類?

【參考答案】

位元組流,字元流兩種型別流。位元組流繼承於InputStream、OutputStream;字元流繼承於Reader、Writer。其它與IO操作相關的類都是派生至上述4個抽象類,如位元組相關的:FileInputStream、FileOutputStream類;字元相關的:BufferedReader、BufferedWriter類

68、用JDBC如何呼叫儲存過程

【參考答案】

透過JDBC元件中的CallableStatement介面實現呼叫儲存過程。

核心程式碼如下:

Class.forName("com.mysql.jdbc.Driver");

Connection conn=

DriverManager.getConnection("jdbc:mysql:///test","root","root");

CallableStatement cstmt = cn.prepareCall("{call insert_Student(?,?,?)}");

cstmt.registerOutParameter(3,Types.INTEGER);

cstmt.setString(1, "wangwu");

cstmt.setInt(2, 25);

cstmt.execute();

69、JAVA事件有哪些模式?

【參考答案】

1、事件直接驅動模式。它的特點是直接而且快,是必須經常使用的,主要適合於迅速處理前臺的命令,通常就是我們說的command(命令)模式。。2.監控式事件模式。主要藉助第三者來監控和觸發事件,就是通常我們說的觀察者模式。特點是:有一個觀察者置身事外在定期獨立執行著,我們將我們要監聽的事件向這個觀察者註冊,這樣觀察者就代替我們來監聽這個事件,應用客戶端透過觀察者來獲得事件狀況。

【分析】

70、JVM載入class檔案原理?

【參考答案】

所謂裝載就是尋找一個類或是一個介面的二進位制形式並用該二進位制形式來構造代表這個類或是這個介面的class物件的過程.

在Java中,類裝載器把一個類裝入Java虛擬機器中,要經過三個步驟來完成:裝載、連結和初始化,其中連結又可以分成校驗、準備、解析

裝載:查詢和匯入類或介面的二進位制資料;

連結:執行下面的校驗、準備和解析步驟,其中解析步驟是可以選擇的;

校驗:檢查匯入類或介面的二進位制資料的正確性;

準備:給類的靜態變數分配並初始化儲存空間;

解析:將符號引用轉成直接引用;

初始化:啟用類的靜態變數的初始化Java程式碼和靜態Java程式碼塊

JVM中類的裝載是由ClassLoader和它的子類來實現的,Java ClassLoader是一個重要的Java執行時系統元件。它負責在執行時查詢和裝入類檔案的類

一個Java應用程式使用兩種型別的類裝載器:根裝載器(bootstrap)和使用者定義的裝載器(user-defined)。

根裝載器以某種預設的方式將類裝入,包括那些Java API的類。在執行期間一個Java程式能安裝使用者自己定義的類裝載器。根裝載器是虛擬機器固有的一部分,而使用者定義的類裝載器則不是,它是用Java語言寫的,被編譯成class檔案之後然後再被裝入到虛擬機器,並像其它的任何物件一樣可以被例項化。Java類裝載器的體系結構如下所示:

Bootstrap(根裝載器)

|

Extension (擴充套件裝載器)

|

System

|

UserDefine1

/

UserDefine2 UserDefine3

|

UserDefine4

Java的類裝載模型是一種代理(delegation)模型。當JVM要求類裝載器CL(ClassLoader)裝載一個類時,CL首先將這個類裝載請求轉發給他的父裝載器。只有當父裝載器沒有裝載並無法裝載這個類時,CL才獲得裝載這個類的機會。這樣,所有類裝載器的代理關係構成了一種樹狀的關係。樹的根是類的根裝載器(bootstrap ClassLoader) ,在JVM中它以"null"表示。除根裝載器以外的類裝載器有且僅有一個父裝載器。在建立一個裝載器時,如果沒有顯式地給出父裝載器,那麼JVM將預設系統裝載器為其父裝載器

下面針對各種類裝載器分別進行詳細的說明:

根(Bootstrap)裝載器:該裝載器沒有父裝載器,它是JVM實現的一部分,從sun.boot.class.path裝載執行時庫的核心程式碼。

擴充套件(Extension)裝載器:繼承的父裝載器為根裝載器,不像根裝載器可能與執行時的作業系統有關,這個類裝載器是用純Java程式碼實現的,它從java.ext.dirs (擴充套件目錄)中裝載程式碼。

系統(System or Application)裝載器:裝載器為擴充套件裝載器,我們都知道在安裝JDK的時候要設定環境變數(CLASSPATH ),這個類裝載器就是從java.class.path(CLASSPATH環境變數)中裝載程式碼的,它也是用純Java程式碼實現的,同時還是使用者自定義類裝載器的預設父裝載器。

小應用程式(Applet)裝載器:裝載器為系統裝載器,它從使用者指定的網路上的特定目錄裝載小應用程式程式碼。

71、SOCKET中有幾中連線方式,各有什麼區別?

【參考答案】

Sockets有兩種主要的操作方式:面向連線(TCP/IP)的和無連線(UDP)的。無連線的操作使用資料包協議,無連線的操作是快速的和高效的,但是資料安全性不佳.面向連線的操作使用TCP協議.面向連線的操作比無連線的操作效率更低,但是資料的安全性更高

【分析】

72、抽象類能否被例項化?抽象類的作用是什麼?

【參考答案】

抽象類一般不能被例項化;抽象類通常不是由程式設計師定義的,而是由專案經理或模組設計人設計抽象類的原因通常是為了規範方法名抽象類必須要繼承,不然沒法用,作為模組設計者,可以把讓底層程式設計師直接用得方法直接呼叫,而一些需要讓程式設計師覆蓋後自己做得方法則定義稱抽象方法

【分析】

73、Linkedlist、Arraylist內部是如何實現的(更深入的問了LinkedList與ArrayList的區別)【天威誠信面試題】

【參考答案】

ArrayList的內部實現是基於內部陣列Object[],它更像是對陣列實現的一種封裝,所以在向ArrayList的前面或中間插入資料時,必須將其後的所有資料相應的後移,這樣必然要花費較多時間。

而LinkedList的內部實現是基於一組雙向連結串列實現的儲存特性,所以提供了連結串列一樣訪問的API介面,它們在效能上有很大的差別。當你訪問Linkedlist連結串列中的某個元素時,就必須從連結串列的一端開始沿著連線方向一個一個元素地去查詢,直到找到所需的元素為止,所以,當你的操作是在一列資料的前面或中間新增或刪除資料,並且按照順序訪問其中的元素時,就應該使用LinkedList了。

而當你的操作是在一列資料的後面新增資料而不是在前面或中間,並且需要隨機地訪問其中的元素時,使用ArrayList會提供比較好的效能。

【分析】

74、Hashtable的原理【北辰網路】

【參考答案】

透過節點的關鍵碼確定節點的儲存位置,即給定節點的關鍵碼k,透過一定的函式關係H(雜湊函式),得到函式值H(k),將此值解釋為該節點的儲存地址

75、JDBC中的PreparedStatement相比Statement的好處?

【參考答案】

預編譯語句java.sql.PreparedStatement ,擴充套件自Statement,不但具有Statement的所有能力而且具有更強大的功能。不同的是,PreparedStatement是在建立語句物件的同時給出要執行的sql語句。這樣,sql語句就會被系統進行預編譯,執行的速度會有所增加,尤其是在執行大語句的時候,效果更加理想

76、sleep()和wait()區別

【參考答案】

sleep()方法:執行緒主動放棄CPU,使得執行緒在指定的時間內進入阻塞狀態,不能得到CPU時間,指定的時間一過,執行緒重新進入可執行狀態。典型地,sleep()被用在等待某個資源就緒的情形:測試發現條件不滿足後,讓執行緒阻塞一段時間後重新測試,直到條件滿足為止。

wait( ):與notify()配套使用,wait()使得執行緒進入阻塞狀態,它有兩種形式,一種允許指定以毫秒為單位的一段時間作為引數,另一種沒有引數,當指定時間引數時對應的notify()被呼叫或者超出指定時間時執行緒重新進入可執行狀態,後者則必須對應的notify()被呼叫

(網上的答案:sleep是執行緒類(Thread)的方法,導致此執行緒暫停執行指定時間,給執行機會給其他執行緒,但是監控狀態依然保持,到時後會自動恢復。呼叫sleep不會釋放物件鎖。wait是Object類的方法,對此物件呼叫wait方法導致本執行緒放棄物件鎖,進入等待此物件的等待鎖定池,只有針對此物件發出notify方法(或notifyAll)後本執行緒才進入物件鎖定池準備獲得物件鎖進入執行狀態。)

sleep就是正在執行的執行緒主動讓出cpu,cpu去執行其他執行緒,在sleep指定的時間過後,cpu才會回到這個執行緒上繼續往下執行,如果當前執行緒進入了同步鎖,sleep方法並不會釋放鎖,即使當前執行緒使用sleep方法讓出了cpu,但其他被同步鎖擋住了的執行緒也無法得到執行。wait是指在一個已經進入了同步鎖的執行緒內,讓自己暫時讓出同步鎖,以便其他正在等待此鎖的執行緒可以得到同步鎖並執行,只有其他執行緒呼叫了notify方法(notify並不釋放鎖,只是告訴呼叫過wait方法的執行緒可以去參與獲得鎖的競爭了,但不是馬上得到鎖,因為鎖還在別人手裡,別人還沒釋放。如果notify方法後面的程式碼還有很多,需要這些程式碼執行完後才會釋放鎖,可以在notfiy方法後增加一個等待和一些程式碼,看看效果),呼叫wait方法的執行緒就會解除wait狀態和程式可以再次得到鎖後繼續向下執行。對於wait的講解一定要配合例子程式碼來說明,才顯得自己真明白。

package com.huawei.interview;

public class MultiThread {

/**

* @param args

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

new Thread(new Thread1()).start();

try {

Thread.sleep(10);

}catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

new Thread(new Thread2()).start();

}

private static class Thread1 implements Runnable

{

@Override

public void run() {

// TODO Auto-generated method stub

//由於這裡的Thread1和下面的Thread2內部run方法要用同一物件作為監視器,我們這裡不能用this,因為在Thread2裡面的this和這個Thread1的this不是同一個物件。我們用MultiThread.class這個位元組碼物件,當前虛擬機器裡引用這個變數時,指向的都是同一個物件。

synchronized (MultiThread.class) {

System.out.println("enter thread1...");

System.out.println("thread1 is waiting");

try {

//釋放鎖有兩種方式,第一種方式是程式自然離開監視器的範圍,也就是離開了synchronized關鍵字管轄的程式碼範圍,另一種方式就是在synchronized關鍵字管轄的程式碼內部呼叫監視器物件的wait方法。這裡,使用wait方法釋放鎖。

MultiThread.class.wait();

}catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

System.out.println("thread1 is going on...");

System.out.println("thread1 is being over!");

}

}

}

private static class Thread2 implements Runnable

{

@Override

public void run() {

// TODO Auto-generated method stub

synchronized (MultiThread.class) {

System.out.println("enter thread2...");

System.out.println("thread2 notify other thread can release wait status..");

//由於notify方法並不釋放鎖,即使thread2呼叫下面的sleep方法休息了10毫秒,但thread1仍然不會執行,因為thread2沒有釋放鎖,所以Thread1無法得不到鎖。

MultiThread.class.notify();

System.out.println("thread2 is sleeping ten millisecond...");

try {

Thread.sleep(10);

}catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

System.out.println("thread2 is going on...");

System.out.println("thread2 is being over!");

}

}

}

})

77、概述反射和序列化

【參考答案】

Reflection:是Java被視為動態語言的一個關鍵性質。這個機制允許程式在執行時透過Reflection APIs取得任何一個已知名稱的class的內部資訊,包括其modifiers(諸如public, static等等)、superclass(例如Object)、實現之interfaces(例如Cloneable),也包括fields和methods的所有資訊,並可於執行時改變fields內容或喚起methods。

序列化:就是一種用來處理物件流的機制,所謂物件流也就是將物件的內容進行流化。可以對流化後的物件進行讀寫操作,也可將流化後的物件傳輸於網路之間。序列化是為了解決在對物件流進行讀寫操作時的問題。

78、Java中實現多型的機制是什麼?

【參考答案】

重寫,過載

方法的重寫Overriding和過載Overloading是Java多型性的不同表現。

重寫Overriding是父類與子類之間多型性的一種表現,過載Overloading是一個類中多型性的一種表現。如果在子類中定義某方法與其父類有相同的名稱和引數,我們說該方法被重寫(Overriding)。子類的物件使用這個方法時,將呼叫子類中的定義,對它而言,父類中的定義如同被“遮蔽”了。

果在一個類中定義了多個同名的方法,它們或有不同的引數個數或有不同的引數型別,則稱為方法的過載(Overloading)。Overloaded的方法是可以改變返回值的型別。

79、Overload和Override的區別?Overloaded的方法是否可以改變返回值的型別?【軟通動力】

【參考答案】

Overload是過載的意思,Override是覆蓋的意思,也就是重寫。

過載Overload表示同一個類中可以有多個名稱相同的方法,但這些方法的引數列表各不相同(即引數個數或型別不同)。

重寫Override表示子類中的方法可以與父類中的某個方法的名稱和引數完全相同,透過子類建立的例項物件呼叫這個方法時,將呼叫子類中的定義方法,這相當於把父類中定義的那個完全相同的方法給覆蓋了,這也是物件導向程式設計的多型性的一種表現。子類覆蓋父類的方法時,只能比父類丟擲更少的異常,或者是丟擲父類丟擲的異常的子異常,因為子類可以解決父類的一些問題,不能比父類有更多的問題。子類方法的訪問許可權只能比父類的更大,不能更小。如果父類的方法是private型別,那麼,子類則不存在覆蓋的限制,相當於子類中增加了一個全新的方法。

是否可以改變返回值型別,在過載的定義中,與方法是什麼型別返回值無關。

【分析】

override可以翻譯為覆蓋,從字面就可以知道,它是覆蓋了一個方法並且對其重寫,以求達到不同的作用。對我們來說最熟悉的覆蓋就是對介面方法的實現,在介面中一般只是對方法進行了宣告,而我們在實現時,就需要實現介面宣告的所有方法。除了這個典型的用法以外,我們在繼承中也可能會在子類覆蓋父類中的方法。在覆蓋要注意以下的幾點:

1、覆蓋的方法的標誌必須要和被覆蓋的方法的標誌完全匹配,才能達到覆蓋的效果;

2、覆蓋的方法的返回值必須和被覆蓋的方法的返回一致;

3、覆蓋的方法所丟擲的異常必須和被覆蓋方法的所丟擲的異常一致,或者是其子類;

4、被覆蓋的方法不能為private,否則在其子類中只是新定義了一個方法,並沒有對其進行覆蓋。

overload對我們來說可能比較熟悉,可以翻譯為過載,它是指我們可以定義一些名稱相同的方法,透過定義不同的輸入引數來區分這些方法,然後再呼叫時,VM就會根據不同的引數樣式,來選擇合適的方法執行。在使用過載要注意以下的幾點:

1、在使用過載時只能透過不同的引數樣式。例如,不同的引數型別,不同的引數個數,不同的引數順序(當然,同一方法內的幾個引數型別必須不一樣,例如可以是fun(int,float),但是不能為fun(int,int));

2、不能透過訪問許可權、返回型別、丟擲的異常進行過載;

3、方法的異常型別和數目不會對過載造成影響;

4、對於繼承來說,如果某一方法在父類中是訪問許可權是priavte,那麼就不能在子類對其進行過載,如果定義的話,也只是定義了一個新方法,而不會達到過載的效果。

80、ClassLoader如何載入class。

【參考答案】

jvm裡有多個類載入,每個類載入可以負責載入特定位置的類,例如,bootstrap類載入負責載入jre/lib/rt.jar中的類,我們平時用的jdk中的類都位於rt.jar中。extclassloader負責載入jar/lib/ext/*.jar中的類,appclassloader負責classpath指定的目錄或jar中的類。除了bootstrap之外,其他的類載入器本身也都是java類,它們的父類是ClassLoader。

81、ArrayList如何實現插入的資料按自定義的方式有序存放

【參考答案】

實現Comparable比較介面,並實現compareTo方法。排序的方法,取決於compareTo方法中的比較定義的返回值,一般有3個返回值:1、-1、0表示不同的比較結果。

程式示例:

class MyBean implementsComparable{

public intcompareTo(Object obj){

if(! obj instanceof MyBean)

throw new ClassCastException();

MyBean other = (MyBean) obj;

return age > other.age?1:age== other.age?0:-1;

}

}

class MyTreeSet {

private ArrayList datas = new ArrayList();

public void add(Object obj){

for(int i=0;i

if(obj.compareTo(datas.get(i) != 1){

datas.add(i,obj);

}

}

}

}

82、hashCode方法的作用?

【參考答案】

hashcode這個方法是用來鑑定2個物件是否相等的。hashcode方法一般使用者不會去呼叫,比如在hashmap中,由於key是不可以重複的,他在判斷key是不是重複的時候就判斷了hashcode這個方法,而且也用到了equals方法。這裡不可以重複是說equals和hashcode只要有一個不等就可以了!所以簡單來講,hashcode相當於是一個物件的編碼。我們一般在覆蓋equals的同時也要覆蓋hashcode,讓他們的邏輯一致。

83、abstract的method是否可同時是static,是否可同時是native,是否可同時是synchronized?

【參考答案】

abstract的method不可以是static的,因為抽象的方法是要被子類實現的,而static與子類扯不上關係!

native方法表示該方法要用另外一種依賴平臺的程式語言實現的,不存在著被子類實現的問題,所以,它也不能是抽象的,不能與abstract混用。例如,FileOutputSteam類要硬體打交道,底層的實現用的是作業系統相關的api實現,例如,在windows用c語言實現的,所以,檢視jdk的原始碼,可以發現FileOutputStream的open方法的定義如下:

private native void open(String name) throws FileNotFoundException;

如果我們要用java呼叫別人寫的c語言函式,我們是無法直接呼叫的,我們需要按照java的要求寫一個c語言的函式,又我們的這個c語言函式去呼叫別人的c語言函式。由於我們的c語言函式是按java的要求來寫的,我們這個c語言函式就可以與java對接上,java那邊的對接方式就是定義出與我們這個c函式相對應的方法,java中對應的方法不需要寫具體的程式碼,但需要在前面宣告native。

關於synchronized與abstract合用的問題,我覺得也不行,因為在我幾年的學習和開發中,從來沒見到過這種情況,並且我覺得synchronized應該是作用在一個具體的方法上才有意義。而且,方法上的synchronized同步所使用的同步鎖物件是this,而抽象方法上無法確定this是什麼。

84、Anonymous Inner Class (匿名內部類)是否可以extends(繼承)其它類,是否可以implements(實現)interface(介面)?

【參考答案】

可以繼承其他類或實現其他介面。不僅是可以,而是必須!

85、JAVA語言如何進行異常處理,關鍵字:throws,throw,try,catch,finally分別代表什麼意義?在try塊中可以丟擲異常嗎?

【參考答案】

Java使用物件導向的方式來處理異常,它把程式中發生的每個異常也都分別封裝到一個物件來表示的,該物件中包含有異常的資訊。而throws hrow ry、catch、finally就是Java中用來對異常進行處理的幾個關鍵字,在Java程式設計中規容Java編譯器強制普通異常必須try..catch處理或用throws宣告繼續拋給上層呼叫方法處理,一般異常必須要求被捕獲和處理,而系統異常可以處理也可以不處理,所以編譯器不強制用try..catch處理或用throws、throw宣告異常。而finally一般與try或trycatch一起使用做為異常的最後處理出口。

86、同步和非同步有何異同,在什麼情況下分別使用他們?舉例說明。

【參考答案】

如果資料將線上程間共享。例如正在寫的資料以後可能被另一個執行緒讀到,或者正在讀的資料可能已經被另一個執行緒寫過了,那麼這些資料就是共享資料,必須進行同步存取。

當應用程式在物件上呼叫了一個需要花費很長時間來執行的方法,並且不希望讓程式等待方法的返回時,就應該使用非同步程式設計,在很多情況下采用非同步途徑往往更有效率。

87、當一個執行緒進入一個物件的一個synchronized方法後,其它執行緒是否可進入此物件的其它方法?

【參考答案】

分幾種情況:

1.其他方法前是否加了synchronized關鍵字,如果沒加,則能。

2.如果這個方法內部呼叫了wait,則可以進入其他synchronized方法。

3.如果其他個方法都加了synchronized關鍵字,並且內部沒有呼叫wait,則不能。

4.如果其他方法是static,它用的同步鎖是當前類的位元組碼,與非靜態的方法不能同步,因為非靜態的方法用的是this。

88、執行緒的基本概念、執行緒的基本狀態以及狀態之間的關係

【參考答案】

一個程式中可以有多條執行線索同時執行,一個執行緒就是程式中的一條執行線索,每個執行緒上都關聯有要執行的程式碼,即可以有多段程式程式碼同時執行,每個程式至少都有一個執行緒,即main方法執行的那個執行緒。如果只是一個cpu,它怎麼能夠同時執行多段程式呢?這是從宏觀上來看的,cpu一會執行a線索,一會執行b線索,切換時間很快,給人的感覺是a,b在同時執行,好比大家在同一個辦公室上網,只有一條連結到外部網線,其實,這條網線一會為a傳資料,一會為b傳資料,由於切換時間很短暫,所以,大家感覺都在同時上網。

狀態:就緒,執行,synchronize阻塞,wait和sleep掛起,結束。wait必須在synchronized內部呼叫。

呼叫執行緒的start方法後執行緒進入就緒狀態,執行緒排程系統將就緒狀態的執行緒轉為執行狀態,遇到synchronized語句時,由執行狀態轉為阻塞,當synchronized獲得鎖後,由阻塞轉為執行,在這種情況可以呼叫wait方法轉為掛起狀態,當執行緒關聯的程式碼執行完後,執行緒變為結束狀態。

89、簡述synchronized和java.util.concurrent.locks.Lock的異同?

【參考答案】

主要相同點:Lock能完成synchronized所實現的所有功能

主要不同點:Lock有比synchronized更精確的執行緒語義和更好的效能。synchronized會自動釋放鎖,而Lock一定要求程式設計師手工釋放,並且必須在finally從句中釋放。Lock還有更強大的功能,例如,它的tryLock方法可以非阻塞方式去拿鎖。

90、HashMap和Hashtable的區別?【北通網科】

【參考答案】

HashMap是Hashtable的輕量級實現(非執行緒安全的實現),他們都實現Map介面,主要區別在於HashMap允許空(null)鍵值(key),由於非執行緒安全,在只有一個執行緒訪問的情況下,效率要高於Hashtable。

HashMap允許將null作為一個entry的key或者value,而Hashtable不允許。

HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因為contains方法容易讓人引起誤解。

Hashtable繼承自Dictionary類,而HashMap是Java1.2引進的Map interface的一個實現。

最大的不同是,Hashtable的方法是synchronized的,而HashMap不是,在多個執行緒訪問Hashtable時,不需要自己為它的方法實現同步,而HashMap就必須為之提供外同步。

Hashtable和HashMap採用的hash/rehash演算法都大概一樣,所以效能不會有很大的差異。

91、List、Set、Map是否繼承自Collection介面?

【參考答案】

List、Set是,Map不是;Map介面定義的是Key-Value儲存的特性,與List和Set不同,Map在儲存物件時,先要定義這個物件的key的值,再存入與這個key相對應的Object,Map集合的取值時根據存入的key(關鍵字)來獲取與這個關鍵字對應的物件。

92、List、Map、Set三個介面,存取元素時,各有什麼特點?

【參考答案】

首先,List與Set具有相似性,它們都是單列元素的集合,所以,它們有一個功共同的父介面Collection介面。Set裡面不允許有重複的元素,即不能有兩個相等的物件。

List表示有先後順序的集合,當我們多次呼叫add(Obj e)方法時,每次加入的物件就像火車站買票有排隊順序一樣,按先來後到的順序排序。

Map與List和Set不同,它是雙列的集合每次儲存時,要儲存一對key/value,不能儲存重複的key,這個重複的規則也是按equals比較相等。取則可以根據key獲得相應的value,即get(Object key)返回值為key所對應的value。另外,也可以獲得所有的key的結合。

【分析】

總結:List以特定次序來持有元素,可有重複元素。Set無法擁有重複元素,內部排序。Map儲存key-value值,value可多值。上面是大致不同,另外上述3個只是介面,而具體實現類中,用法大同小異,只是實現的資料結構不同,例如List介面下的LinkedList主要實現了雙連結串列的儲存特點,Vector是執行緒安全的集合類。

93、說出ArrayList,Vector, LinkedList的儲存效能和特性。【大唐動力面試題】

【參考答案】

ArrayList和Vector都是使用陣列方式儲存資料,此陣列元素數大於實際儲存的資料以便增加和插入元素,它們都允許直接按序號索引元素,但是插入元素要涉及陣列元素移動等記憶體操作,所以索引資料快而插入資料慢,Vector由於使用了synchronized方法(執行緒安全),通常效能上較ArrayList差,而LinkedList使用雙向連結串列實現儲存,按序號索引資料需要進行前向或後向遍歷,但是插入資料時只需要記錄本項的前後項即可,所以插入速度較快。

LinkedList也是執行緒不安全的,LinkedList提供了一些方法,使得LinkedList可以被當作堆疊和佇列來使用。

94、如何去掉一個Vector集合中重複的元素

【參考答案】

Vector newVector = new Vector();

for (int i=0;i

{

Object obj = vector.get(i);

if(!newVector.contains(obj);

newVector.add(obj);

}

還有一種簡單的方式,HashSet set = new HashSet(vector);

95、Set裡的元素是不能重複的,那麼用什麼方法來區分重複與否呢?是用==還是equals()?它們有何區別?

【參考答案】

Set裡的元素是不能重複的,元素重複與否是使用equals()方法進行判斷的。

96、兩個物件值相同(x.equals(y) == true),但卻可有不同的hash code,這句話對不對?

【參考答案】

對。

如果物件要儲存在HashSet或HashMap中,它們的equals相等,那麼,它們的hashcode值就必須相等。

如果不是要儲存在HashSet或HashMap,則與hashcode沒有什麼關係了,這時候hashcode不等是可以的,例如arrayList儲存的物件就不用實現hashcode方法。

97、位元組流與字元流的區別

【參考答案】

要把一片二進位制資料資料逐一輸出到某個裝置中,或者從某個裝置中逐一讀取一片二進位制資料,不管輸入輸出裝置是什麼,我們要用統一的方式來完成這些操作,用一種抽象的方式進行描述,這個抽象描述方式起名為IO流,對應的抽象類為OutputStream和InputStream,不同的實現類就代表不同的輸入和輸出裝置,它們都是針對位元組進行操作的。

在應用中,經常要完全是字元的一段文字輸出去或讀進來,用位元組流可以嗎?計算機中的一切最終都是二進位制的位元組形式存在。對於“中國”這些字元,首先要得到其對應的位元組,然後將位元組寫入到輸出流。讀取時,首先讀到的是位元組,可是我們要把它顯示為字元,我們需要將位元組轉換成字元。由於這樣的需求很廣泛,人家專門提供了字元流的包裝類。

底層裝置永遠只接受位元組資料,有時候要寫字串到底層裝置,需要將字串轉成位元組再進行寫入。字元流是位元組流的包裝,字元流則是直接接受字串,它內部將串轉成位元組,再寫入底層裝置,這為我們向IO設別寫入或讀取字串提供了一點點方便。

字元向位元組轉換時,要注意編碼的問題,因為字串轉成位元組陣列,

其實是轉成該字元的某種編碼的位元組形式,讀取也是反之的道理。

講解位元組流與字元流關係的程式碼案例:

import java.io.BufferedReader;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.InputStreamReader;

import java.io.PrintWriter;

public class IOTest {

public static void main(String[] args) throws Exception {

String str = "中國人";

/*FileOutputStream fos = new FileOutputStream("1.txt");

fos.write(str.getBytes("UTF-8"));

fos.close();*/

/*FileWriter fw = new FileWriter("1.txt");

fw.write(str);

fw.close();*/

PrintWriter pw = new PrintWriter("1.txt","utf-8");

pw.write(str);

pw.close();

/*FileReader fr = new FileReader("1.txt");

char[] buf = new char[1024];

int len = fr.read(buf);

String myStr = new String(buf,0,len);

System.out.println(myStr);*/

/*FileInputStream fr = new FileInputStream("1.txt");

byte[] buf = new byte[1024];

int len = fr.read(buf);

String myStr = new String(buf,0,len,"UTF-8");

System.out.println(myStr);*/

BufferedReader br = new BufferedReader(

new InputStreamReader(

new FileInputStream("1.txt"),"UTF-8"

)

);

String myStr = br.readLine();

br.close();

System.out.println(myStr);

}

}

98、java裡面的io跟nio有什麼區別

【參考答案】

1、Java NIO和IO之間第一個最大的區別是,IO是面向流的,NIO是面向緩衝區的。

2、Java IO的各種流是阻塞的。而Java NIO的非阻塞模式,使一個執行緒從某通道傳送請求讀取資料,但是它僅能得到目前可用的資料,如果目前沒有資料可用時,就什麼都不會獲取。而不是保持執行緒阻塞,所以直至資料變的可以讀取之前,該執行緒可以繼續做其他的事情。

3、選擇器上,Java IO無選擇器,而NIO有選擇器,Java NIO的選擇器允許一個單獨的執行緒來監視多個輸入通道,你可以註冊多個通道使用一個選擇器,然後使用一個單獨的執行緒來“選擇”通道:這些通道里已經有可以處理的輸入,或者選擇已準備寫入的通道。

99、Java中會存在記憶體洩漏嗎,請簡單描述。

【參考答案】

所謂記憶體洩露就是指一個不再被程式使用的物件或變數一直被佔據在記憶體中。java中有垃圾回收機制,它可以保證一物件不再被引用的時候,即物件變成了孤兒的時候,物件將自動被垃圾回收器從記憶體中清除掉。由於Java使用有向圖的方式進行垃圾回收管理,可以消除引用迴圈的問題,例如有兩個物件,相互引用,只要它們和根程式不可達的,那麼GC也是可以回收它們的,例如下面的程式碼可以看到這種情況的記憶體回收:

package com.huawei.interview;

import java.io.IOException;

public class GarbageTest {

/**

* @param args

* @throws IOException

*/

public static void main(String[] args) throws IOException {

// TODO Auto-generated method stub

try {

gcTest();

}catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

System.out.println("has exited gcTest!");

System.in.read();

System.in.read();

System.out.println("out begin gc!");

for(int i=0;i<100;i++)

{

System.gc();

System.in.read();

System.in.read();

}

}

private static void gcTest() throws IOException {

System.in.read();

System.in.read();

Person p1 = new Person();

System.in.read();

System.in.read();

Person p2 = new Person();

p1.setMate(p2);

p2.setMate(p1);

System.out.println("before exit gctest!");

System.in.read();

System.in.read();

System.gc();

System.out.println("exit gctest!");

}

private static class Person

{

byte[] data = new byte[20000000];

Person mate = null;

public void setMate(Person other)

{

mate = other;

}

}

}

java中的記憶體洩露的情況:長生命週期的物件持有短生命週期物件的引用就很可能發生記憶體洩露,儘管短生命週期物件已經不再需要,但是因為長生命週期物件持有它的引用而導致不能被回收,這就是java中記憶體洩露的發生場景,通俗地說,就是程式設計師可能建立了一個物件,以後一直不再使用這個物件,這個物件卻一直被引用,即這個物件無用但是卻無法被垃圾回收器回收的,這就是java中可能出現記憶體洩露的情況,例如,快取系統,我們載入了一個物件放在快取中(例如放在一個全域性map物件中),然後一直不再使用它,這個物件一直被快取引用,但卻不再被使用。

檢查java中的記憶體洩露,一定要讓程式將各種分支情況都完整執行到程式結束,然後看某個物件是否被使用過,如果沒有,則才能判定這個物件屬於記憶體洩露。

如果一個外部類的例項物件的方法返回了一個內部類的例項物件,這個內部類物件被長期引用了,即使那個外部類例項物件不再被使用,但由於內部類持久外部類的例項物件,這個外部類物件將不會被垃圾回收,這也會造成記憶體洩露。

[]是物件已不可到達,而記憶體又沒有回收,真正的記憶體黑洞。

而Java的洩漏,則是因為各種原因,物件對應用已經無用,但一直被持有,一直可到達。

總結原因無外乎幾方面:

1.被生命週期極長的集合類不當持有,號稱是Java記憶體洩漏的首因。

這些集合類的生命週期通常極長,而且是一個輔助管理性質的物件,在一個業務事務執行完後,如果沒有將某個業務物件主動的從中清除的話,這個集合就會吃越來越多記憶體,可以用WeakReference,如WeakHashMap,使得它持有的物件不增加物件的引用數。

2.Scope定義不對,這個很簡單了,方法的區域性變數定義成類的變數,類的靜態變數等。

3.異常時沒有加finally{}來釋放某些資源,JDBC時代也是很普遍的事情。

4.另外一些我瞭解不深的原因,如:Swing裡的Listener沒有顯式remove;內部類持有外部物件的隱式引用;Finalizers造成關聯物件沒有被及時清空等。

記憶體洩漏的檢測

有不少工具輔助做這個事情的,如果手上一個工具也沒有,可以用JDK自帶的小工具:

·看看誰佔滿了Heap?

用JDK6的jmap可以顯示執行程式中物件的型別,個數與所佔的大小

先用jps找到程式號,然後jmap -histo pid顯示或jmap -dump:file=heap_file_name pid匯出heap檔案

·為什麼這些物件仍然可以到達?

用jhat(Java Heap Analysis Tool)分析剛才匯出的heap檔案。

先jhat heap_file_name,然後開啟瀏覽器瀏覽。

100、Hashcode和Equals的聯絡

【參考答案】

首先equals()和hashcode()這兩個方法都是從object類中繼承過來的,主要用來比較物件時進行呼叫。在object類中定義如下:

a)、如果兩個物件相同,那麼它們的hashCode值一定要相同;

b)、如果兩個物件的hashCode相同,它們並不一定相同上面說的物件相同指的是用eqauls方法比較。

101、Tread和Threadlocal的作用及區別?

【參考答案】

答:threadlocal是執行緒區域性變數(thread local variable),為每一個使用該執行緒的執行緒都提供一個變數值的副本,使每一個執行緒都可以獨立地改變自己的副本,而不會和其他執行緒的副本產生衝突。

102、TCP和UDP的區別?

【參考答案】

TCP/IP的運輸層有兩個不同的協議:①使用者資料包協議UDP②傳輸控制協議TCP

二者最大區別:TCP是面向連線的,而UDP是無連線的.區別大致如下:

1)UDP傳送的資料單位協議是UDP報文或使用者資料包,TCP傳送的資料單位協議是TCP報文段。

2)UDP傳送資料之前不需要建立連線,因此減少了開銷和傳送之前的時延。TCP提供面向連線的服務,不提供廣播或多播服務。

3)對方的運輸層在收到UDP報文後,不需要給出任何確認。TCP則需要確認。

4)UDP沒有擁塞控制,因此網路出現的擁塞不會使源主機的傳送速率降低,也不保證可靠交付,因此主機不需要維持具有許多引數的、複雜的連線狀態表。TCP要提供可靠的、面向連線的運輸服務,因此不可避免地增加了許多的開銷,這不僅使協議資料單元的首部增大很多,還要佔用許多的處理機資源。

5)UDP使用者資料包只有8個位元組的首部開銷,比TCP的20個位元組的首部要短。

103、啟動一個執行緒用什麼方法?【北京永中軟體面試題】

【參考】

使用Thread類的start()方法來啟動一個執行緒,使執行緒進入就緒狀態。如果自定義的類是Thread類的子類的話,可以直接使用Start()來啟,如果是實現的Runnable介面的話,還要將該類的例項作為引數傳入到Thread物件中來啟動。

104、作用域public等寫不寫的區別?【北京永中軟體面試題】

【參考】

作用域不寫將採用預設的作用域,預設作用域的訪問許可權是包的許可權,也就是除本包中的所有類能訪問,不同包只有子類能訪問。

105、同步和非同步有何異同

【參考答案】

同步(synchronized)和非同步(asynchronized)是對於多執行緒(multi-threading)而言的

同步可防止併發主要出於資料安全的考慮

如果資料將線上程間共享。例如正在寫的資料以後可能被另一個執行緒讀到,或者正在讀的資料可能已經被另一個執行緒寫過了,那麼這些資料就是共享資料,必須進行同步存取。

非同步允許併發

ajax技術通常都是非同步實現的,非同步主要使用在當應用程式在物件上呼叫了一個需要花費很長時間來執行的方法,並且不希望讓程式等待方法的返回時,就應該使用非同步程式設計,在很多情況下采用非同步途徑往往更有效率。

106、Static方法和static欄位有什麼用處?可以被過載嗎?

【參考答案】

用static修飾的方法叫類方法,被所有例項共享;static修飾的欄位為類變數,被所有例項共享,在使用類變數時,一般會結合final一起使用定義類常量,不允許被其它的類例項修改。

可以被過載,過載只是引數型別、順序和個數不同。
 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31557905/viewspace-2217183/,如需轉載,請註明出處,否則將追究法律責任。

相關文章