在項目中隨手把haseMap改爲了currenHaseMap差點被公司給開除了。php
String str1 = null; String str2 = "java金融"; // str1.equals(str2); 錯誤的寫法 str2.equals(str1); // 常量寫前面 Objects.equals(str1, str2);// 藉助jdkUtil工具類 StringUtils.equals(str1,str2); // 自定義工具類
Integer n1 = 100; Integer n2 = 100; System.out.println(n1 == n2);//true System.out.println(n1.equals(n2));//true Integer n3 = 200; Integer n4 = 200; System.out.println(n3 == n4);//false System.out.println(n3.equals(n4));//true
爲何n3== n4 是false呢?因爲包裝類的緩存機制。
包裝類的比較用equals去判斷。
最推薦的仍是用工具類去判斷。例如上面的列子若是n3=null的話n3.equals(n4)這時候就會拋出npe了。若是用工具類的話就不會存在這種狀況。總之一句話判斷相等若是不肯意去判空(偷懶、代碼也很差看)就藉助工具類。合理使用工具類可使你的代碼減小沒必要要的npe。java
這個常見的坑的話就是因爲自動拆箱致使的 NPE 異常。這個阿里巴巴開發手冊(須要這個手冊能夠關注公衆號回覆"JAVA")說的很明白了。
c++
double d = 1.001; float f = 1.001f; BigDecimal bigDecimal1 = new BigDecimal(d); BigDecimal bigDecimal2 = new BigDecimal(f); System.out.println(bigDecimal1); System.out.println(bigDecimal2);
輸出結果sql
1.000999999999999889865875957184471189975738525390625 1.00100004673004150390625
這個結果是否是跟咱們所指望的1.001有點不同。數據庫
float和double能夠用於工程計算科學計算,他們會有精度丟失,這是因爲浮點運算器的結構致使的,可是在金融領域一旦精度出現問題就意味着多是嚴重的現實經濟損失,因此普通的那些數值型通常不會在這個場景下使用。
因此涉及金錢的計算必定不要使用float和double。使用BigDecimal而且必定要用String來構造。 上面的列子咱們能夠這樣來初始化 new BigDecimal("1.001")。數組
BigDecimal a = new BigDecimal("1"); System.out.println(a.divide(new BigDecimal(3)));
輸出緩存
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result. at java.math.BigDecimal.divide(BigDecimal.java:1690) at com.workit.demo.antisper.Test.main(Test.java:11)
解決辦法:使用以下兩個函數設置精度安全
BigDecimal a = new BigDecimal("1"); System.out.println(a.divide(new BigDecimal(3), 2,BigDecimal.ROUND_HALF_UP));
String str = "java|php|c++"; String[] split = str.split("|"); for(String s:split){ System.out.println(s); }
輸出結果app
j a v a | p h p | c + +
結果並非咱們所期待的,java、php、c++。
解決辦法咱們對|進行轉義分割,代碼改成 String[] split = str.split("\|");結果就正確了。
String的split方法須要轉義的字符串<font style color="red">:. $ | ( ) [ { ^ ? * + </font> 共12個特殊字符,遇到以這些字符進行分割字符串的時候,須要在這些特殊字符前加雙反斜槓 。ide
下面列舉一些經常使用可是卻與咱們所期待的結果不同的用法。
int[] array = {1,2,3}; List list = Arrays.asList(array); System.out.println(list.size()); //1
輸出的結果是1不是3哦是否是跟想象的有點不同?緣由以下:
因爲Arrays.ArrayList參數爲可變長泛型,而基本類型是沒法泛型化的,因此它把int[] array 數組當成了一個泛型對象,因此集合中最終只有一個元素array 。
String[] array = {"歡迎","關注","java金融"}; List list = Arrays.asList(array); array[0] ="修改數組第一個元素"; list.set(2,"修改集合第三個元素"); System.out.println(Arrays.toString(array)); System.out.println(list.toString());
輸出結果
[修改數組第一個元素, 關注, 修改集合第三個元素] [修改數組第一個元素, 關注, 修改集合第三個元素]
是否是也與咱們所期待的不同。修改了數組奧了的值竟然影響到了集合裏面的值。緣由以下:
因爲asList產生的集合元素是直接引用做爲參數的數組,因此當外部數組或集合改變時,數組和集合會同步變化,這在平時咱們編碼時可能產生莫名的問題。
String[] array = {"歡迎","關注","java金融"}; List list = Arrays.asList(array); list.add("java金融"); System.out.println(list.toString());
輸出結果:
Exception in thread "main" java.lang.UnsupportedOperationException at java.util.AbstractList.add(AbstractList.java:148) at java.util.AbstractList.add(AbstractList.java:108)
拋出異常緣由:因爲asList產生的集合並無重寫add,remove等方法,因此它會調用父類AbstractList的方法,而父類的方法中拋出的倒是異常信息。
當咱們使用Arrays.asList 產生的集合時候,須要謹慎的去使用。若是須要對集合進行操做的時候咱們能夠經過 List list = new ArrayList(Arrays.asList(array)); 來進行使用。
String key = "java金融"; Map<String,Object> map = new ConcurrentHashMap<>(); map.put("1","2"); map.put(key,null);// Exception in thread "main" java.lang.NullPointerException
記得剛開始工做的時候,我負責的一個管理系統裏面有一個關於省份的緩存,用HashMap來存的。大概就是項目一塊兒動,而後就從db裏面把省份信息加載到HashMap裏面,之後須要用到省份信息直接從HashMap裏面取,HashMap不是線程不安全嗎?而後我反手就把它改爲了currenHaseMap。測試環境測試沒問題,而後就跟着其餘功能上線。上完線以後也沒有去迴歸關於省份的這一塊內容,而後就下班了。次日上班運營反映有部分註冊用戶的省份信息沒了。leader就找我昨天有沒有改過關於省份的代碼,我說就改了一個currenHaseMap。leader先讓昨天上線代碼回退,一回退省份信息就有了。後面通過仔細排查原來生產數據庫有一條省份信息是空的。而後加載那條空的省份信息到currenHaseMap就報空指針了,在這條空記錄後面信息就沒加載到currenHaseMap了。幸虧是內網管理系統沒有形成太大的影響 。
String userName= String.valueOf(parmMap.get("userName")); if(StringUtils.isNotBlank(userName)) { sql.append(" and tt.userName like %").append(userName); }
這裏的 parmMap.get("userName") 若是是 null , 那麼這裏的 userName就是 「null」 ,這是一個值爲 null 的字符串。致使數據會拼接到SQL 中,導出出錯。爲何會這樣咱們看下源碼就知道了。
public static String valueOf(Object obj) { return (obj == null) ? "null" : obj.toString(); }
因此轉字符串的時候咱們要根據實際的狀況來選擇合適的方法。
### 總結
本文列舉了一些對於java常見的一些可能稍微不注意就會採坑的一些知識點。還有其餘更多須要注意的知識點也歡迎你們來補充。其實這些常見的採坑基本上只要去看下源碼都可以避免的。