我遇到了一个奇怪的NullPointerException实例,我运行以下代码,
Graph_img g = new Graph_img(3,4);
g.randomGraph();
其中构造函数和方法如下,
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]);
}
}
但是如果我运行初始化移动到方法而不是构造函数,
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]);
}
}
然后一切正常。我很困惑 - 为什么?谢谢 - 史蒂夫
答案 0 :(得分:3)
Node[][] Img = new Node[w][h];
在构造函数中,这会创建一个新的变量名Img
,对其进行初始化,然后立即完全忘记它。您定义的构造函数中的Img
会屏蔽您可能拥有的任何名为Img
的类成员。
如果您有一个名为Img
的成员,则应输入:
Img = new Node[w][h];
这会初始化您的班级成员Img
变量。
答案 1 :(得分:1)
这是在构造函数中声明的局部变量:
Node[][] Img = new Node[w][h];
隐藏名为Img
的任何成员变量:删除Node[][]
以访问成员变量Img
:
Img = new Node[w][h];
答案 2 :(得分:1)
Node[][] Img = new Node[w][h];
该2D数组中的所有引用都为null,直到您将它们设置为某些内容为止。声明变量和分配内存是必要的,但还不够。所有Java引用的默认值为null。您必须在代码中将它们设置为其他内容。
您在方法randomGraph()
中使用此值声明的值在范围内是本地的,并且在您离开方法时是GC。
如果您真的打算将其保留为成员变量,请将其更改为:
this.Img = new Node[w][h]; //<-- MOVED HERE
for(int x=0; x<w; x++)
如果你的代码使用本地变量,你编写它的方式,我建议你删除类成员。
另外,学习并遵循Sun Java编码标准。该变量名称应为img
,而不是Img
。
答案 3 :(得分:1)
Node[][] Img = new Node[w][h];
在构造函数中创建名为Img
的局部变量,而不是初始化名为Img
您可能正在寻找:
Img = new Node[w][h];
[假设Img
是一个字段]
作为旁注:通常在java中,惯例是变量以小写字母开头 - 它可以帮助其他程序员理解Img
是一个字段而不是一个类。您可能想要重命名Img
- &gt; img
,
答案 4 :(得分:1)
此:
Node[][] Img = new Node[w][h];
声明本地变量。如果要使用实例变量,则需要在构造函数外部声明变量,并在构造函数中赋值:
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
}
(为了便于阅读和符合Java命名约定,我调整了你的名字。)
如果您仍然在构造函数中声明变量,那么它仍然是本地变量,只是隐藏实例变量。