Reputation: 11
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
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
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
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
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
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