Java 語言中十大「坑爹」功能!

做爲一門面向對象的編程語言,Java憑藉其簡單易用、功能強大的特色受到了廣大編程愛好者的青睞,伴隨着開源社區的推波助瀾,Java語言更是席捲全球,勢不可擋,在世界各地都有Java技術的從業者,它也常年高居編程語言排行榜的首位,足以代表Java的強悍與王者之風。
然而,即使是如此強大的編程語言,也有不少「坑爹」的功能,稍不注意,咱們就會掉入坑裏,輕則遭到同事的嘲笑和鄙視,重則形成悲慘後果而不得不跑路。
固然,坑爹這個詞加上了雙引號,由於大部分時候,都是因爲咱們不夠熟練、違反咱們的常識才形成了使人不愉快的後果。
今天咱們就來梳理一下Java中最「坑爹」、最違反常識的功能點,以排行榜的方式發佈,以饗讀者。說明一下,本文中的代碼基於JDK8來編譯實現。程序員

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");
}數組

上面的代碼會輸出:
one
two
three
然而,這並非咱們想要的,或者說違反了咱們的常識。知足了某種條件,固然就只須要執行這種條件下的邏輯便可,其餘的case應該不予理會、直接跳過,象上面這段代碼,只須要輸出one就好了。固然,在每一個case結尾處加上break就能夠達到咱們指望的效果。緩存

這個功能點稍顯「坑爹」,也是初學者常犯的錯誤,因此它也光榮上榜,排名第10位。
邏輯運算符的「短路」現象編程語言

使用邏輯運算符時,咱們會遇到「短路」的現象:一旦可以肯定整個表達式的值,就不會計算餘下的部分了,固然,這個功能點實際上是很是有用的,但對於初學者來講,可能會感受比較驚訝,使用不當就會產生「坑爹」後果。好比下面的代碼:ide

int num = 1;
System.out.println(false && ((num++)==1));
System.out.println(num);設計

就會輸出false和1,由於邏輯與&&的前半部分爲false,無論後半部分爲true仍是false,整個表達式都會返回false,因此就不會再計算後面的部分了,若是把false改爲true,那麼後半部分就會獲得執行,num也就變成2了。
它在「坑爹」榜單中位列第9位。
數組下標從零開始code

Java程序員都清楚,數組的下標是從零開始的,好比,咱們要遍歷一個數組,能夠採用以下的方式:對象

int[] arr = new int[]{1,3,5,7,9};
for(int i=0;i<arr.length;i++){
System.out.println("the element is:"+arr[i]);
}

這跟咱們平常生活中的經驗是相違背的,正常狀況都是從第1個元素開始計數的,特別是對於初學者來講有點難以接受,會以爲很驚訝。即便對於經驗豐富的程序員來講,有些地方也須要格外注意,好比:

String str = "hello world";
System.out.println(str.charAt(1));

咱們知道,charAt的做用是獲取字符串中某個位置的字符,然而,上面的代碼並非輸出第一個字符h,而是e,由於數組是從零開始計數的,這個也是比較「坑爹」啊。固然,設計者這麼作的緣由是考慮到了內存偏移量的因素。
每次在編寫這樣的代碼時,都須要作這樣的1到0的映射和轉換(熟練了就是下意識的轉換),確實也有點「坑爹」,因此它也不能倖免,排在第8位。
ArrayList遍歷刪除時報錯

Talk is cheap,先上代碼:

public static void main(String[] args) {
List<String> list = new ArrayList<String>();
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<list.size();i++){
if(list.get(i).equals("bc")){
list.remove(i);
}
}

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

對於不太熟練的程序員來講,有時候就會掉入這樣的陷阱之中。這是排名第7的狀況。

字符轉成數字的坑

有時候,咱們想把字符直接經過類型轉換變成整數,好比像下面這樣:

char symbol = '8';
System.out.println((int) symbol);

咱們想要的結果是8,然而,上面的代碼卻輸出了56,略顯「坑爹」,具體緣由參考ASCII的知識。

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。因此,象這樣的狀況,哪怕只有一條語句,也建議加上大括號,完美避坑。
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);
}

上面的代碼居然輸出:

true
false

這確實太出乎意料了,一樣的代碼,只是數值不一樣(並且差異不太大的樣子),就產生了不同的輸出,這也太離譜了。原來,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名。

空方法體致使死循環

若是循環的方法體爲空,則會致使死循環,好比,下面的代碼打印出數字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位。

神奇的=+

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

int i = 100;

i =+ 2; //注意,加號在後面

System.out.println(i);

上面的代碼既不會輸出102,也不會報錯,而是輸出2,這的確出乎意料,徹底不是咱們指望的結果,太神奇了,很是的「坑爹」。

因此,它排名第2,穩居榜眼的位置。

Java註釋可以識別Unicode

先看看代碼:

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

乍一看,代碼都被註釋掉了,固然不會輸出任何東西,然而,它仍是輸出每一個程序員都倍感親切的Hello World,這是由於,unicode解碼發生在代碼編譯以前,編譯器將\u樣式的代碼進行文本轉義,即便是註釋也是這樣,而後\u000a被轉換成\n換行符,因此println代碼得以正常執行。

這樣的功能着實「坑爹」,極其違反常識,它必需要上榜,必需要榮登狀元的位置。

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

相關文章
相關標籤/搜索