java面試題,各大企業常見的java筆試題之七
1、什麼時候用assert?【中等難度】
答:assertion(斷言)在軟體開發中是一種常用的除錯方式,很多開發語言中都支援這種機制。一般來說,assertion 用於保證程式最基本、關鍵的正確性。assertion 檢查通常在開發和測試時開啟。為了提高效能,在軟體釋出後,
assertion 檢查通常是關閉的。在實現中,斷言是一個包含布林表示式的語句,在執行這個語句時假定該表示式為true;如果表示式計算為false,那麼系統會報告一個Assertionerror。斷言用於除錯目的:assert(a > 0); // throws an Assertionerror if a <= 0
斷言可以有兩種形式:
assert Expression1 ;
assert Expression1 : Expression2 ;
Expression1 應該總是產生一個布林值。
Expression2 可以是得出一個值的任意表達式;這個值用於生成顯示更多除錯資訊的String 訊息。
斷言在預設情況下是禁用的,要在編譯時啟用斷言,需使用source 1.4 標記:
javac -source 1.4 Test.java
要在執行時啟用斷言,可使用-enableassertions 或者-ea 標記。
要在執行時選擇禁用斷言,可使用-da 或者-disableassertions 標記。
要在系統類中啟用斷言,可使用-esa 或者-dsa 標記。還可以在包的基礎上啟用或者禁用斷言。可以在預計正常情況下不會到達的任何位置上放置斷言。斷言可以用於驗證傳遞給私有方法的引數。不過,斷言不應該用於驗證傳遞給公有方法的引數,因為不管是否啟用了斷言,公有方法都必須檢查其引數。不過,既可以在公有方法中,也可以在非公有方法中利用斷言測試後置條件。另外,斷言不應該以任何方式改變程式的狀態。異常部分:(共8 題:基礎8 道)
2、Java 中的異常處理機制的簡單原理和應用?【基礎】
答:當JAVA 程式違反了JAVA 的語義規則時,JAVA 虛擬機器就會將發生的錯誤表示為一個異常。違反語義規則包括2 種情況。一種是JAVA 類庫內建的語義檢查。
例如陣列下標越界,會引發IndexOutOfBoundsException;訪問null 的物件時會引發NullPointerException。另一種情況就是JAVA 允許程式設計師擴充套件這種語義檢查,程式設計師可以建立自己的異常,並自由選擇在何時用throw 關鍵字引發異常。所有的異常都是java.lang.Thowable 的子類。
3、error 和exception 有什麼區別? 【基礎】
答:error 表示系統級的錯誤和程式不必處理的異常,是恢復不是不可能但很困難的情況下的一種嚴重問題;比如記憶體溢位,不可能指望程式能處理這樣的情況;exception 表示需要捕捉或者需要程式進行處理的異常,是一種設計或實現問題;也就是說,它表示如果程式執行正常,從不會發生的情況。
4、try {}裡有一個return 語句,那麼緊跟在這個try 後的finally {}裡的code會不會被執行,什麼時候被執行,在return 前還是後? 【基礎】
答:會執行,在return 前執行。
5、JAVA 語言如何進行異常處理,關鍵字:throws,throw,try,catch,finally分別代表什麼意義?在try 塊中可以丟擲異常嗎?【基礎】
答:Java 通過面向物件的方法進行異常處理,把各種不同的異常進行分類,並提供了良好的介面。在Java 中,每個異常都是一個物件,它是Throwable 類或其它子類的例項。當一個方法出現異常後便丟擲一個異常物件,該物件中包含有異常資訊,呼叫這個物件的方法可以捕獲到這個異常並進行處理。Java 的異常處理是通過5 個關鍵詞來實現的:try、catch、throw、throws 和finally。一般情況下是用try 來執行一段程式,如果出現異常,系統會丟擲(throws)一個異常,這時候你可以通過它的型別來捕捉(catch)它,或最後(finally)由預設處理器來處理;
try 用來指定一塊預防所有“異常”的程式;
catch 子句緊跟在try 塊後面,用來指定你想要捕捉的“異常”的型別;
throw 語句用來明確地丟擲一個“異常”;
throws 用來標明一個成員函式可能丟擲的各種“異常”;
Finally 為確保一段程式碼不管發生什麼“異常”都被執行一段程式碼;
可以在一個成員函式呼叫的外面寫一個try 語句,在這個成員函式內部寫另一個try 語句保護其他程式碼。每當遇到一個try 語句,“異常”的框架就放到堆疊上面,直到所有的try 語句都完成。如果下一級的try 語句沒有對某種“異常”進行處理,堆疊就會展開,直到遇到有處理這種“異常”的try 語句。
6、執行時異常與一般異常有何異同?【基礎】
答:異常表示程式執行過程中可能出現的非正常狀態,執行時異常表示虛擬機器的通常操作中可能遇到的異常,是一種常見執行錯誤。java 編譯器要求方法必須宣告丟擲可能發生的非執行時異常,但是並不要求必須宣告丟擲未被捕獲的執行時異常。
7、給我一個你最常見到的runtime exception?【基礎】
答:ArithmeticException, ArrayStoreException, BufferOverflowException,
BufferUnderflowException, CannotRedoException, CannotUndoException,
ClassCastException, CMMException, ConcurrentModificationException,
DOMException, EmptyStackException, IllegalArgumentException,
IllegalMonitorStateException, IllegalPathStateException,
IllegalStateException, ImagingOpException, IndexOutOfBoundsException,
MissingResourceException, NegativeArraySizeException,
NoSuchElementException, NullPointerException, ProfileDataException,
ProviderException, RasterFormatException, SecurityException,
SystemException, UndeclaredThrowableException,
UnmodifiableSetException, UnsupportedOperationException
8、final, finally, finalize 的區別? 【基礎】
答:final:修飾符(關鍵字);如果一個類被宣告為final,意味著它不能再派生出新的子類,不能作為父類被繼承,因此一個類不能既被宣告為abstract的,又被宣告為final 的;將變數或方法宣告為final,可以保證它們在使用中不被改變;被宣告為final 的變數必須在宣告時給定初值,而在以後的引用中只能讀取,不可修改;被宣告為final 的方法也同樣只能使用,不能過載。finally:再異常處理時提供finally 塊來執行任何清除操作;如果丟擲一個異常,那麼相匹配的catch 子句就會執行,然後控制就會進入finally
塊(如果有的話)。
finalize:方法名;Java 技術允許使用finalize() 方法在垃圾收集器將物件從記憶體中清除出去之前做必要的清理工作。這個方法是由垃圾收集器在確定這個物件沒有被引用時對這個物件呼叫的。它是在Object 類中定義的,因此所有的類都繼承了它。子類覆蓋finalize() 方法以整理系統資源或者執行其他清理工作。finalize() 方法是在垃圾收集器刪除物件之前對這個物件呼叫的。
9、類Example A 繼承Exception,類ExampleB 繼承Example A;【基礎】
有如下程式碼片斷:
try{
throw new ExampleB(“b”);
}catch(ExampleA e){
System.out.printfln(“ExampleA”);
}catch(Exception e){
System.out.printfln(“Exception”);
}
輸出的內容應該是:
A:ExampleA B:Exception C:b D:無
答:輸出為A。
集合部分:(共11 題:基礎11 道)
10、介紹JAVA 中的Collection FrameWork(及如何寫自己的資料結構)【基礎】
答:Collection FrameWork 如下:
Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
└Set
Map
├Hashtable
├HashMap
└WeakHashMap
Collection 是最基本的集合介面,一個Collection 代表一組Object,即
Collection 的元素(Elements); Map 提供key 到value 的對映。
11、List,Set,Map 是否繼承自Collection 介面?【基礎】
答:List,Set 是;Map 不是。
12、你所知道的集合類都有哪些?主要方法?【基礎】
答:最常用的集合類是List 和Map。List 的具體實現包括ArrayList 和Vector,它們是可變大小的列表,比較適合構建、儲存和操作任何型別物件的元素列表。List 適用於按數值索引訪問元素的情形。Map 提供了一個更通用的元素儲存方法。Map 集合類用於儲存元素對(稱作“鍵”和“值”),其中每個鍵對映到一個值。
13、說出ArrayList,Vector, LinkedList 的儲存效能和特性?【基礎】
答:ArrayList 和Vector 都是使用陣列方式儲存資料,此陣列元素數大於實際儲存的資料以便增加和插入元素,它們都允許直接按序號索引元素,但是插入元素要涉及陣列元素移動等記憶體操作,所以索引資料快而插入資料慢,Vector 由於使用了synchronized 方法(執行緒安全),通常效能上較ArrayList 差,而LinkedList 使用雙向連結串列實現儲存,按序號索引資料需要進行前向或後向遍歷,但是插入資料時只需要記錄本項的前後項即可,所以插入速度較快。
14、Collection 和Collections 的區別?【基礎】
答:Collection 是java.util 下的介面,它是各種集合的父介面,繼承於它的介面主要有Set 和List;Collections 是個java.util 下的類,是針對集合的幫助類,提供一系列靜態方法實現對各種集合的搜尋、排序、執行緒安全化等操作。
15、HashMap 和Hashtable 的區別? 【基礎】
答:二者都實現了Map 介面,是將惟一鍵對映到特定的值上;主要區別在於:
1)HashMap 沒有排序,允許一個null 鍵和多個null 值,而Hashtable 不允許;
2)HashMap 把Hashtable 的contains 方法去掉了,改成containsvalue 和
containsKey,因為contains 方法容易讓人引起誤解;
3)Hashtable 繼承自Dictionary 類,HashMap 是Java1.2 引進的Map 介面的實現;
4)Hashtable 的方法是Synchronize 的,而HashMap 不是,在多個執行緒訪問
Hashtable 時,不需要自己為它的方法實現同步,而HashMap 就必須為之提供外同步。
Hashtable 和HashMap 採用的hash/rehash 演算法大致一樣,所以效能不會有很大的差異。
16、Arraylist 與Vector 區別?【基礎】
答:就ArrayList 與Vector 主要從二方面來說:
1)同步性:Vector 是執行緒安全的(同步),而ArrayList 是執行緒序不安全的;
2)資料增長:當需要增長時,Vector 預設增長一倍,而ArrayList 卻是一半。
17、List、Map、Set 三個介面,存取元素時,各有什麼特點?【基礎】
答:List 以特定次序來持有元素,可有重複元素。Set 無法擁有重複元素,內部
排序。Map 儲存key-value 值,value 可多值。
18、Set 裡的元素是不能重複的,那麼用什麼方法來區分重複與否呢? 是用==還是equals()? 它們有何區別? 【基礎】
答:Set 裡的元素是不能重複的,用equals ()方法來區分重複與否。覆蓋equals()方法用來判斷物件的內容是否相同,而”==”判斷地址是否相等,用來決定引用值是否指向同一物件。
19、用程式給出隨便大小的10 個數,序號為1-10,按從小到大順序輸出,並輸出相應的序號。【基礎】
答:程式碼如下:
package test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
public class RandomSort {
public static void printRandomBySort() {
Random random = new Random(); // 建立隨機數生成器
List list = new ArrayList();
// 生成10 個隨機數,並放在集合list 中
for (int i = 0; i < 10; i++) {
list.add(random.nextInt(1000));
}
Collections.sort(list); // 對集合中的元素進行排序
Iterator it = list.iterator();
int count = 0;
while (it.hasNext()) { // 順序輸出排序後集閤中的元素
System.out.println(++count + “: ” + it.next());
}
}
public static void main(String[] args) {
printRandomBySort();
}
}
20、用JAVA 實現一種排序,JAVA 類實現序列化的方法? 在COLLECTION 框架中,實現比較要實現什麼樣的介面?【基礎】
答:用插入法進行排序程式碼如下:
package test;
import java.util.*;
class InsertSort {
ArrayList al;
public InsertSort(int num,int mod) {
al = new ArrayList(num);
Random rand = new Random();
System.out.println(“The ArrayList Sort Before:”);
for (int i=0;i<num ;i++ ){
al.add(new Integer(Math.abs(rand.nextInt()) % mod +
1));
System.out.println(“al["+i+"]=”+al.get(i));
}
}
public void SortIt(){
tempInt;
int MaxSize=1;
for(int i=1;i<al.size();i++){
tempInt = (Integer)al.remove(i);
if(tempInt.intValue() >=
((Integer)al.get(MaxSize-1)).intValue()){
al.add(MaxSize,tempInt);
MaxSize++;
System.out.println(al.toString());
}else{
for (int j=0;j<MaxSize ;j++ ){
if (((Integer)al.get(j)).intValue()
>=tempInt.intValue()){
al.add(j,tempInt);
MaxSize++;
System.out.println(al.toString());
break;
}
}
}
}
System.out.println(“The ArrayList Sort After:”);
for(int i=0;i<al.size();i++){
System.out.println(“al["+i+"]=”+al.get(i));
}
}
public static void main(String[] args){
InsertSort is = new InsertSort(10,100);
is.SortIt();
}
}
JAVA 類實現序例化的方法是實現java.io.Serializable 介面;
Collection 框架中實現比較要實現Comparable 介面和Comparator 介面。
執行緒部分:(共10 題:基礎7 道,中等難度3 道)
21、sleep() 和wait() 有什麼區別? 【基礎】
答:sleep 是執行緒類(Thread)的方法,導致此執行緒暫停執行指定時間,給執行機會給其他執行緒,但是監控狀態依然保持,到時後會自動恢復。呼叫sleep 不會釋放物件鎖。wait 是Object 類的方法,對此物件呼叫wait 方法導致本執行緒放棄物件鎖,進入等待此物件的等待鎖定池,只有針對此物件發出notify 方法(或notifyAll)後本執行緒才進入物件鎖定池準備獲得物件鎖進入執行狀態。
22、當一個執行緒進入一個物件的一個synchronized 方法後,其它執行緒是否可進入此物件的其它方法? 【基礎】
答:其它執行緒只能訪問該物件的其它非同步方法,同步方法則不能進入。
23、請說出你所知道的執行緒同步的方法。【基礎】
答:wait():使一個執行緒處於等待狀態,並且釋放所持有的物件的lock;
sleep():使一個正在執行的執行緒處於睡眠狀態,是一個靜態方法,呼叫此方法要捕捉InterruptedException 異常;notify():喚醒一個處於等待狀態的執行緒,注意的是在呼叫此方法的時候,並不能確切的喚醒某一個等待狀態的執行緒,而是由JVM 確定喚醒哪個執行緒,而且不是按優先順序;
notityAll():喚醒所有處入等待狀態的執行緒,注意並不是給所有喚醒執行緒一個物件的鎖,而是讓它們競爭。
24、多執行緒有幾種實現方法,都是什麼?同步有幾種實現方法,都是什麼? 【基礎】
答:多執行緒有兩種實現方法,分別是繼承Thread 類與實現Runnable 介面,同步的實現方面有兩種,分別是synchronized,wait 與notify。
25、同步和非同步有何異同,在什麼情況下分別使用他們?舉例說明。【基礎】
答:如果資料將線上程間共享。例如正在寫的資料以後可能被另一個執行緒讀到,或者正在讀的資料可能已經被另一個執行緒寫過了,那麼這些資料就是共享資料,必須進行同步存取。當應用程式在物件上呼叫了一個需要花費很長時間來執行的方法,並且不希望讓程式等待方法的返回時,就應該使用非同步程式設計,在很多情況下采用非同步途徑往往更有效率。
26、啟動一個執行緒是用run()還是start()?【基礎】
答:啟動一個執行緒是呼叫start()方法,使執行緒所代表的虛擬處理機處於可執行狀態,這意味著它可以由JVM 排程並執行。這並不意味著執行緒就會立即執行。run()方法可以產生必須退出的標誌來停止一個執行緒。
27、執行緒的基本概念、執行緒的基本狀態以及狀態之間的關係?【基礎】
答:執行緒指在程式執行過程中,能夠執行程式程式碼的一個執行單位,每個程式至少都有一個執行緒,也就是程式本身;Java 中的執行緒有四種狀態分別是:執行、就緒、掛起、結束。
28、簡述synchronized 和java.util.concurrent.locks.Lock 的異同?【中等難度】
答:主要相同點:Lock 能完成synchronized 所實現的所有功能;主要不同點:Lock 有比synchronized 更精確的執行緒語義和更好的效能。synchronized 會自動釋放鎖,而Lock 一定要求程式設計師手工釋放,並且必須在finally 從句中釋放。
29、java 中有幾種方法可以實現一個執行緒?用什麼關鍵字修飾同步方法?stop()和suspend()方法為何不推薦使用?【中等難度】
答:有兩種實現方法,分別是繼承Thread 類與實現Runnable 介面;
用synchronized 關鍵字修飾同步方法;
反對使用stop(),是因為它不安全。它會解除由執行緒獲取的所有鎖定,而且如果物件處於一種不連貫狀態,那麼其他執行緒能在那種狀態下檢查和修改它們。結果很難檢查出真正的問題所在;
suspend()方法容易發生死鎖。呼叫suspend()的時候,目標執行緒會停下來,但卻仍然持有在這之前獲得的鎖定。此時,其他任何執行緒都不能訪問鎖定的資源,除非被“掛起”的執行緒恢復執行。對任何執行緒來說,如果它們想恢復目標執行緒,同時又試圖使用任何一個鎖定的資源,就會造成死鎖。故不應該使用suspend(),
而應在自己的Thread 類中置入一個標誌,指出執行緒應該活動還是掛起。若標誌指出執行緒應該掛起,便用wait()命其進入等待狀態。若標誌指出執行緒應當恢復,則用一個notify()重新啟動執行緒。
30、設計4 個執行緒,其中兩個執行緒每次對j 增加1,另兩個執行緒對j 每次減少1;寫出程式。【中等難度】
答:以下程式使用內部類實現執行緒,對j 增減的時候沒有考慮順序問題:
public class TestThread {
private int j;
public TestThread(int j) {this.j = j;}
private synchronized void inc(){
j++;
System.out.println(j + “–Inc–” +
Thread.currentThread().getName());
}
private synchronized void dec(){
j–;
System.out.println(j + “–Dec–” +
Thread.currentThread().getName());
}
public void run() {
(new Dec()).start();
new Thread(new Inc()).start();
(new Dec()).start();
new Thread(new Inc()).start();
}
class Dec extends Thread {
public void run() {
for(int i=0; i<100; i++){
dec();
}
}
}
class Inc implements Runnable {
public void run() {
for(int i=0; i<100; i++){
inc();
}
}
}
public static void main(String[] args) {
(new TestThread(5)).run();
}
}