1. 程式人生 > >Java筆試題和解答精選

Java筆試題和解答精選

 都是一些非常非常基礎的題,是我最近參加各大IT公司筆試後靠記憶記下來的,經過整理獻給與我一樣參加各大IT校園招聘的同學們,純考Java基礎功底,老手們就不用進來了,免得笑話我們這些未出校門的孩紙們,但是IT公司就喜歡考這些基礎的東西,所以為了能進大公司就~~~當複習期末考吧。花了不少時間整理,在整理過程中也學到了很多東西,請大家認真對待每一題~~~ 下面都是我自己的答案非官方,僅供參考,如果有疑問或錯誤請一定要提出來,大家一起進步啦~~~ 1. 下面哪些是Thread類的方法()

A start()       B run()       C exit()       D getPriority()

答案:ABD

解析:看Java API docs吧:http://docs.oracle.com/javase/7/docs/api/,exit()是System類的方法,如System.exit(0)。

2. 下面關於java.lang.Exception類的說法正確的是()

A 繼承自Throwable      B Serialable      CD 不記得,反正不正確

答案:A

解析:Java異常的基類為java.lang.Throwable,java.lang.Error和java.lang.Exception繼承 Throwable,RuntimeException和其它的Exception等繼承Exception,具體的RuntimeException繼承RuntimeException。

擴充套件:錯誤和異常的區別(Error vs Exception) 

1) java.lang.Error: Throwable的子類,用於標記嚴重錯誤。合理的應用程式不應該去try/catch這種錯誤。絕大多數的錯誤都是非正常的,就根本不該出現的。
java.lang.Exception
: Throwable的子類,用於指示一種合理的程式想去catch的條件。即它僅僅是一種程式執行條件,而非嚴重錯誤,並且鼓勵使用者程式去catch它。

2)  Error和RuntimeException 及其子類都是未檢查的異常(unchecked exceptions),而所有其他的Exception類都是檢查了的異常(checked exceptions).
checked exceptions: 

通常是從一個可以恢復的程式中丟擲來的,並且最好能夠從這種異常中使用程式恢復。比如FileNotFoundException, ParseException等。檢查了的異常發生在編譯階段,必須要使用try…catch(或者throws)否則編譯不通過。
unchecked exceptions: 通常是如果一切正常的話本不該發生的異常,但是的確發生了。發生在執行期,具有不確定性,主要是由於程式的邏輯問題所引起的。比如ArrayIndexOutOfBoundException, ClassCastException等。從語言本身的角度講,程式不該去catch這類異常,雖然能夠從諸如RuntimeException這樣的異常中catch並恢復,但是並不鼓勵終端程式設計師這麼做,因為完全沒要必要。因為這類錯誤本身就是bug,應該被修復,出現此類錯誤時程式就應該立即停止執行。 因此,面對Errors和unchecked exceptions應該讓程式自動終止執行,程式設計師不該做諸如try/catch這樣的事情,而是應該查明原因,修改程式碼邏輯。

RuntimeException:RuntimeException體系包括錯誤的型別轉換、陣列越界訪問和試圖訪問空指標等等。

處理RuntimeException的原則是:如果出現 RuntimeException,那麼一定是程式設計師的錯誤。例如,可以通過檢查陣列下標和陣列邊界來避免陣列越界訪問異常。其他(IOException等等)checked異常一般是外部錯誤,例如試圖從檔案尾後讀取資料等,這並不是程式本身的錯誤,而是在應用環境中出現的外部錯誤。 

3. 下面程式的執行結果是()

String str1 = "hello";
String str2 = "he" + new String("llo");
System.err.println(str1 == str2);

答案:false

解析:因為str2中的llo是新申請的記憶體塊,而==判斷的是物件的地址而非值,所以不一樣。如果是String str2 = str1,那麼就是true了。

4. 下列說法正確的有()

A. class中的constructor不可省略

B. constructor必須與class同名,但方法不能與class同名

C. constructor在一個物件被new時執行

D.一個class只能定義一個constructor

答案:C 

解析:這裡可能會有誤區,其實普通的類方法是可以和類名同名的,和構造方法唯一的區分就是,構造方法沒有返回值。

5. 具體選項不記得,但用到的知識如下:

String []a = new String[10];

則:a[0]~a[9] = null

a.length = 10

如果是int []a = new int[10];

則:a[0]~a[9] = 0

a.length = 10

6. 下面程式的執行結果:()

複製程式碼
    public static void main(String args[]) {

        Thread t = new Thread() {

            public void run() {
                pong();
            }
        };

        t.run();
        System.out.print("ping");

    }

    static void pong() {

        System.out.print("pong");

    }
複製程式碼

A pingpong        B pongping       C pingpong和pongping都有可能       D 都不輸出

答案:B

解析:這裡考的是Thread類中start()和run()方法的區別了。start()用來啟動一個執行緒,當呼叫start方法後,系統才會開啟一個新的執行緒,進而呼叫run()方法來執行任務,而單獨的呼叫run()就跟呼叫普通方法是一樣的,已經失去執行緒的特性了。因此在啟動一個執行緒的時候一定要使用start()而不是run()。

7. 下列屬於關係型資料庫的是()

A. Oracle    B MySql    C IMS     D MongoDB

答案:AB

解答:IMS(Information Management System )資料庫是IBM公司開發的兩種資料庫型別之一; 

一種是關係資料庫,典型代表產品:DB2;

另一種則是層次資料庫,代表產品:IMS層次資料庫。

非關係型資料庫有MongoDB、memcachedb、Redis等

8. GC執行緒是否為守護執行緒?()

答案:是

解析:執行緒分為守護執行緒和非守護執行緒(即使用者執行緒)。

只要當前JVM例項中尚存在任何一個非守護執行緒沒有結束,守護執行緒就全部工作;只有當最後一個非守護執行緒結束時,守護執行緒隨著JVM一同結束工作。 守護執行緒最典型的應用就是 GC (垃圾回收器)

9. volatile關鍵字是否能保證執行緒安全?()

答案:不能

解析:volatile關鍵字用在多執行緒同步中,可保證讀取的可見性,JVM只是保證從主記憶體載入到執行緒工作記憶體的值是最新的讀取值,而非cache中。但多個執行緒對

volatile的寫操作,無法保證執行緒安全。例如假如執行緒1,執行緒2 在進行read,load 操作中,發現主記憶體中count的值都是5,那麼都會載入這個最新的值,線上程1堆count進行修改之後,會write到主記憶體中,主記憶體中的count變數就會變為6;執行緒2由於已經進行read,load操作,在進行運算之後,也會更新主記憶體count的變數值為6;導致兩個執行緒及時用volatile關鍵字修改之後,還是會存在併發的情況。

10. 下列說法正確的是()

A LinkedList繼承自List

B AbstractSet繼承自Set

C HashSet繼承自AbstractSet

D WeakMap繼承自HashMap

答案:AC

解析:下面是一張下載的Java中的集合型別的繼承關係圖,一目瞭然。

11. 存在使i + 1 < i的數嗎()

答案:存在

解析:如果i為int型,那麼當i為int能表示的最大整數時,i+1就溢位變成負數了,此時不就<i了嗎。

擴充套件:存在使i > j || i <= j不成立的數嗎()

答案:存在

解析:比如Double.NaN或Float.NaN,感謝@BuilderQiu網友指出。

12. 0.6332的資料型別是()

A float     B double     C Float      D Double

答案:B

解析:預設為double型,如果為float型需要加上f顯示說明,即0.6332f

13. 下面哪個流類屬於面向字元的輸入流(  )

A  BufferedWriter           B  FileInputStream          C  ObjectInputStream          D  InputStreamReader

 答案:D

 解析:Java的IO操作中有面向位元組(Byte)和麵向字元(Character)兩種方式。
面向位元組的操作為以8位為單位對二進位制的資料進行操作,對資料不進行轉換,這些類都是InputStream和OutputStream的子類。
面向字元的操作為以字元為單位對資料進行操作,在讀的時候將二進位制資料轉為字元,在寫的時候將字元轉為二進位制資料,這些類都是Reader和Writer的子類。

總結:以InputStream(輸入)/OutputStream(輸出)為字尾的是位元組流;

          以Reader(輸入)/Writer(輸出)為字尾的是字元流。

擴充套件:Java流類圖結構,一目瞭然,解決大部分選擇題:

14. Java介面的修飾符可以為()

A private     B protected     C final       D abstract

答案:CD

解析:介面很重要,為了說明情況,這裡稍微囉嗦點:

(1)介面用於描述系統對外提供的所有服務,因此介面中的成員常量和方法都必須是公開(public)型別的,確保外部使用者能訪問它們;

(2)介面僅僅描述系統能做什麼,但不指明如何去做,所以介面中的方法都是抽象(abstract)方法;

(3)介面不涉及和任何具體例項相關的細節,因此介面沒有構造方法,不能被例項化,沒有例項變數,只有靜態(static)變數;

(4)介面的中的變數是所有實現類共有的,既然共有,肯定是不變的東西,因為變化的東西也不能夠算共有。所以變數是不可變(final)型別,也就是常量了。

(5) 介面中不可以定義變數?如果介面可以定義變數,但是介面中的方法又都是抽象的,在介面中無法通過行為來修改屬性。有的人會說了,沒有關係,可以通過 實現介面的物件的行為來修改介面中的屬性。這當然沒有問題,但是考慮這樣的情況。如果介面 A 中有一個public 訪問許可權的靜態變數 a。按照 Java 的語義,我們可以不通過實現介面的物件來訪問變數 a,通過 A.a = xxx; 就可以改變介面中的變數 a 的值了。正如抽象類中是可以這樣做的,那麼實現介面 A 的所有物件也都會自動擁有這一改變後的 a 的值了,也就是說一個地方改變了 a,所有這些物件中 a 的值也都跟著變了。這和抽象類有什麼區別呢,怎麼體現介面更高的抽象級別呢,怎麼體現介面提供的統一的協議呢,那還要介面這種抽象來做什麼呢?所以介面中 不能出現變數,如果有變數,就和介面提供的統一的抽象這種思想是抵觸的。所以介面中的屬性必然是常量,只能讀不能改,這樣才能為實現介面的物件提供一個統 一的屬性。

通俗的講,你認為是要變化的東西,就放在你自己的實現中,不能放在介面中去,介面只是對一類事物的屬性和行為更高層次的抽象。對修改關閉,對擴充套件(不同的實現 implements)開放,介面是對開閉原則的一種體現。

所以:

介面的方法預設是public abstract;

介面中不可以定義變數即只能定義常量(加上final修飾就會變成常量)。所以介面的屬性預設是public static final 常量,且必須賦初值

注意:final和abstract不能同時出現。

15. 不通過建構函式也能建立物件嗎()

A 是     B 否

答案:A

解析:Java建立物件的幾種方式(重要):

(1) 用new語句建立物件,這是最常見的建立物件的方法。
(2) 運用反射手段,呼叫java.lang.Class或者java.lang.reflect.Constructor類的newInstance()例項方法。
(3) 呼叫物件的clone()方法。
(4) 運用反序列化手段,呼叫java.io.ObjectInputStream物件的 readObject()方法。

(1)和(2)都會明確的顯式的呼叫建構函式 ;(3)是在記憶體上對已有物件的影印,所以不會呼叫建構函式 ;(4)是從檔案中還原類的物件,也不會呼叫建構函式。

16. ArrayList list = new ArrayList(20);中的list擴充幾次()

A 0     B 1     C 2      D 3

答案:A

解析:這裡有點迷惑人,大家都知道預設ArrayList的長度是10個,所以如果你要往list裡新增20個元素肯定要擴充一次(擴充為原來的1.5倍),但是這裡顯示指明瞭需要多少空間,所以就一次性為你分配這麼多空間,也就是不需要擴充了。

17. 下面哪些是對稱加密演算法()

A DES   B AES   C DSA   D RSA

答案:AB

解析:常用的對稱加密演算法有:DES、3DES、RC2、RC4、AES

常用的非對稱加密演算法有:RSA、DSA、ECC

使用單向雜湊函式的加密演算法:MD5、SHA

18.新建一個流物件,下面哪個選項的程式碼是錯誤的?(

Anew BufferedWriter(new FileWriter("a.txt"));

Bnew BufferedReader(new FileInputStream("a.dat"));

Cnew GZIPOutputStream(new FileOutputStream("a.zip"));

Dnew ObjectInputStream(new FileInputStream("a.dat"));

答案:B

解析:請記得13題的那個圖嗎?Reader只能用FileReader進行例項化。

19. 下面程式能正常執行嗎()

複製程式碼
public class NULL {

    public static void haha(){
        System.out.println("haha");
    }
    public static void main(String[] args) {
        ((NULL)null).haha();
    }

}
複製程式碼

答案:能正常執行

解析:輸出為haha,因為null值可以強制轉換為任何java類型別,(String)null也是合法的。但null強制轉換後是無效物件,其返回值還是為null,而static方法的呼叫是和類名繫結的,不借助物件進行訪問所以能正確輸出。反過來,沒有static修飾就只能用物件進行訪問,使用null呼叫物件肯定會報空指標錯了。這裡和C++很類似。這裡感謝@Florian網友解答。

20. 下面程式的執行結果是什麼()

複製程式碼
class HelloA {

    public HelloA() {
        System.out.println("HelloA");
    }
    
    { System.out.println("I'm A class"); }
    
    static { System.out.println("static A"); }

}

public class HelloB extends HelloA {
    public HelloB() {
        System.out.println("HelloB");
    }
    
    { System.out.println("I'm B class"); }
    
    static { System.out.println("static B"); }
    
    public static void main(String[] args) { 
     new HelloB(); 
   }

}
複製程式碼

答案:

static A
static B
I'm A class
HelloA
I'm B class
HelloB

解析:說實話我覺得這題很好,考查靜態語句塊、構造語句塊(就是隻有大括號的那塊)以及建構函式的執行順序。

物件的初始化順序:(1)類載入之後,按從上到下(從父類到子類)執行被static修飾的語句;(2)當static語句執行完之後,再執行main方法;(3)如果有語句new了自身的物件,將從上到下執行構造程式碼塊、構造器(兩者可以說繫結在一起)。

下面稍微修改下上面的程式碼,以便更清晰的說明情況:

 View Code

此時輸出結果為:

複製程式碼
static A
static B
-------main start-------
I'm A class
HelloA
I'm B class
HelloB
I'm A class
HelloA
I'm B class
HelloB
-------main end-------
複製程式碼

21. getCustomerInfo()方法如下,try中可以捕獲三種類型的異常,如果在該方法執行中產生了一個IOException,將會輸出什麼結果(

複製程式碼
    public void getCustomerInfo() {

        try {

            // do something that may cause an Exception

        } catch (java.io.FileNotFoundException ex) {

            System.out.print("FileNotFoundException!");

        } catch (java.io.IOException ex) {

            System.out.print("IOException!");

        } catch (java.lang.Exception ex) {

            System.out.print("Exception!");

        }

    }
複製程式碼

IOException!

BIOException!Exception!

CFileNotFoundException!IOException!

DFileNotFoundException!IOException!Exception!

答案:A

解析:考察多個catch語句塊的執行順序。當用多個catch語句時,catch語句塊在次序上有先後之分。從最前面的catch語句塊依次先後進行異常型別匹配,這樣如果父異常在子異常類之前,那麼首先匹配的將是父異常類,子異常類將不會獲得匹配的機會,也即子異常型別所在的catch語句塊將是不可到達的語句。所以,一般將父類異常類即Exception老大放在catch語句塊的最後一個。

22. 下面程式碼的執行結果為:()

複製程式碼
import java.io.*;
import java.util.*;

public class foo{

    public static void main (String[] args){

        String s;

        System.out.println("s=" + s);

    }

}
複製程式碼

程式碼得到編譯,並輸出“s=

程式碼得到編譯,並輸出“s=null

由於String s沒有初始化,程式碼不能編譯通過

程式碼得到編譯,但捕獲到 NullPointException異常

答案:C

解析:開始以為會輸出null什麼的,執行後才發現Java中所有定義的基本型別或物件都必須初始化才能輸出值。

23.  System.out.println("5" + 2);的輸出結果應該是()。

52                   B7                     C2                     D5

答案:A

解析:沒啥好說的,Java會自動將2轉換為字串。

24. 指出下列程式執行的結果 

複製程式碼
public class Example {

    String str = new String("good");

    char[] ch = { 'a', 'b', 'c' };

    public static void main(String args[]) {

        Example ex = new Example();

        ex.change(ex.str, ex.ch);

        System.out.print(ex.str + " and ");

        System.out.print(ex.ch);

    }

    public void change(String str, char ch[]) {

        str = "test ok";

        ch[0] = 'g';

    }
}
複製程式碼

A good and abc

B good and gbc

C test ok and abc

D test ok and gbc 

答案:B

解析:大家可能以為Java中String和陣列都是物件所以肯定是物件引用,然後就會選D,其實這是個很大的誤區:因為在java裡沒有引用傳遞,只有值傳遞

這個值指的是實參的地址的拷貝,得到這個拷貝地址後,你可以通過它修改這個地址的內容(引用不變),因為此時這個內容的地址和原地址是同一地址,

但是你不能改變這個地址本身使其重新引用其它的物件,也就是值傳遞,可能說的不是很清楚,下面給出一個完整的能說明情況的例子吧:

 View Code

程式有些囉嗦,但能反映問題,該程式執行結果為:

複製程式碼
物件交換前:p1 = Alexia female
物件交換前:p2 = Edward male

物件交換後:p1 = Alexia female
物件交換後:p2 = Edward male

物件陣列交換前:arraya[0] = Alexia female, arraya[1] = Edward male
物件陣列交換前:arrayb[0] = jmwang female, arrayb[1] = hwu male

物件陣列交換後:arraya[0] = Alexia female, arraya[1] = Edward male
物件陣列交換後:arrayb[0] = jmwang female, arrayb[1] = hwu male

基本型別陣列交換前:a[0] = 0, a[1] = 1
基本型別陣列交換前:b[0] = 1, b[1] = 2

基本型別陣列交換後:a[0] = 0, a[1] = 1
基本型別陣列交換後:b[0] = 1, b[1] = 2

物件陣列內容交換並改變後:arraya[1] = wjl male
物件陣列內容交換並改變後:arrayb[1] = Edward male

基本型別陣列內容交換並改變後:a[1] = 5
基本型別陣列內容交換並改變後:b[1] = 1
複製程式碼

說明:不管是物件、基本型別還是物件陣列、基本型別陣列,在函式中都不能改變其實際地址但能改變其中的內容。

25. 要從檔案"file.dat"中讀出第10個位元組到變數c,下列哪個方法適合

AFileInputStream in=new FileInputStream("file.dat"); in.skip(9); int c=in.read();

FileInputStream in=new FileInputStream("file.dat"); in.skip(10); int c=in.read();

CFileInputStream in=new FileInputStream("file.dat"); int c=in.read();

RandomAccessFile in=new RandomAccessFile("file.dat"); in.skip(9); int c=in.readByte();

答案:A?D?

解析:long skip(long n)作用是跳過n個位元組不讀,主要用在包裝流中的,因為一般流(如FileInputStream)只能順序一個一個的讀不能跳躍讀,但是包裝流可以用skip方法跳躍讀取。那麼什麼是包裝流呢?各種位元組節點流類,它們都只具有讀寫位元組內容的方法,以FileInputStream與FileOutputStream為例,它們只能在檔案中讀取或者向檔案中寫入位元組,在實際應用中我們往往需要在檔案中讀取或者寫入各種型別的資料,就必須先將其他型別的資料轉換成位元組陣列後寫入檔案,或者從檔案中讀取到的位元組陣列轉換成其他資料型別,想想都很麻煩!!因此想通過FileOutputStream將一個浮點小數寫入到檔案中或將一個整數寫入到檔案時是非常困難的。這時就需要包裝類DataInputStream/DataOutputStream,它提供了往各種輸入輸出流物件中讀入或寫入各種型別的資料的方法。

DataInputStream/DataOutputStream並沒有對應到任何具體的流裝置,一定要給它傳遞一個對應具體流裝置的輸入或輸出流物件,完成類似 DataInputStream/DataOutputStream功能的類就是一個包裝類,也叫過濾流類或處理流類。它對InputOutStream/OutputStream流類進行了包裝,使程式設計人員使用起來更方便。其中DataInputStream包裝類的建構函式語法:public DataInputStream(InputStream in)。包裝類也可以包裝另外一個包裝類。

首先BC肯定 是錯的,那A正確嗎?按上面的解析應該也不對,但我試了下,發現A也是正確的,與網上解析的資料有些出入,下面是我的code:

 View Code

那麼D呢,RandomAccessFile是IO包的類,但是其自成一派,從Object直接繼承而來。可以對檔案進行讀取和寫入。支援檔案的隨機訪問,即可以隨機讀取檔案中的某個位置內容,這麼說RandomAccessFile肯定可以達到題目的要求,但是選項有些錯誤,比如RandomAccessFile的初始化是兩個引數而非一個引數,採用的跳躍讀取方法是skipBytes()而非skip(),即正確的寫法是:

RandomAccessFile in = new RandomAccessFile("file.dat", "r");
in.skipBytes(9);
int c = in.readByte();

這樣也能讀到第十個位元組,也就是A和D都能讀到第十個位元組,那麼到底該選哪個呢?A和D有啥不同嗎?求大神解答~~~

26. 下列哪種異常是檢查型異常,需要在編寫程式時宣告 

ANullPointerException        BClassCastException      CFileNotFoundException       D IndexOutOfBoundsException

答案:C

解析:看第2題的解析。

27. 下面的方法,當輸入為2的時候返回值是多少?

複製程式碼
    public static int getValue(int i) {
        int result = 0;
        switch (i) {
        case 1:
            result = result + i;
        case 2:
            result = result + i * 2;
        case 3:
            result = result + i * 3;
        }
        return result;
    }
複製程式碼

A0                    B2                    C4                     D10

答案:D

解析:注意這裡case後面沒有加break,所以從case 2開始一直往下執行。

28. 選項中哪一行程式碼可以替換題目中//add code here而不產生編譯錯誤?(

複製程式碼
public abstract class MyClass {
public int constInt = 5; //add code here public void method() { } }
複製程式碼

Apublic abstract void method(int a);

B constInt = constInt + 5;

public int method();

public abstract void anotherMethod() {}

答案:A

解析:考察抽象類的使用。

抽象類遵循的原則:

(1)abstract關鍵字只能修飾類和方法,不能修飾字段。 (2)抽象類不能被例項化(無法使用new關鍵字建立物件例項),只能被繼承。 (3)抽象類可以包含屬性,方法,構造方法,初始化塊,內部類,列舉類,和普通類一樣,普通方法一定要實現,變數可以初始化或不初始化但不能初始化後在抽象類中重新賦值或操作該變數(只能在子類中改變該變數)。 (4)抽象類中的抽象方法(加了abstract關鍵字的方法)不能實現。 (5)含有抽象方法的類必須定義成抽象類。 擴充套件:抽象類和介面的區別,做個總結吧:

(1)介面是公開的,裡面不能有私有的方法或變數,是用於讓別人使用的,而抽象類是可以有私有方法或私有變數的。

(2)abstract class 在 Java 語言中表示的是一種繼承關係,一個類只能使用一次繼承關係。但是,一個類卻可以實現多個interface,實現多重繼承。介面還有標識(裡面沒有任何方法,如Remote介面)和資料共享(裡面的變數全是常量)的作用。

(3)在abstract class 中可以有自己的資料成員,也可以有非abstarct的成員方法,而在interface中,只能夠有靜態的不能被修改的資料成員(也就是必須是 static final的,不過在 interface中一般不定義資料成員),所有的成員方法預設都是 public abstract 型別的。

(4)abstract class和interface