21

我一直在 Java 中遇到一个问题的细微变化,它开始影响到我,我真的想不出一个合适的方法来解决它。

我有一个最终但动态的对象属性。也就是说,我希望该值在分配后保持不变,但每个运行时该值可能不同。所以我在类的开头声明了类级别的变量——比如说private final FILE_NAME;。然后,在构造函数中,我给它赋值——比如说FILE_NAME = buildFileName();

当我在buildFileName()引发异常的方法中有代码时,问题就开始了。所以我在构造函数中尝试这样的事情:

try{
   FILE_NAME = buildFileName();
}
catch(Exception e){
   ...
   System.exit(1);
}

现在我有一个错误 - “空白的最终字段 FILE_NAME 可能尚未初始化。” 这就是我开始对 Java 的严格编译器有点恼火的地方。我知道这不会成为问题,因为如果它被捕获,程序将退出......但编译器不知道,因此不允许此代码。如果我尝试向 catch 添加一个虚拟分配,我会得到 - “最终字段 FILE_NAME 可能已经被分配。” 我显然不能在 try-catch 之前分配默认值,因为我只能分配一次。

有任何想法吗...?

4

5 回答 5

20

怎么样

String tempName = null;
try{
   tempName = buildFileName();
}
catch(Exception e){
   ...
   System.exit(1);
}
FILE_NAME = tempName;
于 2010-05-05T13:55:38.087 回答
7

任何一个

try {
   FILE_NAME = buildFileName();
} catch (Exception e){
   ...
   System.exit(1);
   throw new Error();
}

或者有些人更喜欢:

private static final String FILE_NAME = fileName();

private static String fileName() {
    try {
        return buildFileName();
    } catch (Exception e){
        ...
        System.exit(1);
        throw new Error();
    }
}

但是调用System.exit静态初始化器可能是个坏主意。它会弄乱你的单元测试。

于 2010-05-05T14:07:19.143 回答
4

转念一想,我想我只是想出了一个解决方案!- 使用中间变量。

String fileName = null;
try{
   fileName = buildFileName();
}
catch(Exception e){
   ...
   System.exit(1);
}
FILE_NAME = fileName;

不知道为什么我花了这么长时间才想到这个……

于 2010-05-05T13:55:15.983 回答
1

我个人会抛出一个错误——如果你的错误流程设计得当, System.exit() 应该是多余的。如果抛出错误,您的程序可能不会进入荒野......?

于 2010-05-05T14:16:25.230 回答
0

与 OP 的问题一样,我必须能够找到一种方法来为要从文件系统上的 .properties 文件中读取的最终字段分配值,因此在此之前我的应用程序无法知道这些值发生了。在应用程序启动时将 .properties 文件的内容读入 Properties 对象后,使用通用方法调用来分配值是一个 Hail Mary 通行证,谢天谢地。它也限制了编号。每次应用程序加载到内存中时,文件必须被读取一次,只需通过代码检查来查看 Properties 对象当前是否为空。但是当然,一旦分配,最终字段的值就不能改变,除非通过操纵字段来改变其“最终”状态'https://stackoverflow.com/a/3301720/1216686 - 鬼鬼祟祟,但我喜欢它!)。代码示例,为简洁起见,省略了典型的运行时错误检查,例如 NPE:

import java.util.Properties;

public class MyConstants {

  private static Properties props; // declared, not initialized,
                                   // so it can still be set to
                                   // an object reference.

  public static String MY_STRING = getProperty("prop1name", "defaultval1");
  public static int MY_INT = Integer.parseInt(getProperty("prop2name", "1"));
  // more fields...

  private static String getProperty(String name, String dflt) {
   if ( props == null ) {
     readProperties();
   }
   return props.getProperty(name, dflt);
  } 

  private static void readProperties() {
     props = new Properties(); // Use your fave way to read
                      // props from the file system; a permutation
                      // of Properties.load(...) worked for me.
  } 

  // Testing...
  public static void main(String[] args) {
      System.out.println(MY_STRING);
      System.out.println(MY_INT);
  }

}

这使您可以将要读入应用程序的属性外部化,并且仍然将用于保存其值的字段标记为“最终”。它还允许您保证最终字段值的返回值,因为 Properties 类中的 getProperty() 允许方法的调用代码传入默认值,以防在外部找不到属性的键值对时使用.properties 文件。

于 2014-10-28T22:13:39.920 回答