當前位置:才華齋>計算機>java語言>

Java初學者的30個常見問題

java語言 閱讀(1.19W)

大家在學習Java語言時都遇到過哪一些問題呢?本文回答了30個Java入門級初學者的常見問題。希望可以幫助到大家!

Java初學者的30個常見問題

我可以用%除以一個小數嗎? a += b 和 a = a + b 的效果有區別嗎? 宣告一個數組為什麼需要花費大量時間? 為什麼Java庫不用隨機pivot方式的快速排序?

1.2 基本資料型別

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

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

Q. 我可以用 % 除以一個小數嗎?

A. 當然可以。比如,如果 angle 是一個非負數,那麼 angle % (2 * ) 就會把 angle 轉換到 0 到 2 π 之間。

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

A. 當 a 和 b 的型別不同時,那兩條語句的效果就可能有區別。 a += b 等同於 a = (int) (a + b),這種情況下可以是 a是int型,b是float型。但是同等情況下 a = a + b 就會編譯報錯。

1.3 條件語句和迴圈語句

Q. 為什麼判斷字串相等不能使用 == ?

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

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

A. 在下面的例子中,第一段程式碼是合法的,第二段程式碼會引發編譯錯誤。從技術角度說,那一條語句是一個變數宣告,而不是語句,所以會報錯。

// legal for (int i = 0; i <= N; i++) { int x = 5; } // illegal for (int i = 0; i <= N; i++) int x = 5;

Q. 在下面的兩段程式碼裡,有沒有情況,它們的效果不一樣?

for ( ; ) { } ; while () { }

A. 有的。如果在迴圈塊裡使用 continue 語句。在for的程式碼裡,計數器會加一;而在while的程式碼裡,因為被continue略過了,計數器不加一。

1.4 陣列

Q. 某些Java開發人員使用 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[] 是一個數組,為什麼 tln(a) 會打印出一個16進位制的數,就像 @f62373 這樣,而不是打印出陣列的元素?

A. 好問題。這條語句打印出的是 陣列在記憶體中的地址,不幸的是,在絕大多數情況下,這不是你需要的。

1.5 輸入輸出語句

Q. 我可以從標準input中重新讀一次資料嗎?

A. 不可以,你只能讀一次。

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

A. 作業系統自動包括它了。

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

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

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

A. 不同的檔案系統使用了不同的符號。在 Unix 系統上,新行的符號是 '' ;在 Windows 系統上,每一行都有兩個字元組成的字串終結 "" ;在 Macs 系統上,終結符號是 "" 。如果要列印行號,可以使用 tln() ,或者使用下面的語句得到當前作業系統下的行結束符:

String NEWLINE = roperty("rator");

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

String s; while (!pty()) { while (!pty()) { s = String(); String s = String(); ... ... } }

A. 從效率角度說,兩者沒有區別。 但是第二種寫法更好,因為它限制了變數的作用域。

2.1 函式呼叫

Q. 當把陣列當作函式呼叫時的引數時,我常常感到疑惑?

A. 是的。你需要牢記傳值引數(引數是基本變數型別)和傳引用引數(比如陣列)之間的區別。

Q. 那為什麼不把所有的引數都使用傳值的方式,包括對待陣列?

A. 但陣列很大時,複製陣列需要大量的效能開銷。因為這個原因,絕大多數變成語言支援把陣列傳入函式但不復制一個副本——MATLAB語言除外。

2.3 遞迴呼叫

Q. 有沒有隻能用迴圈而不能用遞迴的情況?

A. 不可能,所有的迴圈都可以用遞迴替代,雖然大多數情況下,遞迴需要額外的記憶體。

Q. 有沒有隻能用遞迴而不能用迴圈的情況?

A. 不肯能,所有的遞迴呼叫都可以用迴圈來表示。比如你可以用while的方式來實現棧。

Q. 那我應該選擇哪個,遞迴的方式 還是 迴圈的方式?

A. 根據程式碼的可讀性和效率性之間做權衡。

Q. 我擔心使用遞迴程式碼時的空間開銷和重複計算(例如用遞迴解Fibonacci)的問題。有沒有其他需要擔心的?

A. 在遞迴程式碼中建立大資料型別(比如陣列)時需要額外注意,隨著遞迴的推進,記憶體使用將會迅速增加,由於記憶體使用增加,作業系統管理記憶體的時間開銷也會增加。

4.2 排序與查詢

Q. 為什麼我們要花大篇幅來證明一個程式是正確的?

A. 為了防止錯誤的結果。二分查詢就是一個例子。現在,你懂得了二分查詢的原理,你就能把遞迴形式的二分查詢改寫成迴圈形式的二分查詢。Knuth 教授在 1946年就發表了二分查詢的論文,但是第一個正確的二分查詢的程式在 1962年在出現。

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

A. 有的。在 ys 中包含了 () 和 rySearch() 方法。對於Comparable 型別它使用了 歸併排序,對於基本資料型別,它使用了快速排序。因為基本型別是值傳遞,快速排序比歸併排序更快而且不需要額外的空間。

Q. 為什麼JAVA庫不用 隨機pivot方式的快速排序?

A. 好問題。 因為某些程式設計師在除錯程式碼時,可能需要確定性的程式碼實現。使用隨機pivot違背了這個原則。

4.3 棧和佇列

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

A. Java庫中內建 k,但是你應該避免使用它如果你需要一個真正的棧的話。因為它是實現了額外的功能,比如訪問第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並不是 Stack