在构造函数中初始化公共静态最终变量
Posted
技术标签:
【中文标题】在构造函数中初始化公共静态最终变量【英文标题】:Initializing public static final variables in constructor 【发布时间】:2013-01-03 15:45:04 【问题描述】:我正在尝试为我的应用程序创建一个 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 方法一起使用?
【问题讨论】:
【参考方案1】:如果您确保始终只为 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;
【讨论】:
+1,用于说明如何通过覆盖所有执行路径来初始化最终字段。【参考方案2】:我愿意:
删除最后的修饰符 将可见性从公共降低到私人。 为所需字段提供(静态)getter【讨论】:
【参考方案3】:如果您使用public final
字段,则必须分配默认值,因为它们是常量。将可见性更改为私有并删除 final 修饰符并提供 getter/setter。这应该是解决您的问题的最佳方式。
【讨论】:
【参考方案4】:您可以从 Version 类中删除处理读取清单的代码块并将其放入单独的类中 - 例如 (ManifestReader) - 并在构造函数中直接使用实际值初始化版本实例。
我会将“public static final”更改为“private final”(不是静态的),因为如果您有多个 Version 类实例,则所有实例都必须有自己的应用代码、主要次要等!!
除了提供 getter() 来访问私有 final 字段!
【讨论】:
以上是关于在构造函数中初始化公共静态最终变量的主要内容,如果未能解决你的问题,请参考以下文章
java中静态方法,静态变量,静态初始化器,构造函数,属性初始化都是啥时候调用的? 它们的先后顺序。