2

私は他の数人と一緒に書いたプログラムのローカリゼーションに取り組んでいます。ほとんどの文字列が、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] は言語コード (現在の es) で、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 クラスを呼び出し、Login クラスが CreateLogin メソッドを呼び出します。このメソッドは Clients.main を呼び出し、渡された GUI から DB_info 配列を取得します。クライアントは DB_info 配列を埋めます。次に Lang.other が呼び出され (ログイン ページの言語固有の文字列を取得するため)、ログイン ボタンとラベルが作成されます。ログインが成功すると、(DB から) ログインしている従業員の優先言語が Lang.main に渡され、他の文字列が読み込まれます (したがって、上記のコードでは emp_lang が渡されます)。

Locale オブジェクトのコードを追加するまでは、すべて正常に機能していました。これで、ExceptionInInitializerError 例外が発生します。何が起こっているか知っている人はいますか?

ところで、ini ファイルからロードするために、私は ini4j を使用しています。グーグルで見つけたいくつかのフォーラム投稿は、これが問題であることを示唆していますが、Locale オブジェクトの問題とどのように関連しているかはわかりません。ini の機能は正常に動作します。

4

2 に答える 2

5

静的イニシャライザにサイクルがあるように聞こえるため、まだ初期化されていないものがあります。

GUILangを取得する前に の静的初期化子を呼び出しますLang.L_WELCOMELang行 2 で s 静的初期化子を呼び出しますGUI。例外トレースでは、何らかの理由で s 静的初期化子をGUI呼び出しているように見えます。Lang

全体として、このようなサイクルは、誰かが静的に初期化されたオブジェクトを参照し、null期待したものではなく取得することを意味します。この場合、 2 行目で 2 つのポインターがコンストラクターにLang.java渡されていると思われます。nullLocale

于 2012-04-26T00:54:44.363 に答える
0

キースが指摘しているように、静的イニシャライザ サイクルがあります。将来の読者を助けるために...

これらのバグを最小限に抑えるには、(複雑な)変数の前に (単純な)定数を (コンストラクターがないか最小限のコンストラクターで) 初期化します。StringLocale

デバッグNullPointerExceptionに関しては、静的フィールドとスタック トレースの 2で、以前のクラスが失敗した行に表示されており、これが静的初期化子サイクルによって引き起こされた初期化されていないフィールド<clinit>であるという手がかりです。

于 2015-07-16T05:00:04.710 に答える