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?
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.