卓越分享丨Java 語言中十大“坑爹”功能

卓越分享丨Java 語言中十大“坑爹”功能

作者 | 踐行精神自由

作為一門面向物件的程式語言,Java憑藉其簡單易用、功能強大的特點受到了廣大程式設計愛好者的青睞,伴隨著開源社群的推波助瀾,Java語言更是席捲全球,勢不可擋,在世界各地都有Java技術的從業者,它也常年高居程式語言排行榜的首位,足以表明Java的強悍與王者之風。

然而,即便是如此強大的程式語言,也有很多“坑爹”的功能,稍不注意,我們就會掉入坑裡,輕則遭到同事的嘲笑和鄙視,重則造成悲慘後果而不得不跑路。

當然,坑爹這個詞加上了雙引號,因為大部分時候,都是由於我們不夠熟練、違反我們的常識才造成了令人不愉快的後果。

今天我們就來梳理一下Java中最“坑爹”、最違反常識的功能點,以排行榜的方式釋出,以饗讀者。說明一下,本文中的程式碼基於JDK8來編譯實現。

01

switch必須加上break才結束

對於多重分支選擇,一系列的if-else-if語句會讓程式碼的可讀性變差,建議使用switch語句來代替,然而switch case中的分支判斷,必須加上break語句才會中止其它case的執行,比如:

int count = 1;switch(count){ case 1: System。out。println(“one”); case 2: System。out。println(“two”); case 3: System。out。println(“three”);}

上面的程式碼會輸出:

onetwothree

然而,這並不是我們想要的,或者說違反了我們的常識。滿足了某種條件,當然就只需要執行這種條件下的邏輯即可,其他的case應該不予理會、直接跳過,象上面這段程式碼,只需要輸出one就行了。當然,在每個case結尾處加上break就可以達到我們期望的效果。

這個功能點稍顯“坑爹”,也是初學者常犯的錯誤,所以它也光榮上榜,排名第10位。

02

邏輯運算子的“短路”現象

使用邏輯運算子時,我們會遇到“短路”的現象:一旦能夠確定整個表示式的值,就不會計算餘下的部分了,當然,這個功能點其實是非常有用的,但對於初學者來說,可能會感覺比較驚訝,使用不當就會產生“坑爹”後果。比如下面的程式碼:

int num = 1;System。out。println(false && ((num++)==1));System。out。println(num);

就會輸出false和1,因為邏輯與&&的前半部分為false,不管後半部分為true還是false,整個表示式都會返回false,所以就不會再計算後面的部分了,如果把false改成true,那麼後半部分就會得到執行,num也就變成2了。

它在“坑爹”榜單中位列第9位。

03

陣列下標從零開始

Java程式設計師都清楚,陣列的下標是從零開始的,比如,我們要遍歷一個數組,可以採用如下的方式:

int[] arr = new int[]{1,3,5,7,9};for(int i=0;i

這跟我們日常生活中的經驗是相違背的,正常情況都是從第1個元素開始計數的,特別是對於初學者來說有點難以接受,會覺得很驚訝。即使對於經驗豐富的程式設計師來說,有些地方也需要格外注意,比如:

String str = “hello world”;System。out。println(str。charAt(1));

我們知道,charAt的作用是獲取字串中某個位置的字元,然而,上面的程式碼並不是輸出第一個字元h,而是e,因為陣列是從零開始計數的,這個也是比較“坑爹”啊。當然,設計者這麼做的原因是考慮到了記憶體偏移量的因素。

每次在編寫這樣的程式碼時,都需要做這樣的1到0的對映和轉換(熟練了就是下意識的轉換),確實也有點“坑爹”,所以它也不能倖免,排在第8位。

04

ArrayList遍歷刪除時報錯

Talk is cheap,先上程式碼:

public static void main(String[] args) { List list = new ArrayList(); list。add(“abc”); list。add(“bc”); list。add(“bc”); list。add(“abcd”); list。add(“abcdef”); //報錯 int length = list。size(); for(int i = 0;i < length;i++){ if(list。get(i)。equals(“bc”)){ list。remove(i); } }}

想從ArrayList中刪除某個元素,於是,我們就寫了上面的程式碼,但是它卻丟擲了IndexOutOfBoundsException異常,原因是ArrayList在刪除元素後會重新計算數量,把list。size放在for迴圈中即可:

for(int i=0;i

當然,這種方法也存在問題,建議使用迭代器的方式來刪除元素。

對於不太熟練的程式設計師來說,有時候就會掉入這樣的陷阱之中。這是排名第7的情況。

05

字元轉成數字的坑

有時候,我們想把字元直接透過型別轉換變成整數,比如像下面這樣:

char symbol = ‘8’;System。out。println((int) symbol);

我們想要的結果是8,然而,上面的程式碼卻輸出了56,略顯“坑爹”,具體原因參考ASCII的知識。

06

while迴圈體的“障眼法”

對於while迴圈語句,如果你沒有加上大括號,即使後面的語句挨在一起,也只會執行第一條statement,比如:

int i = 0;while(i++<3) System。out。print(“A”); System。out。print(“B”);

上面的程式碼會輸出:

AAAB

而不是3個A、3個B,更“坑爹”的是,如果兩條語句放在一行上,迷惑性會更大:

int i = 0;while(i++<3) System。out。print(“A”);System。out。print(“B”);

上面這種寫法同樣是輸出AAAB。所以,象這樣的情況,哪怕只有一條語句,也建議加上大括號,完美避坑。

07

Integer類有快取

這個功能點也是面試的高頻熱點之一,稍不注意,也有可能被帶入溝裡,我們看看下面這段程式碼:

public static void main(String[] args){ Integer a = 100; Integer b = 100; Integer c = 200; Integer d = 200; System。out。println(a==b); System。out。println(c==d);}

上面的程式碼竟然輸出:

truefalse

這確實太出乎意料了,同樣的程式碼,只是數值不同(而且差別不太大的樣子),就產生了不一樣的輸出,這也太離譜了。原來,Integer中有一個靜態內部類IntegerCache,在類載入的時候,它會把[-128, 127]之間的值快取起來,而Integer a = 100這樣的賦值方式,會首先呼叫Integer類中的靜態valueOf方法,這個方法會嘗試從快取裡取值,如果在這個範圍之內就不用重新new一個物件了:

public static Integer valueOf(int i) { if (i >= IntegerCache。low && i <= IntegerCache。high) return IntegerCache。cache[i + (-IntegerCache。low)]; return new Integer(i);}

此功能入選“坑爹”排行榜的第4名。

08

空方法體導致死迴圈

如果迴圈的方法體為空,則會導致死迴圈,比如,下面的程式碼打印出數字1,2,3:

int i = 1;while(i<4){ System。out。println(i++);}

如果你在敲鍵盤的時候,不小心在while結尾處加了一個分號(如果方法體沒有加大括號,更容易產生這種情況):

int i = 1;while(i<4);{ System。out。println(i++);}

你猜怎麼著,上面的程式碼可以正常編譯並執行,然而,它卻陷入了死迴圈……是不是非常“坑爹”?for迴圈也存在類似的情況。

它高居排行榜的第3位。

09

神奇的=+

我們知道,對於類似a=a+b這樣的賦值語句,有一種簡寫方式:a +=b,然而,如果你不小心寫成了a =+ b,結果又會是什麼呢?我們看看下面的程式碼:

int i = 100;i =+ 2; //注意,加號在後面System。out。println(i);

上面的程式碼既不會輸出102,也不會報錯,而是輸出2,這的確出乎意料,完全不是我們期望的結果,太神奇了,非常的“坑爹”。

所以,它排名第2,穩居榜眼的位置。

10

Java註釋能夠識別Unicode

先看看程式碼:

public static void main(String[] args){ // \u000d System。out。println(“Hello World!”);}

乍一看,程式碼都被註釋掉了,當然不會輸出任何東西,然而,它還是輸出每個程式設計師都倍感親切的Hello World,這是因為,unicode解碼發生在程式碼編譯之前,編譯器將\u樣式的程式碼進行文字轉義,即使是註釋也是這樣,然後\u000a被轉換成\n換行符,所以println程式碼得以正常執行。

這樣的功能著實“坑爹”,極其違反常識,它必須要上榜,必須要榮登狀元的位置。

以上就是編者總結的Java語言中十大“坑爹”的功能點,你是否認同這樣的排名?你覺得有哪些功能更應該入選此榜單?歡迎後臺留言討論!