java初學者——坑王(一)
阿新 • • 發佈:2018-11-30
最近在學java,做一個課堂作業——實現16進位制數轉換成10進位制數。然後擼了以下程式碼:
/** * 16進位制轉換成10進位制 * @param hex 16進位制傳參 * @return 返回10進位制整數 */ public static int HexToDec(String hex){ // int[] array = {10, 11, 12, 13, 14, 15}; int decNum = 0; for(int i=0; i<hex.length(); i++){ char tempChar = hex.charAt(i); if (tempChar >= '0' && tempChar <= '9'){ int tempValue = (int)(tempChar); decNum = decNum + tempValue * 16^(hex.length() - i - 1); }else if("A".equals(tempChar)){ decNum = decNum + 10 * 16^(hex.length() - i - 1); }else if("B".equals(tempChar)){ decNum = decNum + 11 * 16^(hex.length() - i - 1); }else if("C".equals(tempChar)){ decNum = decNum + 12 * 16^(hex.length() - i - 1); }else if("D".equals(tempChar)){ decNum = decNum + 13 * 16^(hex.length() - i - 1); }else if("E".equals(tempChar)){ decNum = decNum + 14 * 16^(hex.length() - i - 1); }else if("F".equals(tempChar)){ decNum = decNum + 15 * 16^(hex.length() - i - 1); } } return decNum; }
寫完以後,自我覺得雖然程式碼不夠簡潔吧,至少功能應該是ok的。沒想到一執行、除錯,發現了各種問題。讓隔壁做後端開發的室友看了看,這小夥竟然沒發現出什麼問題。看來這裡有個大坑…
程式碼比較簡單,各位大神應該都在我至少,就不班門弄斧講解了。
通過排查,最後發現這段程式碼中有三個坑。
字元型別強制轉成整型
案例中,有一段程式碼是將字元型別強制轉成整型,粗略一看沒啥問題。除錯過程中,tempChar
為’4’, 通過以下程式碼轉換:
int tempValue = (int)(tempChar);
得到結果tempValue
為52。說實話,當時看到這個結果是懵逼的,都要懷疑人生了。後經他人點播,字元’4’的askii碼轉成整形為52;
也就是說,java中,字元型別強制轉成整型得到的是:askii碼錶中,字元對應的十進位制值。
上述程式碼如何改善呢,可以根據askii碼錶中 傳入字元與’0’的距離來得到值:
int tempValue = (int)(tempChar + '0');
N次方
如果你還記得16進位制轉成10進位制的演算法,那麼這段計算方法你不會陌生:
16^(hex.length() - i - 1)
我想得到是:16的(hex.length() - i - 1)
次方。可能這個符號^
用的較少,這個符號並不是取次方。^
這個符號其實代表的是異或。難怪執行16^1
的結果是17。除錯的時候第二次懷疑人生。道行尚淺啊!
字元比較
16進位制會包含字母A/B/C/D/E/F,程式碼中也做了特殊處理。比較方式如下:
"?".equals(tempChar) # ? 代表A/B/C/D/E/F
本來麼,我應該會用==
號,但想起前幾天視訊中說過,字串比較用equals
方法比較專業,並且常量在前,變數在後會更好。話是記住了,除錯時卻遇到麻煩了。明明看到的是’E’,但是就是進不去條件內部。後面改成 :
"?" == tempChar # ? 代表A/B/C/D/E/F
功能正常,符合預期。
通過查閱文件,發現了問題的根源:
java中的資料型別,可分為兩類:
1,基本資料型別,也稱原始資料型別。byte,short,char,int,long,float,double,boolean 他們之間的比較,應用雙等號(==),比較的是他們的值。
2,複合資料型別(類),當他們用(==)進行比較的時候,比較的是他們在記憶體中的存放地址,所以,除非是同一個new出來的物件,他們的比較後的結果為true,否則比較後結果為false。JAVA當中所有的類都是繼承於Object這個基類的,在Object中的基類中定義了一個equals的方法,這個方法的初始行為是比較物件的記憶體地 址,但在一些類庫當中這個方法被覆蓋掉了,如String,Integer,Date在這些類當中equals有其自身的實現,而不再是比較類在堆記憶體中的存放地址了。
對於複合資料型別之間進行equals比較,在沒有覆寫equals方法的情況下,他們之間的比較還是基於他們在記憶體中的存放位置的地址值的,因為Object的equals方法也是用雙等號(==)進行比較的,所以比較後的結果跟雙等號(==)的結果相同。
上述引用來自:https://blog.csdn.net/qiuyoungster/article/details/53052854