【问题标题】:Java Access Modifier and NullPointerExceptionJava 访问修饰符和 NullPointerException
【发布时间】:2013-02-15 03:24:07
【问题描述】:

我的 Java 代码出现运行时错误,我正在尝试了解其背后的原因。双星号之间的两个静态访问修饰符是有问题的项目。代码在有或没有这些修饰符的情况下编译(当然删除了星号)。但是在运行时,它只有在存在修饰符时才会运行而不会出错。为什么是这样?当静态修饰符不存在时在运行时生成的错误粘贴在代码下方。非常感谢您的帮助!

代码如下:

public class Blue {


    public int[][] multiArray(int x, int y){

        int[][] myArray = new int[x][y];
        return myArray;

    }

    static Blue blueObject = new Blue();

    public **static** int[][] one = blueObject.multiArray(3,3); 
    public **static** int[][] two = blueObject.multiArray(3,3);

    public static void main(String[] args){

        System.out.println("Hello world!");

    }

}

运行时产生的错误没有静态访问修饰符:

Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.NullPointerException
    at Blue.<init>(Blue.java:13)
    at Blue.<clinit>(Blue.java:11)

【问题讨论】:

标签: java nullpointerexception access-modifiers


【解决方案1】:

这个问题与 JVM 如何处理类加载以及你的类是如何定义的有关。 当你有 static int[][] 之一时,它可以工作,因为 JVM 读取/加载静态代码的顺序与它们在类中表示的顺序相同。因此,当 JVM 尝试初始化 int[][] 1 时,static 蓝色的 blueObject 就可以使用了。

但是,如果您将 int[][] 之一声明为 non-static,则当 JVM 尝试创建 static 蓝色 blueObject,它必须创建一个完全初始化的 Blue 对象并将其分配给 static blueobject,因此它尝试初始化 int[][];但此时,你的静态 blueObject.multiArray(3,3);还没准备好。

我希望这对你的问题有意义。

【讨论】:

  • 这很有意义。我只是想验证一下,实例变量在静态变量之前编译并不是。相反,这里的问题是,当我调用构造函数 Blue() 时,它试图初始化对象的实例变量,这些变量分配给对象本身提供的值。由于 blueObject 尚不存在,因此这是不可能的,从而产生了错误。我只是想用我自己的话重复你所说的话,以确保我正确理解它。非常感谢!
  • 是的,没错。我会在答案框中放一个示例代码来说明这一点。
【解决方案2】:

因为你将 blueObject 声明为静态,所以将定义更改为:

Test blueObject = new Test();

它会运行!

要么工作在“单例模式”(一切都是静态的),要么工作在“对象模式”(你创建一个对象并通过对象调用类方法)——你不能同时拥有。

【讨论】:

    【解决方案3】:

    @user1419674 通常 JVM会先初始化静态变量,然后再初始化实例变量。而且静态变量在第一次调用代码时只初始化一次。

    public class Test {
        public Test(){
            System.out.println("constructor of class Test");
        }
    }
    
    public class App {
        private Test test = new Test();
        private static int s_i;
        static {
            s_i = 1;
            System.out.println("initializing static field");
        }
    
        public static void main(String args[]) {
            App app1 = new App();
            App app2 = new App();
        }
    }
    

    上面的运行代码会打印出来:

    initializing static field
    constructor of class Test
    constructor of class Test
    

    但是,在您的代码中,静态变量的类型是 Blue 本身。它变得像 static Blue blueObject 的初始化依赖于 int[][] one 的初始化,这实际上需要 static Blue blueObject .

    【讨论】:

      猜你喜欢
      • 2013-12-01
      • 2013-05-25
      • 2017-08-17
      • 1970-01-01
      • 1970-01-01
      • 2015-11-26
      • 2011-10-15
      • 2014-11-03
      • 2016-01-29
      相关资源
      最近更新 更多