vscode:在 "while ((inputLine = in.readLine()) != null)" 循环中。 x = x + a 没有警告。与:x += a "value of the local variable is not used"

vscode: in "while ((inputLine = in.readLine()) != null)"-loop. x = x + a without warning. Versus: x += a "value of the local variable is not used"

下面是来自https://docs.oracle.com/javase/tutorial/networking/urls/readingURL.html的例子,唯一的变化是将String inputLine的内容加到strAll String中,而不是打印出来,见X_HERE.

import java.net.*;
import java.io.*;

public class URLReader {
    public static void main(String[] args) throws Exception {

        URL oracle = new URL("http://www.oracle.com/");
        BufferedReader in = new BufferedReader(
        new InputStreamReader(oracle.openStream()));

        String inputLine;
        String strAll = "";
        while ((inputLine = in.readLine()) != null)
            // System.out.println(inputLine);
            strAll = strAll + inputLine; // X_HERE
        in.close();
    }
}

这不会引发任何警告。如果将行 X_HERE 替换为

strAll += inputLine;

使用“加法赋值”你会收到警告:

The value of the local variable strAll is not used

如果将 while 条件替换为 (true),strAll 的警告将消失。为什么“加法赋值”在这种情况下会受到不同对待?

感谢@Joni 编辑:我正在使用 Visual Studio 代码,警告出现在“问题”Window。

这是具有相同效果的更简单的孤立实例。

这两种变体都编译成相同的字节码。

在这个例子中,

a += 1;

IDE 看到 a 被 1 更新,但没有看到直接使用 a

在这个例子中,

a = a + 1;

IDE 看到 a 被用在表达式 a + 1 中,然后分配回 a,因此从 IDE 的角度来看, a 已被使用。

只是给变量赋值不构成用法。

请注意,此 unused 行为也存在于 Eclipse IDE 中,但如果需要可以禁用。

此警告不是 Java 语言的一部分,甚至不是 Java 编译器的一部分。这只是 visual studio 试图提供帮助的代码。

这是 vs 代码中静态代码分析功能的错误或限制。它将 strAll = strAll + inputLine 计为变量 strAll 的“使用”,而不将等效的 strAll += inputLine 计为变量的“使用”。如果代码分析更智能一些,它会针对这两种情况给出“未使用的变量”警告。

为了完整起见,这是我在 github issue:

中的回答

strAll += inputLine 是一个“复合赋值表达式”。因为这是 Java 的内置结构,ecj(用于 Java 的 Eclipse 编译器在 vscode 中使用)了解此构造的细节,特别是它跟踪隐式读取不会创建从 strAll 到另一个变量或参数的数据流。

然而,

strAll = strAll + inputLine 只是无数形式中的一种,人类 reader 很容易看到 strAll 真的无处可去。

虽然在我加入 Eclipse 之前就决定区别对待这两种形式,但我很确定团队认为这是在 ecj 可以推理的事物和过于复杂的事物之间划定的最清晰的界线.扩展流分析时需要讨论的一些示例:

  • strAll = "foo" + strAll + "bar";
  • strAll = (bar = strAll) + "foo";
  • strAll = convert(strAll); // 这个比第一眼看起来更棘手
  • 等页数

所以模式很可能是 ecj 给你一根手指,人们会拿整个手臂,或者更多...

底线:如果您想向 Java 编译器提供更多信息,请适当使用 Java 细节 :) 复合赋值比其长形式传达更多信息。

关于while (true),我认为(不仔细看)流分析只是在发现方法无法正常完成时才停止。