2013-01-20 60 views
3

我正在尝试为我的应用程序制作一个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变量可能未初始化,我无法弄清楚什么正确的程序是这样做的。

阅读this问题给了我一些见解,不使用public static final。我宁愿使用public static与getter方法吗?

回答

3

我想:

  • 除去最后修饰
  • 从公众减少对私人的知名度。
  • 提供(静态)干将为所需字段
+0

这工作,谢谢。 – Logan

6

如果你确保你总是分配给final领域恰好一次,编译器会很高兴:

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; 
    } 
} 
+0

+1,用于说明如何通过覆盖*所有*执行路径来初始化最终字段。 – Perception

0

如果您正在使用public final字段您必须分配默认值,因为这些是常量。将可见性更改为私有并删除最终修饰符并提供getter/setter。这应该是解决您的问题的最佳方式。

0

您可以删除处理从Version类读取清单的代码块,并将其放入单独的类中(例如(ManifestReader)),并直接用构造函数中的实际值初始化版本实例。

我会将“公共静态最终”更改为“私人最终”(非静态),因为如果您有多个版本类的实例,所有必须拥有自己的应用代码,主要次要等!

旁边提供getter()访问私人最终字段!

相关问题