日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java日常错误及需要注意细节,持续更新......

發布時間:2025/3/8 java 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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

總結

以上是生活随笔為你收集整理的Java日常错误及需要注意细节,持续更新......的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。