Java 面試基礎問題集1

Q. 爲何 -0/3 結果是 0,而 -0.0/3.0 結果是 -0.0?(注意後邊的結果0帶負號)java

A. 在Java裏,整數是用補碼錶示的。在補碼中0只有一種表示方法。另外一方面,浮點數則是用 IEEE 標準表示的, 對於0有兩種表示方法, 0 和 -0。程序員

 

Q. 我能夠用 % 除以一個小數嗎?編程

A. 固然能夠。好比,若是 angle 是一個非負數,那麼 angle % (2 * Math.PI) 就會把 angle 轉換到 0 到 2 π 之間。windows

 

Q. 當 a b 都是基本類型變量時,a += b 和 a = a + b 的效果有區別嗎?數組

A. 當 a 和 b 的類型不一樣時,那兩條語句的效果就可能有區別。 a += b 等同於 a = (int) (a + b),這種狀況下能夠是 a是int型,b是float型。可是同等狀況下 a = a + b就會編譯報錯。數據結構

 

Q. 爲何判斷字符串相等不能使用 == ?函數

A. 這反映了基礎類型(int, double, boolean)和引用類型(String)的區別。性能

 

Q. 有沒有在什麼狀況下,一條語句塊的花括號不能省略的?大數據

A. 在下面的例子中,第一段代碼是合法的,第二段代碼會引起編譯錯誤。從技術角度說,那一條語句是一個變量聲明,而不是語句,因此會報錯。優化

//1 
for(int i=0;i<5;i++){
    int n=10;
}


//2    
for(int i=0;i<5;i++)
   int n=10; // error :Declaration not allowed here

 

Q. 在下面的兩段代碼裏,有沒有狀況,它們的效果不同?

//1
for(int i=0;i<5;i++){
   //TODO
}


//2
int i=0;
while(i<5){
   //TODO
   i++;
}

A. 有的。若是在循環塊裏使用 continue 語句。在for的代碼裏,計數器會加一;而在while的代碼裏,由於被continue略過了,計數器不加一。

 

Q. 使用 int a[] 而不是 int[] a 去聲明一個數組。這二者有什麼區別?

A. 在Java中這兩種用法都是合法的,他們的做用都是同樣的。

前者是在C中的定義數組的方法。後者是JAVA推薦的方法,由於它的寫法 int[] 更能代表這是一個 int 的數組。

 

Q. 爲何數組下標從0 開始而不是從 1 開始?

A. 這種傳統起源於機器語言的編程方法。在機器語言中,數組下標被用來計算元素位置與第一個元素之間的偏移量。若是從1開始的話,計算偏移時還須要作一次減法運算,那是種浪費。

 

Q. 若是用負數做爲數組下標會發生什麼事?

A. 下標小於0或者大於等於數組長度,JAVA運行時會拋出ArrayIndexOutOfBoundsException 異常,而且停止程序運行。

 

Q. 使用數組時還有其餘須要注意的陷阱嗎?

A. 須要記住,JAVA在你建立一個數組時會去初始化它,因此聲明一個數組須要O(N)的時間。

 

Q. 既然 a 是一個數組,爲何 System.out.println(a) 會打印出一個16進制的數,就像 @f62373 這樣,而不是打印出數組的元素?

A. 這條語句打印出的是數組在內存中的地址,不幸的是,在絕大多數狀況下,這不是你須要的。

 

Q. 我能夠從標準input中從新讀一次數據嗎?

A. 不能夠,你只能讀一次。

 

Q. 怎樣輸入 end-of-file (eof) 符號?

A. 操做系統自動包括它了。

 

Q. 使用 printf 時還有哪些用法?

A. 對於整數來講,使用 o 輸出八進制,使用 x 輸出十六進制。對於浮點數來講,使用 e 或者 g 輸出科學計數法形式。

 

Q. 行結束的符號是什麼?

A. 不一樣的文件系統使用了不一樣的符號。在 Unix 系統上,新行的符號是 '\n' ;在Windows 系統上,每一行都有兩個字符組成的字符串終結 "\r\n" ;在 Macs 系統上,終結符號是 "\n\r" 。若是要打印行號,可使用 System.out.println ,或者使用下面的語句獲得當前操做系統下的行結束符:

String newline= System.getProperty("line.separator"); 
 

Q. 下面兩種寫法,哪種更有效率?

//1
String s;
while(!StdId.isEmpty()){
    s=StdIn.readString();
}

        
//2
while(!StdId.isEmpty()){
    String s=StdIn.readString();
}

A. 從效率角度說,二者沒有區別。可是第二種寫法更好,由於它限制了變量的做用域。

 

Q. 爲何不把全部的參數都使用傳值的方式,包括對待數組?

A. 但數組很大時,複製數組須要大量的性能開銷。由於這個緣由,絕大多數變成語言支持把數組傳入函數但不復制一個副本——MATLAB語言除外。

 

Q. 有沒有隻能用循環而不能用遞歸的狀況?

A. 不可能,全部的循環均可以用遞歸替代,雖然大多數狀況下,遞歸須要額外的內存。

 

Q. 有沒有隻能用遞歸而不能用循環的狀況?

A. 不可能,全部的遞歸調用均可以用循環來表示。好比你能夠用while的方式來實現棧。

注:根據代碼的可讀性和效率性之間作權衡選擇循環或遞歸。

Q. 使用遞歸代碼時的空間開銷和重複計算(例如用遞歸解Fibonacci)時須要注意什麼?

A. 在遞歸代碼中建立大數據類型(好比數組)時須要額外注意,隨着遞歸的推動,內存使用將會迅速增長,因爲內存使用增長,操做系統管理內存的時間開銷也會增長。

 

Q. 爲何咱們要花大篇幅來證實一個程序是正確的?

A. 爲了防止錯誤的結果。

二分查找就是一個例子。如今,你懂得了二分查找的原理,你就能把遞歸形式的二分查找改寫成循環形式的二分查找。Knuth 教授在 1946年就發表了二分查找的論文,可是第一個正確的二分查找的程序在 1962年在出現。

 

Q. 在JAVA內建庫中有沒有排序和查找的函數?

A. 有的。在 java.util.Arrays 中包含了 Arrays.sort 和 Arrays.binarySearch 方法。對於Comparable 類型它使用了歸併排序,對於基本數據類型,它使用了快速排序。由於基本類型是值傳遞,快速排序比歸併排序更快並且不須要額外的空間。

 

Q. 爲何JAVA庫不用隨機pivot方式的快速排序?

A. 由於某些程序員在調試代碼時,可能須要肯定性的代碼實現。使用隨機pivot違背了這個原則。

 

Q. 在Java庫中有對stacks 和 queues 的實現嗎?

A. Java庫中內建 java.util.Stack,可是你應該避免使用它若是你須要一個真正的棧的話。由於它是實現了額外的功能,好比訪問第N個元素。另外,它也支持從棧底部插入元素,因此它看上去更像是一個隊列。儘管實現了這些額外的功能對編程人員是一個加分,但是咱們使用數據結構並不僅是想使用全部功能,而是須要咱們正好須要的那種結構。JAVA對於棧的實現就是一個典型的寬接口的例子。

 

Q. 我想使用數組來表示一個包含泛型的棧,可是如下代碼編譯報錯。爲何?

private Item[] a = new Item[max]; 
oldfirst = first;

A. 建立一個泛型數組在 Java 1.5裏不支持。你可使用cast,好比下面的寫法:

private Item[] a = (Item[]) new Object[max]; 
oldfirst = first;

根本的緣由是JAVA中的數組是「協變的(covariant)」,可是泛型並非。好比, String 是 Object的一種子類型,可是 Stack<String>並非 Stack<Object> 的一種子類型。 許多程序員認爲「協變的」數組是JAVA在數據類型方面的一個缺點。可是,若是咱們不考慮泛型,「協變的」數組是有用的,好比實現Arrays.sort(Comparable) 方法,而後當參數是 String時它也能夠被正常調用。

 

Q. 可不能夠在數組上使用 foreach 方式?

A. 能夠的(雖然數組並無實現 Iterator 接口)。請參考下面的代碼:

public static void main(String[] args) { 
    for (String s : args) 
       StdOut.println(s); 
}

Q. 在 linked list 上使用 iterator 是否是比循環或者遞歸更有效率?

A. 編譯器翻譯時,可能把那種「尾遞歸」形式翻譯成等價的循環形式。因此可能並無能夠被觀測到的性能提高。

尾部遞歸是一種編程技巧。若是在遞歸函數中,遞歸調用返回的結果總被直接返回,則稱爲尾部遞歸。尾遞歸是極其重要的,不用尾遞歸,函數的堆棧耗用難以估量,須要保存不少中間函數的堆棧。好比f(n, sum) = f(n-1) + value(n) + sum; 會保存n個函數調用堆棧,而使用尾遞歸f(n, sum) = f(n-1, sum+value(n)); 這樣則只保留後一個函數堆棧便可,以前的可優化刪去。

Q. 自動裝箱機制會怎麼處理下面的狀況?

Integer a = null; 
int b = a;

A. 它將返回一個運行時錯誤。基礎類型不容許它對應的裝箱類型裏的值是null。

Q. 爲何第一組打印的是 true,可是後面兩組打印的是 false?

Integer a1 = 100; 
Integer a2 = 100; 
System.out.println(a1 == a2); // true 

Integer b1 = new Integer(100); 
Integer b2 = new Integer(100); 
System.out.println(b1 == b2); // false 

Integer c1 = 150; 
Integer c2 = 150; 
System.out.println(c1 == c2); // false

A. 第二組代碼打印 false 是由於 b1 和 b2 指向不一樣的 Integer 對象引用。第一組和第三組依賴於自動裝箱機制。使人意外的第一組打印了 true 是由於在 -128 和 127之間的值會自動轉換成一樣的immutable型的Integer 對象。對於超出那個範圍的數,Java會對於每個數建立一個新的Integer對象。

相關文章
相關標籤/搜索