sksw
sksw

Reputation: 11

Java NullPointerException 2D array initialized in constructor, but method refuses to acknowledge

I've run into a strange instance of NullPointerExceptionwhere I run the following code,

Graph_img g = new Graph_img(3,4);
g.randomGraph();

where the constructor and method are the following,

public Graph_img(int width, int height){
    super();
    w = width;
    h = height;
    Node[][] Img = new Node[w][h];
}

//generate new MRF graph ~75% 0 bilevel
public void randomGraph(){
    V = new ArrayList<Node>(0);
    E = new ArrayList<Edge>(0);
    for(int x=0; x<w; x++)
        for(int y=0; y<h; y++){
            if(Math.random()>0.75)
                Img[x][y] = new Node(x*h+y,1,2); //<--- NullPointerException
            else
                Img[x][y] = new Node(x*h+y,0,2); //<--- NullPointerException
            V.add(Img[x][y]);
        }
}

But if I run with the initialization moved to the method instead of the constructor,

public Graph_img(int width, int height){
    super();
    w = width;
    h = height;
    //Node[][] Img = new Node[w][h]; <-- MOVING THIS
}

//generate new MRF graph ~75% 0 bilevel
public void randomGraph(){
    V = new ArrayList<Node>(0);
    E = new ArrayList<Edge>(0);
    Node[][] Img = new Node[w][h]; //<-- MOVED HERE
    for(int x=0; x<w; x++)
        for(int y=0; y<h; y++){
            if(Math.random()>0.75)
                Img[x][y] = new Node(x*h+y,1,2);
            else
                Img[x][y] = new Node(x*h+y,0,2);
            V.add(Img[x][y]);
        }
}

Then everything works. I am perplexed - why? Thanks - Steve

Upvotes: 1

Views: 1290

Answers (5)

Jon Skeet
Jon Skeet

Reputation: 1500515

This:

Node[][] Img = new Node[w][h];

declares a local variable. If you want to use an instance variable, you'll need to declare the variable outside the constructor, and just assign it in the constructor:

class GraphImage
{
    private final Node[][] nodes;

        private final int width; private final int height;

    public GraphImage(int width, int height)
    {
        this.width = width;
        this.height = height;
        nodes = new Node[width][height];
    }

    // Other methods
}

(I've adjusted your names for readability and conformity with Java naming conventions.)

If you still declare the variable in the constructor, that will still be a local variable which just hides the instance variable.

Upvotes: 1

Mat
Mat

Reputation: 206689

Node[][] Img = new Node[w][h];

In the constructor, this creates a new variable names Img, initializes it, and then promptly and completely forgets about it. Img in the constructor as you've defined it masks any class member called Img you might have.

If you have a member called Img, you should have typed:

Img = new Node[w][h];

This will initialize your class member Img variable.

Upvotes: 3

amit
amit

Reputation: 178451

Node[][] Img = new Node[w][h];

Is creating a local variable named Img in the constructor, and not initializing a field named Img

You are probably looking for:

Img = new Node[w][h];

[assuming Img is a field]

As a side note: Usually in java, the convention is that variables are starting with lower case letter - it helps fellow programmers understand that Img is a field and not a class instantly. You might want to rename Img -> img,

Upvotes: 1

duffymo
duffymo

Reputation: 308763

Node[][] Img = new Node[w][h];

All the references in that 2D array are null until you set them to something. Declaring the variable and allocating memory are necessary, but not sufficient. The default value for all Java references is null. You have to set them to something else in your code.

The value you declare with this in your method randomGraph() is local in scope and is GC'd when you leave the method.

Change it to this if you really intend to keep it as a member variable:

this.Img = new Node[w][h]; //<-- MOVED HERE
for(int x=0; x<w; x++) 

If you code works with the local variable, the way you've written it, I'd recommend that you remove the class member.

Also, learn and follow the Sun Java coding standards. That variable name should be img, not Img.

Upvotes: 1

hmjd
hmjd

Reputation: 121971

This is a local variable declared in the constructor:

Node[][] Img = new Node[w][h];

hiding any member variable named Img: remove the Node[][] to access the member variable Img:

Img = new Node[w][h];

Upvotes: 1

Related Questions