2

How do I tell Java that I don't need to initialize a to have a working program and to not give me an error?

int a;
boolean b = true;
while (true) {
   if (b == false) {
       System.out.print(a);
       break;
   } else {
       b = false;
       a = 5;
   }
}

And if I can't, is there a reason why this is the way the compiler was designed?

Was it easy to design such a compiler or is this a mechanism to ensure that I restructure my code?

This is not the same question as this one

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
rahs
  • 1,759
  • 2
  • 15
  • 31
  • 6
    Yes. Compilers are not sentient. `int a;` does not assign a default value to `a`, and the compiler only sees you printing `a` in that loop. It can't determine that `a` will always be assigned before then. `int a = 0;` and all your problems go away. – Elliott Frisch Sep 29 '18 at 01:52
  • Are you asking why this compiler error exists at all? Or why the control flow analyzer doesn't take variable states into account when determining whether a variable was definitely assigned? Note that your question is a trivial example, but you could easily write a version that couldn't be so easily proven. For example, imagine a loop that finds the two primes that sum to a given even integer -- to prove whether the variable was definitely assigned or not, the compiler would have to prove Goldbach's conjecture! – Daniel Pryden Sep 29 '18 at 01:59
  • 2
    The linked duplicate is not exactly the same question (it's actually an even more trivial case), but the answers show why this behavior is required by the spec. – Daniel Pryden Sep 29 '18 at 02:07
  • Actually Daniel, they don't. They show that the behavior >>is<< required by the spec, but not >>why<< the specification requires it. This is a singularly inappropriate "dup" choice, and I haven't yet found a good one. – Stephen C Sep 29 '18 at 02:45
  • @StephenC [Here's](https://stackoverflow.com/questions/47589869/compiler-says-variable-might-not-have-been-initialized-although-i-have-a-flag) one I like. – Sotirios Delimanolis Sep 29 '18 at 03:10
  • @SotiriosDelimanolis - Yea, maybe. :-) But I actually like this question for its "directness". – Stephen C Sep 29 '18 at 03:17

1 Answers1

10

Is 'error: variable a might not have been initialized' really necessary in this if construct?

Yes it is necessary. The Java language specification requires it. This is covered in JLS 16 - Definite Assignment.

"Each local variable (§14.4) and every blank final field (§4.12.4, §8.3.1.2) must have a definitely assigned value when any access of its value occurs."


How do I tell Java that I don't need to initialize a to have a working program and to not give me an error?

You can't tell Java that. You need to initialize the variable ... or restructure the code.


And if I can't, is there a reason why this is the way the compiler was designed?

Because the Java compiler must implement the specification, otherwise it is not a proper Java compiler. The specification says that is an error.

The real question is why the specification says that. The answer is so that compiler writers are not forced to included difficult theorem proving code in all Java compilers.

  • In the example you give, it is obvious to a programmer that the variable will always be initialized. However, a compiler needs to verify it. It needs to be absolutely sure, since an uninitialized variable would have undefined behavior.

  • Automated (undirected) verification is a complicated task. Complicated means more (compiler) code to write, more (compiler) bugs, etcetera.

  • The "state of the art" in this technology is not up to doing this kind of analysis for complicated Java code.

  • There are (theoretical) cases where verification that a variable is initialized is mathematically impossible.

So ... wisely ... the people who specified the Java language pushed this back to the programmer. You need to write your code so that variables are definitely assigned before use, according to the rules set out in the JLS.

And there is a second reason too. Suppose that the JLS did allow a Java compiler to accept

   System.out.print(a);

if and only if it could satisfy itself that a was (always) previously initialized. Now consider two Java compilers written by different people (or the same people at different times) to implement the same version of the JLS.

  • Compiler C1 can figure out that a is always initialized, and says that the program is valid.

  • Compiler C2 cannot figure out that a is always initialized, and says that the program is invalid.

We now have two Java compilers that ostensibly implement the same version of the JLS, but disagree on whether your example program (above) is valid. That is simply untenable.


To complicate things further, I suspect that something similar to the "definite assignment" checking must also occur when the JVM verifies bytecodes that have just been loaded. Thus a change to the JLS definite assignment rules would ripple on to the JVMS, and potentially affect the behavior of the JVM platform for other programming languages and tools that compile / generate directly to JVM bytecodes.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Thanks! Were you previously aware of this condition: "Each local variable (§14.4) and every blank final field (§4.12.4, §8.3.1.2) must have a definitely assigned value when any access of its value occurs."? How do you go about searching the JLS for a question like this? – rahs Sep 29 '18 at 03:51
  • 1
    1) I was. I didn't need to search. I knew where to look. 2) You can download the PDF version and search it. How do you search for answers like this? By knowing the appropriate terms to search for. Also, by getting to understand the structure of the JLS. Basically, you **study** it. Hard work. But if you want real answers you need to do the work. – Stephen C Sep 29 '18 at 04:25