平时发现的一些有意思的小知识

平时遇到的一些自己开始不懂,后来看了下原理,豁然开朗的问题:

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就好了

这里面体现了 原生类型和包装类型的装箱和拆箱。 

自动装箱的时候 实际上调用了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。

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 有意思的地方:

 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不是支持序列化吗?

  应该知道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操作的还是老的数组,

原文地址:https://www.cnblogs.com/haoerlv/p/10179685.html