Java NullPointerException在构造函数中初始化的2D数组,但方法拒绝确认

时间:2012-03-25 11:41:53

标签: java

我遇到了一个奇怪的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]);
        }
}

然后一切正常。我很困惑 - 为什么?谢谢 - 史蒂夫

5 个答案:

答案 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命名约定,我调整了你的名字。)

如果您仍然在构造函数中声明变量,那么它仍然是本地变量,只是隐藏实例变量。