【问题标题】:Instantiation of Global fields [duplicate]全局字段的实例化[重复]
【发布时间】:2021-04-13 16:21:26
【问题描述】:

我写了一个检测图中循环的代码。

输入的形式可以是多行,每行格式为 a # b

表示从ab之间有一条边。

我的代码工作了,然后我玩了一下,遇到了 line a 和 line c 以及 line b 和 line d 的问题。

当我将 a 行和 c 行合并并将声明和实例化一起编写为 "ArrayList[]" arr=new ArrayList[99999] 时,类似地 b 行和 d 行,那么一切正常(假设我进行了适当的更改比如传递 arrvisited 作为 DFS 和 DFSvisit 之间的参数)。

但是如果我像下面写的那样写它,那么我会得到空指针异常。这是什么原因?

class Test {
    ArrayList<Integer>[] arr;                // line a
    boolean[] visited;                       // line b
    public static void main (String[] args) throws java.lang.Exception {
        Test obj=new Test();
        obj.DFS();
    }

    public void DFS() {
        arr=new ArrayList[99999];            // line c
        visited=new boolean[99999];          // line d
     
        for(int i=0;i<99999;i++) {              
            arr[i]=new ArrayList<>();    //instantiate each element of "array of Arraylists"
        }
    
        boolean[] flag=new boolean[99999];       //a flag array to identify which elements of array are valid elements
    
        Scanner sc=new Scanner(System.in);
    
        while(sc.hasNext()) {
            int a=sc.nextInt();       //take first number
            sc.next();                //throw away "#" token
            int b=sc.nextInt();       //take second number
            flag[a]=true;             //means arr[a] is valid
            arr[a].add(b);            //add b to adjaceny list of arr[a]
        }
    
    
        Test obj=new Test();
        for(int i=0;i<99999 ;i++) {
            if (flag[i]) {              //call DFSvisit only if arr[i] is valid
                obj.DFSvisit(i);
            }
        }
    
        System.out.println("Cycle does not exist");
    }

    void DFSvisit(int i) {              // basic DFS implementation
        visited[i] = true;
        for (int j=0;j<arr[i].size();) {
            if (visited[arr[i].get(j)]==true) {
                System.out.println("Cycle exists");
                System.exit(0);
            } else {
                DFSvisit(arr[i].get(j));
            }
        
            j++;
        }
        visited[i] = false;
    }
}

错误:

Exception in thread "main" java.lang.NullPointerException
at test.Test.DFSvisit(Test.java:59)
at test.Test.DFS(Test.java:49)
at test.Test.main(Test.java:18)

附:我知道如果我在初始化之前尝试使用引用变量,那么我会得到空指针异常。但是在这里我无法看到发生这种情况的任何地方。我已将 arrvisited 声明为类的成员(在每个方法之外)。然后我在从 ma​​in 方法转移到 DFS 方法后初始化它们。在这两者之间,我没有尝试使用 arrvisited,但我还是得到了 NPE。这是为什么呢?

【问题讨论】:

  • java 中没有全局变量。 arr 是一个字段。
  • @Michael:arr 是一个数组列表的数组......出于某种原因。所以new Arraylist[99999] 在某种意义上是“正确的”。
  • @JoachimSauer 啊哈,谢谢
  • @Michael,您给出的答案是在初始化之前我们无法访问引用变量内部的内容。我知道。但是在我的问题中,在初始化它们之前,我没有在哪里使用过 arr 或访问过的变量。所以我无法理解我哪里出错了。我知道我遗漏了一些东西,但我认为这比您链接中解决的问题更难发现。

标签: java instantiation


【解决方案1】:

你只是混淆了两个对象。

class Test {
    ArrayList<Integer>[] arr;
    boolean[] visited;
    public static void main (String[] args) throws java.lang.Exception {
        Test obj=new Test(); // here you create the first object. arr is null here
        obj.DFS();
    }

    public void DFS() {
        arr=new ArrayList[99999];
        visited=new boolean[99999]; // here you initialize the fields of the first instance of the object
...
        Test obj=new Test(); // here you create the second instance of the object. arr is null
        for(int i=0;i<99999 ;i++) {
            if (flag[i]) {
                obj.DFSvisit(i); // here you call the method of the second object where arr is null. NPE
            }
        }

如果你合并这些行,那么字段初始化将在对象构造期间发生。这就是那里没有 NPE 的原因。

【讨论】:

  • 谢谢。所以我通过不同的对象 obj 调用 DFSvisit。此 obj 指向具有 arr 并以 NULL 访问的对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-24
  • 2020-01-15
  • 2022-06-21
  • 2010-12-05
  • 1970-01-01
  • 1970-01-01
  • 2015-05-03
相关资源
最近更新 更多