奇怪的 Java 知识

52 阅读2分钟

我正在参加「掘金·启航计划」

static 代码块执行顺序

代码块加载顺序

  • 静态代码块 static{}类加载的时候执行,是最早被执行的,优先级最高
  • 构造代码块 {} 构造代码块在每一次创建对象时执行,始终在构造方法前执行
  • 构造方法 新建对象时调用,new 关键字创建对象的时候

问题:如下代码的加载顺序应该是如何?

class Static {

    public static Static t1 = new Static();

    {
        System.out.println("构造块");
    }

    static {
        System.out.println("静态块");
    }

}

Static s = new Static();
// 构造块
// 静态块
// 构造块

按照我们的理解加载的逻辑应该是 : 静态代码块 static{} > 构造代码块 {} > 构造方法 为什么顺序没有按照我们的理解去输出。原因在于 public static Static t1 = new Static();,因为此静态代码块在执行的时候创建了对象。所以才有构造块在静态块之前执行了。将上面代码改成如下就会正常输出了

class Static {


    {
        System.out.println("构造块");
    }

    static {
        System.out.println("静态块");
    }

    public static Static t1 = new Static();
}

Static s = new Static();
// 静态块
// 构造块
// 构造块

父类代码块加载顺序

先看个例子 A 继承 B:

class B {

    public B() {
        super();
        System.out.println("构造器B");
    }

    {
        System.out.println("普通的代码块B");
    }

    static {
        System.out.println("静态代码块B");
    }

}

class A extends B {

    public A() {
        super();
        System.out.println("构造器A");
    }

    {
        System.out.println("普通的代码块A");
    }

    static {
        System.out.println("静态代码块A");
    }
}

A a = new A();

// 静态代码块B
// 静态代码块A
// 普通的代码块B
// 构造器B
// 普通的代码块A
// 构造器A

总结:父类静态代码块子类静态代码块 > 父类代码块 > 父类构造方法子类代码块 > 子类构造方法

只要记住代码块的加载顺序,耐心分析就可以推断出结论。永远相信计算机是按照规则执行并不会出现诡异的事情。

ArrayList 删除元素

ArrayList remove 方法使用很简单。有两种实现

  • 根据数组的下标删除 remove(int index)
  • 根据数组内的元素删除 remove(Object o)

image.png

删除最终的执行都是上图的方法,根据数组元素的下表做一次数组的拷贝(实际上是数组的元素向前移动,最后一位置为 null )。看下面这个例子

数组循环中删除元素

期待的结果是移除下标为偶数的元素,但是如下代码的结果却不是想要的结果。

问题:每次迭代数组的长度都会改变,就导致执行结果不准确。

List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8));
for (int i = 0; i < list.size(); i++) {
    if (i % 2 == 0) {
        list.remove(i);
    }
}
System.out.println(list); // [2, 3, 5, 6, 8]

解决:对于此类问题我们只需要列表从后往前遍历

for (int i = list.size() - 1; i >= 0; i--) {
    if (i % 2 == 0) {
        list.remove(i);
    }
}

System.out.println(list); // [2, 4, 6, 8]

数组重复元素的删除

期待的结果 remove 所有相同的元素。

问题:数组中存在重复元素,如何一次性全部移除

List<String> list = new ArrayList<>(Arrays.asList("1", "1", "1", "2", "3"));
list.remove("1");
System.out.println(list); // [1, 1, 2, 3]

解决:使用 removeIf

List<String> list = new ArrayList<>(Arrays.asList("1", "1", "1", "2", "3"));

list.removeIf(o -> o.equals("1")); 

System.out.println(list); // [2, 3]