Netbeans Java抱怨最终变量没有被初始化

时间:2013-05-29 08:37:55

标签: java netbeans

考虑以下代码:

final MyClass myObject;
try {
    myObject = new MyClass(...)
} catch (MyClassException){
    // terminate
    System.exit(1);
}

myObject.doSomething();

问题是Netbeans编辑器/解析器认为可以在一个单元化对象上调用.doSomething(),当然情况并非如此。

是否存在规避这种情况的正常/标准模式?我可以调用函数但不愿意这样做。我还不是将整个块都包含在try catch块中,因为没有别的东西会抛出MyClassException

我不是(还有;-))Java语法和模式方面的专家,所以我希望我能错过一些明显的东西。

6 个答案:

答案 0 :(得分:5)

您在try块中初始化对象,这可能会抛出异常,使对象保持未初始化状态。

在你的catch块中,你停止你的程序,但System.exit(1)不会停止方法执行,而是terminates currently running JVM - 对于编译器而言,它只是你调用的另一种方法被扔了。

return实际上会停止执行方法 - 因此不会超出return;之外的代码。 您可以修改catch块,如下所示:

catch (MyClassException){
    // terminate
    System.exit(1);
    return;
}

编译器不会抱怨myObject没有以这种方式初始化。

修改

注意:如果你将myObject.doSomething();放入finally块编译器会抱怨,因为finally即使在return之后也会执行。

finally {
    // compiler error
    myObject.doSomething();
}

答案 1 :(得分:1)

案例是在try / catch块之外,您尝试在可能未实例化的对象上调用方法。这是因为try / catch块可能会抛出异常,因此不会创建对象,因此在这种情况下,当您尝试在其上调用doSomething()方法时,您将没有对象。

如果在try / catch块中包含方法调用,它将起作用。

您可以在此处找到相关信息: Java Tutorials: Lesson: Exceptions

答案 2 :(得分:1)

这是我能做的最好的事情:

final MyClass myObject;
{
    MyClass local = null;
    try {
        local = new MyClass(...)
    } catch (MyClassException){
        // terminate
        System.exit(1);
    }
    myObject = local;
}

myObject.doSomething();

答案 3 :(得分:1)

  

问题是Netbeans编辑器/解析器认为可以在一个单元化对象上调用.doSomething(),当然情况并非如此。

这种情况:没有什么可以阻止您使用SecurityManager来禁止System.exit()退出JVM。在这种情况下,下一个语句可以执行。

从Java语法的角度来看,当您调用myObject时,编译器需要证明myObject.doSomething(); 明确分配了

JLS指定可以执行此操作的情况。特别是,可用于确定下一条指令不会被执行的唯一语句是breakcontinuereturnthrow。因此,不允许编译器认为System.exit(1);将阻止执行下一个语句。

答案 4 :(得分:0)

  

Netbeans编辑器/解析器认为.doSomething()可以在一个单元化对象上调用,当然情况并非如此。

你错了。您实际上尝试来初始化变量。编译器在初始化中不“信任”,原因很简单:可以抛出一个异常,你可以抓住但不抛出一个新的{{1}或者制作一个RuntimeException()。例如:

System.exit(1)

你可以捕获异常,打印堆栈跟踪并继续程序,结果将是try { myObject = new MyClass(...) } catch (MyClassException e){ // hey I catch this but do nothing lmao yolo e.printStackTrace(); } myObject.doSomething();

答案 5 :(得分:0)

始终初始化final变量和成员的要点。虽然您的代码永远不会调用doSomething,但它会使最终字段保持未定义状态。如果向try-catch块添加finally子句,这将成为一个问题 - 当发生异常并且finally将不可用时,您可以输入myObject子句,编译器必须避免。一个快速的解决方案是在try块中移动doSomething调用:

final MyClass myObject;
try {
    myObject = new MyClass(...);
    myObject.doSomething();
} catch (MyClassException){
    // terminate
    System.exit(1);
}

只要doSomething没有抛出MyClassException,这应该可以正常工作。如果它抛出这样的异常,你可能需要区分它是来自构造函数还是方法(当然这对你的逻辑来说很重要)。