为什么以后执行静态块?

时间:2014-03-24 07:11:26

标签: java static

P.S:

This question has been edited a few times as my previous code doesn't demonstrate the problem. There are some answers which may not make perfect sense against the edited question

我有一个名为Son.java

的公共类
package com.t;

public class Son extends Father {

    static int i;

    static {
        System.out.println("son - static");
        i = 19;
    }

    {
        System.out.println("son - init-block"); 
    }

    public static void main(String[] args) {
        //Son s = new Son();
        int a[] = new int[2];
        System.out.println(a[5]);
    }

}

class Father {

    static {
        System.out.println("f - static");
    }
    {
        System.out.println("f - init-block");
    }
}

当我第一次运行程序时:

输出是:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
    at com.t.Son.main(Son.java:19)
f - static
son - static

以后我运行这个程序时(输出顺序为random

输出是:

f - static
son - static
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
    at com.t.Son.main(Son.java:19)

我已经读过static块被执行,因为这些类已被初始化。

但是为什么异常首先出现在那里然后执行静态块?

我也在使用Eclipse来运行我的程序。 有人可以解释一下吗?

4 个答案:

答案 0 :(得分:10)

首先不会发生异常,您只是首先看到异常的打印输出。

如果首先发生异常,你将永远不会看到输出的其余部分。

原因是您在程序中输出了System.err(来自您的例外)和System.out。没有定义这些打印到屏幕的顺序,因此您可以按不同顺序获取它们。

答案 1 :(得分:3)

未捕获的异常的堆栈跟踪打印在System.err中,这是一个无缓冲的流。您将文本打印到System.out这是一个缓冲流,并且无论是否在打印堆栈跟踪之前或之后刷新缓冲区都是不可预测的。

如果您将所有打印报表更改为System.err,那么输出的顺序将成为打印顺序,并且它将始终是相同的顺序。

答案 2 :(得分:0)

@Keppil的回答已经确定了。


我只想指出一些事情......呃......有趣。

OP说:

  

我正在使用Eclipse来运行我的程序。

膝盖反射的反应是说“那是不相关的”......但在这种情况下,我认为>>是<<相关。我怀疑stdout / stderr时序中的非确定性是由于输出进入Eclipse“控制台”面板而被放大

当从命令行运行应用程序时,输出到stderr和stdout可能会合并到OS内核中的某个流中。如果没有,控制台程序可能使用select系统调用来处理来自两个源的输入......并且提供一个流优先于另一个,'cos这是编码它的简单方法。因此,即使订单不确定,您也可以期望输出以大致一致的顺序出现在控制台上。

但是当应用程序写入Eclipse控制台时,Eclipse可能会使用单独的线程来读取每个流。假设两个线程都在read系统调用中被阻塞,并且输入在两个流上大致同时到达,则由线程调度程序决定首先唤醒哪个线程。对于选择...或者流在内核中合并的行为,这将远不能预测。

无论哪种方式,我的观察是重新排序的stdout / stderr输出在Eclipse控制台上比在使用“本机”控制台时更普遍。

答案 3 :(得分:-2)

提问者说main属于Son级,正在扩展Father。我稍微修改了一下代码,所以我能够编译。

    class Father {
    static{
        System.out.println("f - static");

    }
}

public class Son extends Father {
    static {
        System.out.println("son - static");
    }

public static void main(String[] args) throws ArrayIndexOutOfBoundsException{
        int a[] = new int[2];
        System.out.println(a[3]);
    }
}

输出结果为: -

f - static
son - static
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
    at kanwal.Son.main(Son.java:20)

它的工作原理完全正确。

修改: - 在OP编辑问题之前,已经做出了这个答案。