1

I'm surprised that, if I remove the first assignment, I get a compilation error. The code is the following one:

public void antlr(String fullyQualifiedFilename) {
    String path = null;
    try {
      path = new File(fullyQualifiedFilename).getParent();
      if (path != null) {
        path = new File(path).getCanonicalPath();
      }
    } catch (IOException ioe) {
      //...
    }
    if (path != null) {
      int f;
    }
  }

and I want to remove the variable initialisation and keep just the declaration. Indeed:

public void antlr(String fullyQualifiedFilename) {
    String path;
    try {
      path = new File(fullyQualifiedFilename).getParent();
      if (path != null) {
        path = new File(path).getCanonicalPath();
      }
    } catch (IOException ioe) {
      //...
    }
    if (path != null) {
      int f;
    }
  }

The error I get is the following: Example.java:19,9: error: Local variable path is not assigned before used That make sense expect that the first File constructor throws only the unchecked exception NullPointerException and getParent() does not throw any checked exceptions. So, the first assignment is always compute expect if an unchecked exception is thrown. What I mean is that the compiler have all the necessary information to know that the first assignment path = new File(fullyQualifiedFilename).getParent() is always executed.

This This is what I think the Control Flow Graph should be.

Am I wrong ? Am I missing something?

  • 3
    ```the first assignment path = new File(fullyQualifiedFilename).getParent() is always executed.``` UNLESS there is an exception and there will be no assignment. – tomerpacific Jul 13 '20 at 08:05
  • Yes exactly and the only exceptions that can be raised are unchecked (and the compiler knows that I'm handling only IOException in this Try Block.). – Idriss Riouak Jul 13 '20 at 08:08
  • 2
    I'm not sure what you mean; if an exception is thrown, the variable is uninitialized and cannot be accessed after the `catch` block. – daniu Jul 13 '20 at 08:13
  • 2
    Remember: the Java compiler can't know everything you know. It just follows general rules, which are kept simple in order that the language spec doesn't simply explode in complexity. Sometimes you just have to write things in ways the compiler can understand with its simple rules: in this case, just initialize with `null`. – Andy Turner Jul 13 '20 at 08:15
  • If `IOException` is thrown `path` will be unassigned but the method will continue after the catch block. – Amongalen Jul 13 '20 at 08:15
  • What I mean is that ( I think ) the compiler (can) have enough informations to know that the fist assignment is always executed expect if an unchecked exception is raised. – Idriss Riouak Jul 13 '20 at 08:16
  • @Amongalen, this can't happened because getPartent() or File() are not declared to `throw` anything. – Idriss Riouak Jul 13 '20 at 08:18
  • 2
    @IdrissRiouak you might think the compiler has enough information; but have you actually read [the rules the compiler uses](https://docs.oracle.com/javase/specs/jls/se14/html/jls-16.html)? Can you demonstrate that these rules are violated? – Andy Turner Jul 13 '20 at 08:20
  • @IdrissRiouak I highly doubt that compiler goes that deep analizying what can be thrown. Most likely it assumes that value has to be assigned in both try and catch block, or in finally. It probably assumes that exception can be thrown at start of try block. – Amongalen Jul 13 '20 at 08:21
  • @Amongalen indeed, [the rules say nothing about exception type](https://docs.oracle.com/javase/specs/jls/se14/html/jls-16.html#jls-16.2.15). – Andy Turner Jul 13 '20 at 08:22
  • (Additionally, you technically can't guarantee that an undeclared checked exception can't be thrown, because of that very horrible generics trick that can hide checked exceptions). – Andy Turner Jul 13 '20 at 08:24
  • Thank you @AndyTurner for the clarification and for the reference to the language specification. – Idriss Riouak Jul 13 '20 at 08:26
  • The problem really arises from the code not being structured correctly in the first place. The `if (path != null)` should be within the `try`-block. – daniu Jul 13 '20 at 08:27
  • @daniu yes that's the point, I'm developing a static analysis tool that detects unused assignment. This piece of code is taken from the ANTLR project. – Idriss Riouak Jul 13 '20 at 08:38

0 Answers0