Uninitialized variables and members in Java
Solution 1
The rules for definite assignment are quite difficult (read chapter 16 of JLS 3rd Ed). It's not practical to enforce definite assignment on fields. As it stands, it's even possible to observe final fields before they are initialised.
Solution 2
The language defines it this way.
Instance variables of object type default to being initialized to null. Local variables of object type are not initialized by default and it's a compile time error to access an undefined variable.
See section 4.12.5 for SE7 (same section still as of SE14) http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.5
Solution 3
Here's the deal. When you call
TestClass tc = new TestClass();
the new
command performs four important tasks:
- Allocates memory on the heap for the new object.
- Initiates the class fields to their default values (numerics to 0, boolean to
false
, objects tonull
). - Calls the constructor (which may re-initiate the fields, or may not).
- Returns a reference to the new object.
So your fields 'a' and 'b' are both initiated to null
, and 'a' is re-initiated in the constructor. This process is not relevant for method calling, so local variable 'c' is never initialized.
HTH
PS: for the gravely insomniac, read this.
Solution 4
The compiler can figure out that c will never be set. The b variable could be set by someone else after the constructor is called, but before doSomething(). Make b private and the compiler may be able to help.
Solution 5
The compiler can tell from the code for doSomething() that c is declared there and never initialized. Because it is local, there is no possibility that it is initialized elsewhere.
It can't tell when or where you are going to call doSomething(). b is a public member. It is entirely possible that you would initialize it in other code before calling the method.

Comments
-
Yuval Adam over 2 years
Consider this:
public class TestClass { private String a; private String b; public TestClass() { a = "initialized"; } public void doSomething() { String c; a.notify(); // This is fine b.notify(); // This is fine - but will end in an exception c.notify(); // "Local variable c may not have been initialised" } }
I don't get it. "b" is never initialized but will give the same run-time error as "c", which is a compile-time error. Why the difference between local variables and members?
Edit: making the members private was my initial intention, and the question still stands...