3

我的代码是这样的:

public class Foo {
    public int a;
    Bar[] bar = new Bar[10];

    a = bar[0].baz;
}

public class Bar {
    public int b;

    public Bar () { //I tried doing away with this constructor, but that didn't
                    //fix anything
        b = 0;
    }

    public int Baz () {
        //do somthing
    }
}

我收到类似于以下内容的错误消息:

Exception in thread "Foo" java.lang.NullPointerException

在 Foo 中的任何一行,我都尝试调用 Bar 类的任何函数或值。如何防止 bar[] 为空?

编辑:经过一番摆弄,我终于把它修好了,谢谢大家!但是,我无法调用构造函数来解决问题;我必须创建另一个函数并从 Main 调用该函数(在我的情况下,类 Foo 实际上是类 Main,如果这真的很重要的话)。我的最终结果:

public class Foo {
    public int a;
    Bar[] bar = new Bar[10];

    public Foo () { //this constructor wasn't called for some reason... I checked this
                    //by using System.out.println... no message was print onscreen
        for (int a = 0; a < bar.length; a++)
            bar[a] = new Bar();
    }

    public static void initializeFoo () {
        for (int a = 0; a < bar.length; a++)
            bar[a] = new Bar();
    }

    public static void Foo () {
        initializeFoo();
        a = bar[0].baz;
    }
}

有人想帮我解决这个问题,还是我应该提出另一个问题?:)

4

8 回答 8

8
Bar[] bar = new Bar[10];

a = bar[0].baz;

上面创建了一个 Bar 类型的数组,但没有用任何实际的 Bar 对象填充它。引用类型的数组使用空引用进行初始化。你需要这样做:

for(int i=0; i<bar.length; i++) {
    bar[i] = new Bar();
}
于 2010-01-24T16:12:21.530 回答
6

您已通过编写此代码为引用分配内存,Bar[] bar = new Bar[10];但谁将为数组元素分配内存?引用类型的 Infact 数组使用空引用进行初始化。

您还需要为数组元素分配内存:

for(int i=0; i<bar.length; ++i)
   bar[i]=new Bar();
于 2010-01-24T16:13:42.070 回答
3

您收到 NullPointerException 的原因是因为这一行:

a = bar[0].baz;

bar[0]尚不存在。

发生的事情是,当 aFoo被初始化时,它的默认初始化程序运行(如上面提到的行)。您构造barBar引用数组,但不初始化数组中的各个位置。如果您希望它们全部被初始化,则需要执行以下操作:

public Foo() {
    bar = new Bar[10];
    for (int i = 0; i < 10; i++) {
      bar[i] = new Bar();
    }
    a = bar[0].baz;
}
于 2010-01-24T16:10:40.360 回答
1

尝试这个:

public class Foo 
{
    public int a;
    Bar[] bar = new Bar[10];

    public Foo()
    {
        for (int i = 0; i < 10; ++i)
        {
            this.bar[i] = new Bar();
        }
    }
    a = bar[0].baz();
}

public class Bar 
{
    public int b;


    public int baz() 
    {
        return b;
    }
}
于 2010-01-24T16:11:41.887 回答
1

之后Bar[] bar = new Bar[10],您的条形数组将使用空值初始化。因此bar[0]containsnull和调用bar[0].baz会导致NullPointerException.

您需要使用类似的语句填充数组bar[0] = new Bar()。或者

for (int i = 0; i < bar.length; i++) {
    bar[i] = new Bar();
}
于 2010-01-24T16:15:47.680 回答
1

这里的关键问题是对Java 中数组初始化的误解。bar[] 的初始化将是“10 个为空的 Bar 引用”。

这是一个更正的示例(它不使用 10),尽管由于其他原因(例如公共成员)它不是很好的 Java 风格:

class Foo {
    Bar[] bar = new Bar[] { new Bar(), new Bar() };
    public int a = bar[0].b;
}

public class Bar {
    public int b = 0;

    public static void main(String... args) {
        Foo foo = new Foo();
        System.out.println(foo.a);
    }
}

这个例子更接近于 Java 的真正风格:

class Foo {
    static final int numBars = 10;
    private Bar2[] bar = new Bar2[numBars];
    private int a;

    public int getA() { return a; }

    public Foo() {
        for (int i = 0; i < numBars; i++) {
            bar[i] = new Bar2(); 
        } 
        a = bar[0].getB();
    }
}

public class Bar2 {
    private int b = 0;
    public int getB() { return b; }

    public static void main(String... args) {
        Foo foo = new Foo();
        System.out.println(foo.getA());
    }
}
于 2010-01-24T16:24:36.680 回答
1

许多正确的答案可供参考。我认为您可能遇到的一些问题:

  • Foo 的构造函数将是 Foo() { /* ... */ } 而不仅仅是将代码放在类中的任何位置。
  • 您可以使用 java.util.Arrays.fill(Object[] a, Object val) 而不是自己使用循环

像这样:

public class Foo {
    public int a;
    Bar[] bar = new Bar[10];

    Foo() {
        java.util.Arrays.fill(bar, new Bar());
        a = bar[0].baz();
    }
}

编辑:对于您更新的问题,只需从您的 main(...) 方法调用 new Foo() 。此外,您不能像您一样拥有静态构造函数。

于 2010-01-24T16:58:50.767 回答
1

对您的代码的一些答案和评论:

构造函数不会自己调用,您可以使用语句主动调用它new Foo()

您的initializeFoo()方法无法编译。该方法是静态的,无法访问非静态类成员(如bar您的情况)。

最后,public static void Foo()不是构造函数,而是方法。构造函数没有返回类型(void在您的情况下)。

于 2010-01-24T19:21:01.770 回答