【问题标题】:Java - Can final variables be initialized in static initialization block?Java - 可以在静态初始化块中初始化最终变量吗?
【发布时间】:2010-02-26 06:47:37
【问题描述】:

根据我对Java语言的理解,静态变量可以在static initialization block初始化。

但是,当我尝试在实践中实现这一点时(static 变量也是 final),我收到下面屏幕截图中显示的错误:

【问题讨论】:

    标签: java static final


    【解决方案1】:

    当然是的:static final 变量可以在静态块中初始化但是....在那个例子中你有隐式 GOTO(try/catch 本质上是一个 'GOTO catch如果发生了不好的事情')。

    如果抛出异常,您的 final 变量将不会被初始化。

    请注意,使用静态结构违背了面向对象的教条。它可能会使您的测试复杂化并使调试更加困难。

    【讨论】:

    • 我可以从static initialization block 抛出异常吗?当static initialization block 中的代码抛出一些我不想处理的异常时,我该怎么办。
    • @awk:如果异常抛出代码是 getString(...) 方法调用,他将需要使用本地人来完成分配。
    • @Kevin 当然,最终变量必须分配给某些东西,所以在 catch 块中他可能会将其分配给 null
    • e.printStackTrace() 本身在一个 catch 块中让我哭了。
    • 您需要确保在退出静态块之前初始化最终的静态变量。在您的情况下,也可以在 catch 块中初始化它们,或者根据您的要求更好地使用 finally 块
    【解决方案2】:

    您可以这样做,但您需要通过抛出异常来退出静态块 - 您可以重新抛出已捕获的异常或新异常。通常,此异常必须是RuntimeException。您真的不应该捕获通用的 Exception 而是可能从您的 try 块中抛出的更具体的异常。最后,如果静态初始化程序抛出异常,那么它将在特定运行期间使类不可用,因为 JVM 只会尝试初始化您的类一次。后续尝试使用该类将导致另一个异常,例如NoClassDefFoundError

    所以,为了工作,你的初始化程序应该是这样的:

    static {
        try {
            ...
        } catch (Exception e) {
            e.PrintStackTrace();
            throw new InitializationFailedException("Could not init class.", e);
        }
    }
    

    假设InitializationFailedException 是自定义RuntimeException,但您可以使用现有的。

    【讨论】:

      【解决方案3】:
      public class MyClass
      {
          private static final SomeClass myVar;
      
          static
          {
              Object obj = null;  // You could use SomeClass, but I like Object so you can reuse it
              try
              {
                  obj = new SomeClass(...);    
              }
              catch(WhateverException err)
              {
                  // Possibly nested try-catches here if the first exception is recoverable...
                  // Print an error, log the error, do something with the error
                  throw new ExceptionInInitializerError(err); 
              }
              finally
              {
                  myVar = (SomeClass) obj;
              }
          }
      }
      

      假设上游无法捕获 ExceptionInInitializationError 或一般 Exception,则程序不应尝试使用 myVar。但是,如果这些被捕获并且程序没有结束,那么您需要编写代码来观察和处理 myVar 是否为空(或者对 NullPointerExceptions 的出现感到满意)。

      我不确定有什么好的方法来处理这个问题。

      【讨论】:

      • >>> 那么你需要编写代码来观察和处理 myVar 为 null 这里静态初始化程序抛出一个异常,它会阻止类被加载(因此变量不能在未初始化的情况下被引用)因此无需担心 NPE(空指针异常)
      【解决方案4】:

      你能把声明放在 finally 块中吗?

      try {
          //load file
      } catch(IOException e) {
          // horay
      } finally {
          HOST=config.get......
      }
      

      【讨论】:

        猜你喜欢
        • 2013-09-30
        • 1970-01-01
        • 2010-12-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-06
        相关资源
        最近更新 更多