6

启动时,我的程序立即抛出 ExceptionInInitializerError。来源来自这个方法:

public static void errorMessage(String input) {
    System.err.println("[ERROR] " + form.format(date) + " - " + Thread.currentThread().getStackTrace()[3].getClassName() + ": " + input);
}

我打印出字符串的不同部分,发现只有在调用form.format(date)时才会抛出错误。它说它是空的。唯一的问题是,日期和表单都在此方法上方静态声明,如下所示:

public static Date date = new Date();
public static DateFormat form = new SimpleDateFormat("HH:mm:ss");

在修复了一些小错误后,错误突然开始抛出。我不知道出了什么问题,也不知道这有什么问题。我的意思是,我在同一个类中调用静态声明的变量。从技术上讲,它们不应该为空,但它们确实是。任何人都有任何想法为什么会引发此错误?这是控制台输出:

java.lang.ExceptionInInitializerError
at A$$OpSystem.getOperatingSystem(A$.java:98)
at A_.<clinit>(A_.java:19)
Caused by: java.lang.NullPointerException
at A$.errorMessage(A$.java:72)
at A$.loadCursor(A$.java:84)
at A$.<clinit>(A$.java:62)
... 2 more
Exception in thread "main" 

顺便说一句,A$.OpSystem.getOperatingSystem 只显示在那里,因为它调用了 A$.errorMessage...

我之前也遇到过这个问题,只是当一个静态声明的变量实际上从未被声明为在调用时保持为空。现在它不应该为空,但它是。所以我不知道是什么原因造成的。想法?

但我想这是了解静态变量如何实际加载的好时机......

编辑:如果我将调用“loadCursor”的静态光标对象移动到不同的类,似乎不会引发异常。什么?

我对这种情况进行了测试,但它没有返回错误?

public class StaticMethodTesting {

public static int i = getInt();

public static int getInt() {
    return getAnotherInt();
}

public static int getAnotherInt() {
    return 0;
}

public static void main(String[]args) {
    System.out.println("Hi");
}
}
4

2 回答 2

8

检查您的异常跟踪后...

at A$.errorMessage(A$.java:72)
at A$.loadCursor(A$.java:84)
at A$.< clinit>(A$.java:62)

很明显,一些静态字段初始化 in在初始化and和调用A$之前执行,然后在逻辑上失败as并且未初始化。dateformloadCursorNullPointerExceptiondateform

问题是您已将初始化您的代码放在初始化您的和对象的代码Cursor之前。根据 Java Language Specification 的第 8.3.2.1 节,在声明时具有赋值的静态字段按声明顺序初始化。dateform

如果您阅读详细的初始化过程,尤其是第 §12.4.2.9 节,您会发现...

接下来,按文本顺序执行类的类变量初始化程序和静态初始化程序,或者接口的字段初始化程序,就好像它们是一个块一样。


所以,你可能会做这样的事情:

static Cursor cursor = loadCursor();
static Date date = new Date();
static DateFormat form = new SimpleDateFormat("HH:mm:ss");

static Cursor loadCursor() {
  ...
  errorMessage("...");
  ...
}

loadCursor如果您希望它工作,则不能在之前调用date并初始化。form


您的示例没有产生“错误”(嗯?)的原因是因为这两种方法都没有引用尚未初始化的字段。如果您想要绝不是错误的等效行为,请参阅以下内容(可以在此处运行):

import java.util.Random;

public final class Example {

  /* note if the below read: static final int value = rand.nextInt(),
     this would be considered an illegal forward reference to rand */
  private static final int value = next();
  private static final Random rand = new Random();

  private static int next() {
    return rand.nextInt();
  }

  public static void main(final String[] argv) { }
}

可以看到输出如下。

Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.NullPointerException
        at Example.next(Example.java:11)
        at Example.<clinit>(Example.java:7)
于 2012-08-15T03:24:20.627 回答
0

我想你会发现问题在这里发生

Thread.currentThread().getStackTrace()[3].getClassName() 

您可能需要做更多类似的事情

StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
String className = stackTrace[Math.min(3, stackTrace.length - 1)].getClassName();

或类似的:P

于 2012-08-15T03:14:09.193 回答