0

I wrote a code for detecting cycle in graph.

The input is given such that there can be several lines with each line of form a # b .

It denotes that there is an edge from a to b.

My code worked and then I played with it a bit and came across a problem with line a and line c and with line b and line d.

When I combine line a and line c and write the declaration and instantiation together as "ArrayList[]" arr=new ArrayList[99999] , similarly line b and line d,then everything is working fine(Assuming I make appropriate changes like passing arr and visited as arguments between DFS and DFSvisit).

But If I write it as I have written below then I am getting Null pointer exception. What is the reason for this?

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;
    }
}

Error:

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)

P.S. I know that If I try to use reference variable before it is initialised then I will get Null Pointer Exception. But here I am not able to see anywhere where that is happening. I have declared arr and visited as a member of class(outside every method). I am then initialising them after moving from main method to DFS method. In between I haven't tried to use either arr or visited but I am getting NPE anyway. Why is that?

Ayush
  • 41
  • 5
  • No such thing as globals in java. `arr` is a field. – Michael Apr 13 '21 at 16:25
  • @Michael: `arr` is an array of arraylists ... for some reason. So `new Arraylist[99999]` is "correct" in some sense. – Joachim Sauer Apr 13 '21 at 16:26
  • @JoachimSauer Aha, thanks – Michael Apr 13 '21 at 16:27
  • Does this answer your question? [NullPointerException when Creating an Array of objects](https://stackoverflow.com/questions/1922677/nullpointerexception-when-creating-an-array-of-objects) – OH GOD SPIDERS Apr 13 '21 at 16:36
  • @Michael, the link you have given answers that we cant access what is inside the reference variable before initialising it. I know that. But in my question, I have no where used arr or visited variables before initializing them. So I am not able to understand where I am getting wrong. I know I am missing something but I think it is little hard to spot than the issue addressed in your link. – Ayush Apr 13 '21 at 18:11
  • @Progman, no. It is the same question's link given by Micahel. – Ayush Apr 13 '21 at 18:17

1 Answers1

1

You just got confused between two objects.

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
            }
        }

If you combine the lines, then the field initialization will happen during the object construction. That's why no NPE there.

Morse
  • 1,330
  • 2
  • 17
  • 27
  • thanks. So I am calling DFSvisit via different object obj. This obj is pointing to the object which has arr and visited as NULL. – Ayush Apr 14 '21 at 05:58