平時發現的一些有意思的小知識

平時遇到的一些本身開始不懂,後來看了下原理,豁然開朗的問題:數組

1.緩存

 1 package day1226;
 2 
 3 /**
 4  * @author : hao
 5  * @project : StudySjms
 6  * @description :
 7  * @time : 2018/12/26 15:54
 8  */
 9 public class IntegerTest {
10 
11     public static void main(String[] args) {
12         Integer i1 = 100;
13         Integer i2 = 100;
14         Integer i3 = 200;
15         Integer i4 = 200;
16         System.out.println(i1==i2);    //true
17         System.out.println(i3==i4);  //false
18     }
19 }

這是爲何呢? 開始我覺得只是false就行了多線程

這裏面體現了 原生類型和包裝類型的裝箱和拆箱。 spa

自動裝箱的時候 實際上調用了Interger.valueOf(int)  ,拆箱的時候用的是initValue(Integer)線程

1     public static Integer valueOf(int i) {
2         if(i >= -128 && i <= IntegerCache.high)
3             return IntegerCache.cache[i + 128];
4         else
5             return new Integer(i);
6     }

能夠發現若是值是-128-127範圍內是返回緩存裏的引用,若是不是新建一個對象,返回引用。全部上面200兩個引用是兩個對象的,因此false。code

 

2.你瞭解可變參數和數據參數嗎?對象

 1 package day1227;
 2 
 3 /**
 4  * @author : hao
 5  * @project : StudySjms
 6  * @description :
 7  * @time : 2018/12/27 15:48
 8  */
 9 public class KbArrayTest {
10 
11 
12     public static void main(String[] args) {
13         KbArrayTest test = new KbArrayTest();
14         int[] array = new int[]{1,2,3};
15 
16         test.printA(array);
17         test.printB(array);
18 
19         test.printA(new int[]{3,4,5});
20         test.printA(3,5,7);
21         
22         test.printB(new int[]{3,4,5});
23         //test.printB(3,5,7); 不經過,   int...num參數能夠接受數組,反之int[] array 不接受1,2,3這種參數
24     }
25 
26 
27 
28     private void printA(int... num){
29         for (int i = 0; i < num.length; i++) {
30             System.out.println(num[i]);
31         }
32     }
33 
34     private void printB(int[] array){
35         for (int i = 0; i < array.length; i++) {
36             System.out.println(array[i]);
37         }
38     }
39 }

這裏面看一下編譯後的class 有意思的地方:blog

 1 //
 2 // Source code recreated from a .class file by IntelliJ IDEA
 3 // (powered by Fernflower decompiler)
 4 //
 5 
 6 package day1227;
 7 
 8 public class KbArrayTest {
 9     public KbArrayTest() {
10     }
11 
12     public static void main(String[] args) {
13         KbArrayTest test = new KbArrayTest();
14         int[] array = new int[]{1, 2, 3};
15         test.printA(array);
16         test.printB(array);
17         test.printA(new int[]{3, 4, 5}); 18         test.printA(new int[]{3, 5, 7}); 19         test.printB(new int[]{3, 4, 5});
20     }
21 
22     private void printA(int... num) {
23         for(int i = 0; i < num.length; ++i) {
24             System.out.println(num[i]);
25         }
26 
27     }
28 
29     private void printB(int[] array) {
30         for(int i = 0; i < array.length; ++i) {
31             System.out.println(array[i]);
32         }
33 
34     }
35 }

調用 int... num 形參的方法,無論你參數怎麼寫,編譯後都變成了 new int[]{} 數組參數的形式接口

3. ArrayList裏面的elementData [] 爲何用transient修飾。Arraylist不是支持序列化嗎?ip

  應該知道transient修飾的變量內容是不參與自動序列化,即便實現了Serialiazble接口

  由於Arraylist裏面數組的長度不是固定的,若是擴容後,這個data數據裏面會有不少空的內容,這個就不須要去序列化了,

  ArrayList裏面有兩個類來實現序列化,writeObject和readObject 裏面都是先寫或者先讀容量,而後挨個節點讀或者寫

 

4.ArrayList 在多線程裏面 若是後續用Iterator迭代器遍歷,若是一個線程正在遍歷,兩一個線程修改了,那麼會出現ConcurrentModificationException?知道緣由嗎?知道怎麼解決嗎?原理知道嗎?

  首先ArrayList的父類AbstractList裏面實現樂迭代器接口而且在hasNext和next()方法裏都作了判斷,是否拋這個異常,有一個modCount,和Iterator也有個ExpectedModCount,

而後每次ArrayList改變數組大小操做的時候,都是modCount+1,可是new Itreator的時候給的初始值是原來的,這樣就致使可能出現不一致的狀況。

  而後解決這個問題能夠用CopyOnWriteArrayList來解決。

  爲何能夠呢? 由於這個類全部寫操做都加鎖,而後每次操做都會複製一份原來的數組,改好了在把新數組的引用指向原來的,數組,並且這個array是用volatile修飾的,內存可見性。並且他的iterator是本身實現的。數組也是備份了一份,因此遍歷的時候不會影響的。由於Iterator操做的仍是老的數組,

相關文章
相關標籤/搜索