简体   繁体   中英

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.

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

strAll += inputLine;

using "addition assignment" you get the warning:

The value of the local variable strAll is not used

If you replace the while condition with (true), the warning for strAll disappears. 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.

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 .

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.

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.

This warning is not part of the Java language, or even the Java compiler. 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. 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. 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 :

strAll += inputLine is a "compound assignment expression". 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.

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.

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. 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...

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.

Regarding while (true) , I think (without looking closer), that flow analysis just stops short when it finds that a method cannot complete normally.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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