Java:构造Locale对象时由NullPointerException引起的ExceptionInInitializerError

时间:2012-04-26 00:35:45

标签: java object nullpointerexception locale static-initializer

我正在为我和其他几个人写过的程序进行本地化。现在大多数字符串都是从ini文件中以适当的语言加载的。我试图用程序中的货币格式做同样的事情。但是,一旦我尝试启动应用程序,我就会收到运行时异常。

我正在使用Locale对象作为一些NumberFormat.getCurrencyInstance()的参数,如下所示:

private static final NumberFormat decf;
static 
{
    decf = NumberFormat.getCurrencyInstance(Lang.cLocale);
    decf.setRoundingMode(RoundingMode.HALF_UP);
}

Lang是包含所有本地化内容的类。 IDE在尝试运行时抱怨的代码是public static Locale cLocale = new Locale(GUI.DB_info[19],GUI.DB_info[20]);

GUI是包含GUI的类,我们决定构建DB_info数组(它本身只包含从另一个类的远程数据库加载的信息)。 DB_info [19]是语言代码(现在是),DB_info [20]是国家代码(US)。数组元素正在被填充 - 或者说,我现在无法进入该程序;但填充DB_info的代码没有任何改变。

完整的例外情况如下:

Exception in thread "main" java.lang.ExceptionInInitializerError
at greetingCard.GUI.<clinit>(GUI.java:118)
Caused by: java.lang.NullPointerException
at java.util.Locale.<init>(Unknown Source)
at java.util.Locale.<init>(Unknown Source)
at greetingCard.Lang.<clinit>(Lang.java:13)
... 1 more

引用的GUI中的行是:static String welcome = Lang.L_WELCOME + ", " + empName;,而Lang.java基本上是这样的:

// Set locale for currency display
public static Locale cLocale = new Locale(GUI.DB_info[19],GUI.DB_info[20]); // language, country

// Employee specific strings
public static String L_AMT_REMAIN = "";
public static String L_AMT_TEND = "";
public static String L_APPROVED = "";
public static String L_ARE_YOU_SURE = "";
[...]

public static void Main(String emp_lang)
{
    String header = "";

    if (emp_lang.equals("ENG"))
    {
        header = "ENG";
    }
    else if (emp_lang.equals("SPA"))
    {
        header = "SPA";
    }
    else if (emp_lang.equals("FRE"))
    {
        header = "FRE";
    }
    else if (emp_lang.equals("GER"))
    {
        header = "GER";
    }
    else
    {
        header = "ENG";
    }

    try 
    {
        Ini ini = new Ini(new File("C:/lang.ini"));

        L_AMT_REMAIN = ini.get(header, "L_AMT_REMAIN");
        L_AMT_TEND = ini.get(header, "L_AMT_TEND");
        L_APPROVED = ini.get(header, "L_APPROVED");
        L_ARE_YOU_SURE = ini.get(header, "L_ARE_YOU_SURE");
                    [...]
                                L_WELCOME = ini.get(header, "L_WELCOME");
        L_WELCOME2 = ini.get(header, "L_WELCOME2");
        L_XACT_CHNG = ini.get(header, "L_XACT_CHNG");  
        L_YES = ini.get(header, "L_YES");

        System.err.println("Employee Language: " + header);
    } 
    catch (InvalidFileFormatException e) 
    {
        e.printStackTrace();
    } 
    catch (IOException e) 
    {
        e.printStackTrace();
    }
} // end public static void main

这是大多数字符串以不同语言显示的。 Lang内部还有另一种加载其他字符串的方法,与第一组无关。我不相信它会影响这个问题但我可以在需要时发布它。

启动这些类/方法的顺序如下: GUI.Main调用Login类,该类调用CreateLogin方法。该方法调用Clients.main,它从GUI传递给它的DB_info数组。客户端填充DB_info数组。然后调用Lang.other(为登录页面获取特定于语言的字符串),并创建登录按钮和标签。登录成功后,登录(从DB)的员工的优先语言将传递给Lang.main以加载其他字符串(因此在上面的代码中传递emp_lang)。

直到我添加了Locale对象的代码,所有这一切都运行正常。现在我得到了ExceptionInInitializerError异常。有谁知道发生了什么事?

BTW,从ini文件加载我正在使用ini4j。我在google搜索时发现的一些论坛帖子表明这是一个问题,但我不知道它与Locale对象的问题有什么关系。 ini的东西很好用(工作)。

2 个答案:

答案 0 :(得分:5)

听起来你的静态初始化器中有一个循环,所以还没有初始化。

GUI在获取Lang之前调用Lang.L_WELCOME的静态初始值设定项。 Lang在第2行调用GUI的静态初始值设定项。由于某种原因,您的异常跟踪使其看起来像GUI调用Lang的静态初始值设定项。

总而言之,这样的循环意味着某人将引用静态初始化的对象并获得null而不是他们期望得到的对象。在这种情况下,我怀疑第{2}行Lang.java正在向null构造函数传递两个Locale指针。

答案 1 :(得分:0)

正如Keith所说,你有一个静态初始化周期。为了帮助未来的读者......

为了最大限度地减少这些错误,请在(复杂)变量之前初始化(简单)常量(没有或最少构造函数),所以String之前Locale 1}} - 减少造成问题的周期的空间。

调试方式,静态字段上的NullPointerException和堆栈跟踪中的2 <clinit>,其中较早的类出现在失败的行中,这是未初始化字段<的线索/ em>由静态初始化程序循环引起。