编译器说"变量可能没有被初始化",虽然我有一个标志变量来保证它

use*_*610 18 java

这是我的代码片段:

Someclass someObject;
boolean success = true;
try {
    someObject = someOperation();
} catch (Exception e) {
    success = false;
}
if (success) {
    int number = Integer.valueOf(someObject.someMethord());
}
Run Code Online (Sandbox Code Playgroud)

并在行内:

 int number = Integer.valueOf(someObject.someMethord());
Run Code Online (Sandbox Code Playgroud)

Java编译器抛出错误说

错误:变量some​​Object可能尚未初始化.

但是,如果success等于true,则没有办法someObject不会被初始化,为什么我会收到此错误?

Era*_*ran 51

编译器不会分析success标志和someObject变量初始化之间的关系.

就编译器而言,someObject如果发生异常,则可能无法初始化.

您可以通过null在catch块中设置变量来解决该问题(而不是检查您的success变量,检查它someObject != null).

或者您可以int number = Integer.valueOf(someObject.someMethord());在try块中移动语句.

  • @KonradRudolph更准确:Java语言规范要求编译器应该实现哪些检查.与C不同,Java编译器没有广泛的自由来推理代码正确性等问题. (13认同)
  • @xxxvodnikxxx静态分析*可以*告诉`someObject`在使用时总是完全初始化.这就是为什么*我们*(读者)可以说出来的原因.但是,这种静态分析在一般情况下计算量很大(尽管在这个小例子中它是相当简单的),因此不是由Sun的Java编译器实现的. (11认同)

nne*_*neo 11

Java语言规范(JLS)确切地定义了编译器应该如何分析这样的代码.

在您的情况下,局部变量在块中使用之前someObject明确赋值if.JLS第16章中涉及的明确赋值定义了可以将变量视为("初始化")的确切规则.

它分别分析tryif陈述.之后try,someObject没有明确赋值,因为它不是在分配catch块.在if,条件可以是truefalse.如果是true,则会出现错误,因为此时someObject未明确分配.

不允许 Java编译器分析此代码并"弄清楚" success只有在someObject分配iff时才能生效,因为语言规则规定了必须执行的精确分析.这不是编译器不够智能的情况 - 这是Java语言标准严格的情况.

请注意,如果您使用if(false)而不是if(success)您将不会收到错误,因为JLS指定这false是一个常量表达式,因此循环体将永远不会执行.


无论如何,标志变量是不必要的.将依赖代码移入try,或将变量设置为null声明并显式检查someObject != null是所有方法都更容易理解,更不容易出错.


Gui*_*rré 9

您可以像这样更改声明:

Someclass someObject = null;
Run Code Online (Sandbox Code Playgroud)

或者您可以在try-catch中执行所有操作以确保someObject正确初始化

try {
    Someclass someObject = someOperation();
    int number = Integer.valueOf(someObject.someMethod());
} catch (Exception e) {
    //...
}
Run Code Online (Sandbox Code Playgroud)