三元运算符:局部变量可能未被初始化。

3
我有以下的代码片段...
import java.util.Random;

public class ThreeArgumentOperator {

    private static final Random RANDOM = new Random();

    public static void main(String[] args) {
        String test;
        System.out.println(test = getValue() == null ? "" : test);
    }

    public static String getValue() {
        if (RANDOM.nextBoolean()) {
            return "";
        } else {
            return null;
        }
    }

}

Eclipse编译器(我使用Juno)报告以下错误:
本地变量test可能未初始化
我的问题是: 在这种情况下,编译器不应该报告无法将布尔值转换为字符串吗?我理解操作符==优先于=,因此编译器应该抱怨强制类型转换,而不是可能未初始化的值。
当我更改以下行时:
System.out.println(test = getValue() == null ? "" : test);

System.out.println((test = getValue()) == null ? "" : test);
一切正常。
编辑:我也尝试直接使用javac编译它。 它给出相同的错误。
error: variable test might not have been initialized
System.out.println(test = getValue() == null ? "" : test);

应该这样,而在我的情况下确实如此。 - NPE
@NPE是指您遇到了“类型不匹配:无法从布尔值转换为字符串”的错误吗?如果是这样,您使用的编译器是什么? - Jagger
我刚在我的Eclipse中测试了这个,编译器给了我你描述的错误。顺便说一下,我正在使用Sun的JDK 7。 - Luiggi Mendoza
请不要这样做,这容易出现错误。 - user180100
1
@RC 这并不重要它是否易于出错。关键在于编译器在这种情况下给出了误导性的消息。 - Jagger
3个回答

5

编译器报错是正确的。根据运算符优先级,==将首先被评估,然后是三元运算符? :。这意味着逻辑流程如下:

getValue() == null

为了继续,让我们假设这个结果是 false。接下来的表达式如下:
false ? "" : test

这样,最终的结果就是test。我们的最终表达式...
test = test

但是test从未被初始化,因此出现了错误。


这是一个完美的解释!谢谢。 - Jagger
很高兴听到它有用。 :) - cklab

2

我不太明白问题出在哪里。第一个表达式是:

test = getValue() == null ? "" : test

这意味着:如果getValue()返回null,则test将被初始化为空字符串;否则,用test的值进行初始化。
由于test尚未初始化,无法使用自身来初始化test,因此会出现错误消息。
第二个表达式是:
(test = getValue()) == null ? "" : test

这意味着:

  • getValue()的结果初始化test
  • testnull进行比较
  • 如果test为空,则表达式计算为空字符串
  • 否则,它将计算为test的值

为什么它不能编译?


我在哪里写了第二个不应该编译?无论如何,也谢谢你的回答。 - Jagger
好的,我再次阅读了我的问题并重新排列了一些句子,它可能确实有点含糊不清。 - Jagger

0

我完全理解。

第二个编译版本实际上是两个单独的语句。它等同于这段代码:

test = getValue();
System.out.println(test == null ? "" : test);

第一个将一个值分配给test

test = getValue();

现在test有一个值。如果test不为空,第二个语句可以确定表达式结果的值。

第一个无法编译的版本只有一条语句,因为test还没有值,所以要分配给test的值(即test)是未知的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接