4

Versionロード時にマニフェストからバージョン番号を読み取り、Version.MAJOR他の場所で必要な場所などを参照するアプリのクラスを作成しようとしています。しかし、私はそうすることで問題を抱えています。これが私の現在のコードです:

 public class Version {

    public static final int APPCODE;
    public static final int MAJOR;
    public static final int MINOR;
    public static final char RELEASE;
    public static final int BUILD;

    static {

        try {
            Class clazz = Version.class;
            String className = clazz.getSimpleName() + ".class";
            String classPath = clazz.getResource(className).toString();
            if (classPath.startsWith("jar")) {
                String manifestPath = classPath.substring(0, classPath.lastIndexOf("!") + 1) + "/META-INF/MANIFEST.MF";
                Manifest manifest = new Manifest(new URL(manifestPath).openStream());
                Attributes attr = manifest.getMainAttributes();
                APPCODE = Integer.parseInt(attr.getValue("APPCODE"));
                MAJOR = Integer.parseInt(attr.getValue("MAJOR"));
                MINOR = Integer.parseInt(attr.getValue("MINOR"));
                RELEASE = attr.getValue("RELEASE").charAt(0);
                BUILD = Integer.parseInt(attr.getValue("BUILD"));
            }
        } catch (IOException e) {
            System.exit(9001);
        }
    }
}

変数が初期化されていない可能性があるためstatic final(たとえば、間違ったマニフェストがロードされているか、例外がロードされている場合)、これを行うための正しい手順がわかりません。

この質問を読んで、使用しないという洞察が得られましたpublic static finalpublic staticゲッターメソッドを使用する必要がありますか?

4

4 に答える 4

8

フィールドへの代入を常にfinal1 回だけ行うようにすると、コンパイラーは満足します。

public class Version {

    public static final int APPCODE;
    public static final int MAJOR;
    public static final int MINOR;
    public static final char RELEASE;
    public static final int BUILD;

    static {
        int appcode = 0;
        int major = 0;
        int minor = 0;
        char release = 0;
        int build = 0;
        try {
            Class clazz = Version.class;
            String className = clazz.getSimpleName() + ".class";
            String classPath = clazz.getResource(className).toString();
            if (classPath.startsWith("jar")) {
                String manifestPath = classPath.substring(0,
                        classPath.lastIndexOf("!") + 1)
                        + "/META-INF/MANIFEST.MF";
                Manifest manifest = new Manifest(
                        new URL(manifestPath).openStream());
                Attributes attr = manifest.getMainAttributes();
                appcode = Integer.parseInt(attr.getValue("APPCODE"));
                major = Integer.parseInt(attr.getValue("MAJOR"));
                minor = Integer.parseInt(attr.getValue("MINOR"));
                release = attr.getValue("RELEASE").charAt(0);
                build = Integer.parseInt(attr.getValue("BUILD"));
            }
        } catch (IOException e) {
            System.exit(9001);
        }
        APPCODE = appcode;
        MAJOR = major;
        MINOR = minor;
        RELEASE = release;
        BUILD = build;
    }
}
于 2013-01-20T11:59:11.407 に答える
3

私は...するだろう:

  • 最終修飾子を削除します
  • パブリックからプライベートへの可視性を減らします。
  • 必要なフィールドに (静的) ゲッターを提供する
于 2013-01-20T11:56:17.457 に答える
0

フィールドを使用しているpublic final場合、それらは定数であるため、デフォルト値を割り当てる必要があります。可視性をプライベートに変更し、final 修飾子を削除して、getter/setter を提供します。これが問題を解決する最善の方法です。

于 2013-01-20T11:59:14.863 に答える
0

Version クラスからマニフェストの読み取りを処理するコード ブロックを削除し、それを別のクラス (たとえば (ManifestReader)) に配置して、コンストラクターで実際の値を使用してバージョン インスタンスを直接初期化できます。

バージョンクラスのインスタンスが複数ある場合、すべてに独自のアプリコード、メジャーマイナーなどが必要になるため、「パブリック静的ファイナル」を「プライベートファイナル」(静的ではない)に変更します!!

プライベートの最終フィールドにアクセスするためのgetter()を提供することに加えて!

于 2013-01-20T12:21:52.813 に答える