Java日常錯誤及需要注意細節,持續更新......

記錄日常工作中一些容易被忽視的錯誤及細節,持續更新......

一、問題:HashMap<Long, String>中,用get(Integer key)取不到值

        Map<Long, String> map = new HashMap<Long, String>();map.put(1L, "1");System.err.println(map.get(1));// nullSystem.err.println(map.get(1L));// 1

1.首先想到Long與Integer的hashCode方法不同,Integer-value? ?Long-(int)(value ^ (value >>> 32))

但是!!計算出的hashCode值是相同的,不是問題所在

2.查看HashMap源碼:注意加亮部分

  先比較key.hash,然后first.key == key || key.equals(first.key)

     /*** 先比較key.hash,然后first.key == key || key.equals(first.key)*/final Node<K,V> getNode(int hash, Object key) {Node<K,V>[] tab; Node<K,V> first, e; int n; K k;if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) {if (first.hash == hash && ((k = first.key) == key || (key != null && key.equals(k))))return first;if ((e = first.next) != null) {if (first instanceof TreeNode)return ((TreeNode<K,V>)first).getTreeNode(hash, key);do {if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))return e;} while ((e = e.next) != null);}}return null;}

?先看first.key == key:"=="比較地址值,l是Long cache[]中的1,o是Integer cache[]中的1,false

        Long l = 1L;Object o = 1;System.err.println(l == o);// false// 反編譯后:Long l = Long.valueOf(1L);Object o = Integer.valueOf(1);System.err.println(l == o);

然后看key.equals(first.key):先檢查類型,false

        //Long的equals方法public boolean equals(Object obj) {if (obj instanceof Long) {return value == ((Long)obj).longValue();}return false;}

引發新的問題:為什么這個是true?——反編譯解決

        Long l = 1L;System.err.println(l == 1);// true// 反編譯后:Long l = Long.valueOf(1L);System.err.println(l.longValue() == 1L);//編譯器直接將1轉成1L

?二、兩個值相等的Integer不“==”

        Integer c = 99999;Integer d = 99999;System.out.println(c == d);// false

?Integer c = 99999;// 反編譯:Integer c = Integer.valueOf(99999);

查看Integer源碼:

-128 <= i <= 127時,直接在Integer cache[]中取;否則,new Integer(i)

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

結論:

        int a = 99999;int b = 99999;System.err.println(a == b);// true
Integer c = 99999;Integer d = 99999;System.out.println(c == d);// false
        Integer e = 127;Integer f = 127;System.out.println(e == f);// true    

?三、List.remove()方法調用錯誤

注意list兩個remove方法,remove(int index)? remove(Object o)

    public static void main(String[] args) {List<Integer> list = new LinkedList<Integer>();for (int i = 0; i < 9999999; i++) {list.add(i);}// remove(int index)long before = System.currentTimeMillis();int i = 8888888;list.remove(i);long after = System.currentTimeMillis();System.err.println("index=" + (after - before));// 6ms// remove(Object o)long before = System.currentTimeMillis();Integer i = 8888888;list.remove(i);long after = System.currentTimeMillis();System.err.println("Object=" + (after - before));// 96ms
        }

四、三目運算符與自動拆裝箱

        Map<String,Boolean> map = new HashMap<String, Boolean>();Boolean b = (map!=null ? map.get("test") : false);// Exception in thread "main" java.lang.NullPointerException

查問題:

  NullPointerException找不出原因

  反編譯看:?((Boolean)map.get("test")) == null

        HashMap map = new HashMap();Boolean boolean1 = Boolean.valueOf(map == null ? false : ((Boolean)map.get("test")).booleanValue());

結論:

  三目運算符的語法規范,參見?jls-15.25。

  三目運算符?當第二,第三位操作數分別為基本類型和對象時,其中的對象就會拆箱為基本類型進行操作。

以后注意:

1、保證三目運算符的第二第三位操作數都為對象類型

        Map<String,Boolean> map =  new HashMap<String, Boolean>();Boolean b = (map!=null ? map.get("test") : Boolean.FALSE);

?2、自動拆裝箱問題

        Integer integer = 1; // 裝箱  Integer integer=Integer.valueOf(1); new Integer()int i = integer; // 拆箱  int i=integer.intValue(); 

?

1)包裝對象的數值比較,不能簡單的使用==(只有-128到127之間IntegerCache內的數字可以,但是這個范圍之外還是需要使用equals比較)。

2)自動拆箱,如果包裝類對象為null,那么自動拆箱時就有可能拋出NPE。

3)如果一個for循環中有大量裝箱操作,會浪費很多資源。

五、switch語句忘記break

本來我跟你現在想的一樣,一定不會忘,直到遇到了這個問題。

        int i = 3;switch (i) {case 1:System.out.println(1);break;case 2:System.out.println(2);break;case 3:System.out.println(3);// 沒有break, 不會有問題}

當你需要在之后接著case的時候,直接復制case 3,就bug了。

(1)case完一定break,除非特別需要穿透到下一個case;

(2)復制代碼前后都要檢查是否有問題。

六、數值溢出問題

    // 為了更好的展示問題,代碼舉出的是較極端的情況public void overFlow(int a) {int b = 999999 * a; // 6個9 int最大值=2147483647int limit = 999999999; // 9個9if (b < limit) {System.out.println("a*b小于limit");}}

如果a傳入一個較大的int值,a*999999之后會超過int的最大值

而默認結果是int類型,會將a*999999的結果強轉成int,導致不是想要的結果的結果

即使a*999999是大于limit的,強轉成int后,b可能會比limit小,甚至可能是負數

解決:

    // 用long類型計算(還會用一定風險)public void overFlow(int a) {long b = 999999L * a;int limit = 999999999;if (b < limit) {System.out.println("a*999999小于limit");}}// 將加法和乘法轉變成減法和除法運算public void overFlow(int a) {int limit = 999999999;if (a < limit/999999) {System.out.println("a*999999小于limit");}}

七、對象引用問題

public static void main(String[] args) {Map<Integer, Inner> map = new HashMap<Integer, Inner>();// inner1.list [1]Inner inner1 = new Inner(new LinkedList<Integer>());inner1.getList().add(1);map.put(1, inner1);// inner2.list [1, 2]Inner inner2 = new Inner(map.get(1).getList());inner2.getList().add(2);map.put(2, inner2);for (Entry<Integer, Inner> entry : map.entrySet()) {System.err.println("" + entry.getKey() + " " + entry.getValue().getList());}/*** 目的:inner1.list [1]   inner2.list [1, 2]* 結果:inner1.list [1, 2]   inner2.list [1, 2]*/}static class Inner {List<Integer> list;public List<Integer> getList() {return list;}public Inner(List<Integer> list) {this.list = list;}}

?

分析:

1.將inner1.list的引用給了inner2.list,nner1.list?inner2.list指向的是同一個List。

2.很簡單的問題,開發時習慣了構造方法里這樣寫:this.list = list;

解決:

this.list = list;? 改成? ?this.list = new LinkedList<Integer>(list);

?

轉載于:https://www.cnblogs.com/hexinwei1/p/9720310.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/537724.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/537724.shtml
英文地址,請注明出處:http://en.pswp.cn/news/537724.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

tp5 html獲取get,tp5獲取請求參數

1.問題&#xff1a;照著tp5快速入門手冊里學習&#xff0c;運行一段代碼和書中的結果(資源類型)不同2.相關代碼&#xff1a;public function hello(Request $request){echo 請求參數;dump(input());echo name: .$request->param(name);echo 資源類型&#xff1a; .$request-…

matlab 濾波器設計 coe_一種半帶濾波器的低功耗實現方法

在如今數字技術中&#xff0c;半帶濾波器因其通帶阻帶對稱&#xff0c;系數具有偶對稱性且濾波器階數為奇數&#xff0c;有效系數少等特點廣泛應用于通信、視頻處理、語音識別等數字信號處理應用中&#xff0c;尤其常用于實現信號的2倍抽取。對于一個階數為N(N為偶數)&#xff…

產品設計:APP個人信息保護指引

需求分析 2019年11月4日&#xff0c;工業和信息化部展開APP侵犯用戶權益專項整治行動。即日起各安卓應用市場根據最新的規則審核市場里的各應用&#xff0c;審核不通過將下架處理。 調研了“手機qq”、“抖音”、“快手”、“今日頭條”、“澎湃新聞”等APP&#xff0…

說說GIL

上一篇&#xff1a;線程深入篇引入 Code&#xff1a;https://github.com/lotapp/BaseCode/tree/master/python/5.concurrent/Thread/3.GIL 說說GIL 盡管Python完全支持多線程編程&#xff0c; 但是解釋器的C語言實現部分在完全并行執行時并不是線程安全的&#xff0c;所以這時候…

2021重慶高考成績名次排名查詢,重慶高考排名對應大學-重慶高考位次大學(2021年理科)...

選擇科目測一測我能上哪些大學選擇科目領取你的專屬報告>選擇省份關閉請選擇科目確定v>每年高考結束后&#xff0c;報大學、選專業、填志愿就成了考生與家長十分關心的一件事情。本期&#xff0c;圓夢志愿為大家整理了重慶高考理科2020年位次排名對應的大學&#xff0c;供…

Project項目信息的日程排定方法區別

日程排定方法分&#xff1a;項目開始日期&#xff0c;項目結束日期。 項目開始日期 設置如下 在“工期”單元格輸入任意數字&#xff0c;任務開始日期會從項目開始日期2020年3月1日開始 給項目任務設置工期的時候&#xff0c;從任務的第一個開始設置&#xff0c;按正序進行&a…

gis里創建要素面板怎么打開_周末技術流 | GIS三維熱力圖分析

周末技術流&#xff2e;&#xff2f;&#xff37;現在行動&#xff01;我們的技術流是一個系列&#xff0c;最終帶大家出一套完整圖紙哦~(未經允許嚴禁盜用&#x1f6ab;)Rhino日照分析1.前期回顧本期內容一直關注我們的朋友到這期可能會有點熟悉&#xff0c;確實&#xff0c;我…

第三章實驗二小談

第三章實驗二小談 這周很忙...時間很趕...很多作業還沒做... 首先想談&#xff08;tu&#xff09;論&#xff08;cao&#xff09;一下計算機的嚴謹性。 編程語言嚴謹是一種好事&#xff0c;越嚴謹&#xff0c;把它轉化為機器語言就越方便&#xff0c;在資源占用、運行速度等方面…

project提醒:無法鏈接這些任務,因為它們已通過另一個任務鏈鏈接

給45任務指定前置任務111時&#xff0c;提示“無法鏈接這些任務&#xff0c;因為它們已通過另一個任務鏈鏈接” 查了好久沒找到原因&#xff0c;后來無意在46任務前置任務輸入111&#xff0c;沒有提示。 解決方法&#xff1a; 刪除了提示的45任務&#xff0c;新建任務&#x…

企業網站 源碼 e-mail_天津seo優化套餐服務收費_天津網站優化關鍵詞價格

天津華陽在線專注于SEO關鍵詞排名優化&#xff0c;品牌網站建設&#xff0c;營銷型網站建設&#xff0c;App、小程序開發&#xff0c;搜索引擎seo優化&#xff0c;競價托管sem&#xff0c;品牌口碑建設與代運營等服務。企業通過引進前BAT產品經理不斷豐富產品線優化技術實力&am…

計算機網絡與綜合布線系統設計,計算機網絡與通信技術10-綜合布線系統.ppt

計算機網絡與通信技術10-綜合布線系統.ppt5.7 電氣防護系統設計 電氣防護設計應把握以下原則&#xff1a; 1)為了保證綜合布線系統正常運行&#xff0c;設備間或干線交接間內應設有獨立、穩定、可靠的交流50Hz、220V電源&#xff0c;以便于維護檢修和日常管理&#xff0c;有條件…

必須Mark下,2019 年度中國質量協會質量技術優秀獎

曾經和一群可愛的人兒做的項目&#xff0c;獲得了2019 年度中國質量協會質量技術優秀獎&#xff0c;無心插柳柳成蔭。 那幾年工作得很快樂&#xff0c;工作與家庭都兼顧&#xff0c;是同事也是朋友。2019年末去過一次移動寧波分公司&#xff0c;特意去看了原來駐場的辦公室&am…

python文件編碼及執行

兼容中文編碼 由于Python源代碼也是一個文本文件&#xff0c;所以&#xff0c;當你的源代碼中包含中文的時候&#xff0c;在保存源代碼時&#xff0c;就需要務必指定保存為UTF-8編碼。 當Python解釋器讀取源代碼時&#xff0c;為了讓它按UTF-8編碼讀取&#xff0c;我們通常在文…

html5鏈接mvc,LinkExtensions.ActionLink 方法 (System.Web.Mvc.Html) | Microsoft Docs

對于指定的鏈接文本、操作、控制器、協議、主機名、URL 片段、作為路由值字典的路由值和作為字典的 HTML 屬性&#xff0c;返回一個定位點元素&#xff0c; (元素) 。public static System.Web.Mvc.MvcHtmlString ActionLink (this System.Web.Mvc.HtmlHelper htmlHelper, stri…

這些Windows 10隱藏秘技,你知道幾個?

1. 虛擬桌面 玩電腦的老鳥&#xff0c;估計都聽說過虛擬桌面。簡言之&#xff0c;平時要做的工作太多&#xff0c;又沒有第二個顯示器&#xff0c;那么“虛擬桌面”也就成了不二之選。微軟Windows 10的虛擬桌面隱藏在WinTAB中&#xff0c;也就是所謂的時間線視圖&#xff08;T…

vant toast loading 倒計時_日期倒計時軟件哪個好 蘋果日期倒計時軟件推薦

日期倒計時軟件哪個好&#xff0c;相信大家也是經常會查看日期&#xff0c;來保證一些重要的事情能夠按時進行&#xff0c;那么哪一款日期倒計時軟件比較好用&#xff0c;能夠提醒用戶們日期將至呢。這里就為大家推薦幾款。日期倒計時軟件哪個好1.Days Matter Air作為Days Matt…

瀏覽器的差距

瀏覽器 瀏覽器默認字體是16px&#xff0c;谷歌的最小字體是12px&#xff0c;其他的是10px。 HACK Hack就是針對不同的瀏覽器去寫不同的HTML、CSS樣式&#xff0c;從而讓各瀏覽器能達到一致的渲染效果。 Hack分兩種寫法 Html的hack&#xff1a;寫在html的標簽中 Css的hack&#…

業務應用系統的業務操作日志設計

目的&#xff1a;記錄業務的訪問活動 操作時間&#xff1a;精確到秒 服務器IP&#xff1a;可能部署多臺服務器&#xff0c;記錄當前線程服務器IP地址 訪問者IP&#xff1a;訪問者ip地址 訪問者賬號&#xff1a;系統通過手機號登錄&#xff0c;記錄手機號 業務名稱&#xf…

微型計算機控制技術試卷B,微型計算機控制技術試卷b..doc

微型計算機控制技術試卷b.微型計算機控制技術試卷B一、選擇題(本題共10小題&#xff0c;每小題 1.5分&#xff0c;共15分) 1. 防止抖動是能否正確讀取鍵值的必要環節&#xff0c;實現方法是( )。 A&#xff0e;可以用硬件電路或軟件程序實現?? B&#xff0e;只能用濾波電路或…

c char轉int_c/c++基礎之sizeof用法

在 C/C 中&#xff0c;sizeof() 是一個判斷數據類型或者表達式長度的運算符。1 sizeof 定義 sizeof 是 C/C 中的一個操作符&#xff08;operator&#xff09;&#xff0c;返回一個對象或者類型所占的內存字節數。The sizeof keyword gives the amount of storage, in bytes, as…