平时遇到的一些本身开始不懂,后来看了下原理,豁然开朗的问题:数组
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操做的仍是老的数组,