James Ko
James Ko

Reputation: 34569

Using 'this' in constructors without throwing a NullPointerException

I want to create a class Bar such that every time I instantiate a Bar, it is added to an ArrayList<Bar> of an object Foo. This is what I have tried:

class Foo {
    private ArrayList<Bar> bars;
    .
    .
    .
    public ArrayList<Bar> getBars() { return bars; }
}

//in class Bar
class Bar {
    public Bar(Foo f) {
        f.getBars().add(this); //NullPointerException!
    }
}

I realize what is happening here (the constructor is not finished, so this returns null), but how can I avoid this?

Upvotes: 0

Views: 998

Answers (2)

Stephen C
Stephen C

Reputation: 719229

I realize what is happening here (the constructor is not finished, so this returns null), but how can I avoid this?

Your diagnosis is incorrect.

The value of this can never be null. And that includes in a constructor.

The JLS (15.8.3) states the following:

"The keyword this may be used only in the body of an instance method or default method, or in the body of a constructor of a class, or in an instance initializer of a class, or in the initializer of an instance variable of a class. If it appears anywhere else, a compile-time error occurs."

"When used as a primary expression, the keyword this denotes a value that is a reference to the object for which the instance method or default method was invoked (§15.12), or to the object being constructed."

As you can see:

  1. the this keyword can only appear in a context in where there is a current object, and

  2. the value of this (when used as an expression) is always the reference to the current object; there is no mention of any case where it could be null.

(See also: Can "this" ever be null in Java?)


The object that this refers to is not fully initialized at that point, but that isn't the cause of the exception you are seeing. The cause of the NPE is something else.

Specifically, if an NPE is being thrown at that line, then either f is null or f.getBars() is returning null. And looking at how you have coded the Foo class, the latter is definitely plausible. (You don't initialize the bars member ... so it will be null.)

Upvotes: 2

Dyrborg
Dyrborg

Reputation: 877

Because bars is not initialized, whenever you call f.getBars() it returns a null object. When you try to call .add() on a null object, you get a NullPointerException.

Change

private ArrayList<Bar> bars;

to

private ArrayList<Bar> bars = new ArrayList<Bar>();

or add

public Foo(){this.bars = new ArrayList<Bar>();}

to your Foo class.

Upvotes: 0

Related Questions