views:

1174

answers:

6

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

+3  A: 

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.

No, even if it is private the compiler does not give an error (not mine, anyway).
Dave Costa
Reducing visibility does not change the situation...
Yuval A
+2  A: 

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.

Dave Costa
Same here - making it private does not matter
Yuval A
+14  A: 

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.5.5 in here http://java.sun.com/docs/books/jls/second_edition/html/typesValues.doc.html#96595

John Burton
+3  A: 

Members are automatically set to default values, whereas local variables are not. They must be set explicitly. Check here

Robin
Uninitialised members which are not primitives are null, and as such you will get a null pointer exception.
Yuval A
+5  A: 

Here's the deal. When you call

TestClass tc = new TestClass();

the new command performs four important tasks:

  1. Allocates memory on the heap for the new object.
  2. Initiates the class fields to their default values (numerics to 0, boolean to false, objects to null).
  3. Calls the constructor (which may re-initiate the fields, or may not).
  4. Returns a pointer 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.

Hope this helps,

Yuval =8-)

PS: for the gravely insomniac, read this.

Yuval
+5  A: 

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.

Tom Hawtin - tackline