平時遇到的一些本身開始不懂,後來看了下原理,豁然開朗的問題:數組
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操做的仍是老的數組,