【问题标题】:Why assigning a final field in a try-catch block within a static block is rejected?为什么在静态块内的 try-catch 块中分配 final 字段被拒绝?
【发布时间】:2015-06-26 16:19:58
【问题描述】:

我正在尝试编写以下课程:

public class Secteur {
    private final static int num_secteur;
    static{
            try {
                num_secteur = SecteurDAO.getCurrNumSecteur();
            } catch (ClassNotFoundException | SQLException e) {
                e.printStackTrace();
            }

    }
}  

但我收到以下警告:

最后的空白字段 num_secteur 可能尚未初始化

SecteurDAO.getCurrNumSecteur() 方法访问数据库以获取将设置为 num_secteur 字段的整数。
我的代码有什么问题?

【问题讨论】:

  • 因为在赋值之前可能会抛出异常。
  • 这有什么危险?
  • 危险在于您可能有一个未初始化的变量,如错误消息所述。如果你不能依赖它被初始化,你必须在类尝试使用它时检查它是否被初始化。
  • 我个人的偏好是在这种情况下不使用静态块,而是使用静态方法返回值。优点是 1)您可以命名该方法以使其显而易见; 2)你不想让方法做很多事情,例如初始化多个变量; 3)您可以随时调用它,例如在单元测试中。

标签: java static initialization final


【解决方案1】:

SecteurDAO.getCurrNumSecteur() 的调用可能会失败(抛出异常),因此没有可分配给num_secteur 的值。因此,如果出现异常,它可能不会被初始化。

要解决此问题,您可能希望使用一些特殊值(例如 -1)对其进行初始化,或者在 catch-block 中设置该值。

哦,删除 final 关键字,否则您会收到错误消息“可能已经分配了最终字段 num_secteur”。那是因为您只能为最终字段分配一次值,即使您知道在发生异常时不会发生分配(因为之前会抛出异常),编译器也无法确定,因此告诉你变量可能已经被赋值了。

【讨论】:

  • 但我想确保我的 num_secteur 字段永远不会被再次分配
  • 然后给两个try/catch块中的temp_int赋值,然后在try/catch之后赋值num_secteur = temp_int。
【解决方案2】:

如前所述,如果出现异常,则变量可能不会在静态初始化程序的末尾分配。

您可能会考虑在 try 块之前或 catch 块之后分配给变量,但这可能导致对变量进行 2 次分配,因此这是不允许的。

您可能会考虑为 catch 块中的变量分配一个无效值,但这仍然会导致对变量进行 2 次分配。

将此变量只分配一次并仍保留num_secteur final 的最佳方法是使用临时变量并将其分配给finally 块中的num_secteur

private final static int num_secteur;
static
{
    int test = -1;  // Invalid value.
    try {
        test = SecteurDAO.getCurrNumSecteur();
    } catch (ClassNotFoundException | SQLException e) {
        e.printStackTrace();
    } finally {
        // Only assigned here, exactly once.
        num_secteur = test;
    }
}

【讨论】:

    猜你喜欢
    • 2012-12-22
    • 2019-02-28
    • 1970-01-01
    • 2011-07-25
    • 2010-09-07
    • 2011-01-01
    • 1970-01-01
    • 2019-04-15
    • 2019-08-31
    相关资源
    最近更新 更多