简体   繁体   English

vscode:在“while ((inputLine = in.readLine()).= null)”-循环中。 x = x + a 没有警告:与:x += a “未使用局部变量的值”

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

The following is an example from https://docs.oracle.com/javase/tutorial/networking/urls/readingURL.html , the only change is that the content of the String inputLine is added up to the strAll String instead of printing it, see X_HERE. The following is an example from https://docs.oracle.com/javase/tutorial/networking/urls/readingURL.html , the only change is that the content of the String inputLine is added up to the strAll String instead of printing it ,见 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();
    }
}

This throws no warning.这不会引发任何警告。 If you replace line X_HERE with如果将行 X_HERE 替换为

strAll += inputLine;

using "addition assignment" you get the warning:使用“加法分配”你会得到警告:

The value of the local variable strAll is not used未使用局部变量 strAll 的值

If you replace the while condition with (true), the warning for strAll disappears.如果将 while 条件替换为 (true),strAll 的警告就会消失。 Why is "addition assignment" treated differently in this context?为什么在这种情况下对“加法赋值”有不同的处理?

Edited thanks to @Joni: I am using Visual Studio Code, the warning appears in the “Problems” Window.感谢@Joni 编辑:我正在使用 Visual Studio Code,警告出现在“问题”Window 中。

Here is a simpler, isolated, instance of the same effect.这是相同效果的一个更简单、孤立的实例。

Both of these variations compile to the same byte code.这两种变体都编译为相同的字节码。

In this example,在这个例子中,

a += 1;

The IDE sees a being updated by 1 but does not see a direct usage of a . IDE 看到a被更新了 1 但没有看到 a 的直接a

In this example,在这个例子中,

a = a + 1;

The IDE sees a being used in the expression a + 1 and then assigned back to a , hence from the IDE's perspective, a has been used. IDE 看到a在表达式a + 1中使用,然后分配回a ,因此从 IDE 的角度来看, a已被使用。

Just assigning a value to a variable does not constitute usage.仅仅为变量赋值并不构成使用。

Note that this unused behavior is also present in the Eclipse IDE but can be disabled if desired.请注意,这种unused的行为也存在于Eclipse IDE中,但可以根据需要禁用。

This warning is not part of the Java language, or even the Java compiler.此警告不是 Java 语言的一部分,甚至不是 Java 编译器的一部分。 It's just visual studio code trying to be helpful.这只是试图提供帮助的视觉工作室代码。

This is a bug or a limitation in the static code analysis feature in vs code.这是 vs 代码中 static 代码分析功能中的错误或限制。 It's counting strAll = strAll + inputLine as a "use" of the variable strAll , while it's not counting the equivalent strAll += inputLine as a "use" of the variable.它将strAll = strAll + inputLine为变量strAll的“使用”,而没有将等效的strAll += inputLine为变量的“使用”。 If the code analysis was smarter it would give you a "unused variable" warning for both cases.如果代码分析更智能,它将在这两种情况下为您提供“未使用的变量”警告。

For completeness here's my answer from the github issue :为了完整起见,这是我对github 问题的回答:

strAll += inputLine is a "compound assignment expression". strAll += inputLine是一个“复合赋值表达式”。 Because this is a built-in structure of Java, ecj (Eclipse Compiler for Java, which is used in vscode) knows about the specifics of this construct, in particular it tracks that the implicit read doesn't create a data flow from strAll to another variable or argument.因为这是 Java 的内置结构,所以 ecj(用于 Java 的 Eclipse 编译器,在 vscode 中使用)知道这个结构的细节,特别是它跟踪隐式读取不会创建从strAll到的数据流另一个变量或参数。

strAll = strAll + inputLine , however is just one out of a myriad of forms, where the human reader will readily see that strAll really flows no-where. strAll = strAll + inputLine只是无数 forms 中的一个,人类读者很容易看到strAll真的无处可去。

While the decision to treat both forms differently was made before my time at Eclipse, I am pretty sure that the team saw this as the cleanest line to be drawn between things ecj can reason about and things that are just too complex.虽然在我任职 Eclipse 之前就已经做出了对 forms 进行不同处理的决定,但我很确定团队认为这是 ecj 可以推理的事情和过于复杂的事情之间最清晰的界限。 Some examples of what would need to be discussed when extending the flow analysis:扩展流量分析时需要讨论的一些示例:

  • strAll = "foo" + strAll + "bar";
  • strAll = (bar = strAll) + "foo";
  • strAll = convert(strAll); // this one is trickier than it looks on first sight // 这个比第一眼看起来更棘手
  • etc. pp.等。

So the pattern would likely be that ecj gives you a finger and people will take the whole arm, or more...所以模式很可能是 ecj 给你一个手指,人们会拿走整个 arm,或者更多......

Bottom line: Use Java specifics appropriately if you want to give more information to the Java compiler:) A compound assignment conveys more information than its long form.底线:如果您想为 Java 编译器提供更多信息,请适当使用 Java 详细信息:) 复合赋值比其长形式传达更多信息。

Regarding while (true) , I think (without looking closer), that flow analysis just stops short when it finds that a method cannot complete normally.关于while (true) ,我认为(没有仔细观察),当发现方法无法正常完成时,流分析就会停止。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM