Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Null pointer exception, "Attempt to read from field on a null object reference"

I am making an app in which the user types in a list of tasks, and that list is saved to an array. Each task in the array is an instance of the Assignment class. However, I realized that in java it is not possible to add an element to an array after the array is created. So, what I did was I created an array called tasks which consisted of many null values: Assignment[]tasks = {null, null, null, null, null, null, null, null, null, null, null, null};. When I want to add a task to the array, I just replace the next null value with the object. However, I also need to have an array of just the tasks, with no null values. So I created an array called full_tasks for all of the elements that aren't null:

for (Assignment task: tasks) {
    if (task != null) {
        realLength += 1;
    }
}

Assignment[] full_tasks = new Assignment[realLength];

for (int i=0; i <= full_tasks.length - 1; i++) {
        full_tasks[i] = new Assignment(tasks[i].name, tasks[i].days_due, tasks[i].time);
}

So now, the full_tasks array should be an array of all the tasks, none of which are null, right? However, when I run the app, it can't launch the activity, an error it says is caused by a null pointer exception:

 Caused by: java.lang.NullPointerException: Attempt to read from field 'java.lang.String com.example.lb.homeworkappv11.Assignment.name' on a null object reference
        at com.example.lb.homeworkappv11.Schedule.sortTasks(Schedule.java:64)

The line that the error points to is:

full_tasks[i] = new Assignment(tasks[i].name, tasks[i].days_due, tasks[i].time);

I'm still not totally sure what a null object reference is, but I think it means that one of the elements in the full_tasks array is null. Would that be correct? And if it is, what can I do to make sure that the full_tasks array is only the non-null elements in the tasks array?

Thank you so much!

Edit: the constructor function for the assignment class is:

public Assignment(String name, int days, int time) {
    this.name = name;
    this.days_due = days;
    this.time = time;
    this.toSortBy = "nothing";
}
like image 585
Lucas B Avatar asked Aug 29 '15 14:08

Lucas B


2 Answers

A null reference is just that null. In your code it is tasks[i].name where you try to call name on tasks[i] so tasks[i] is null.

There is one scenario I can think of, where your code would definitely throw a NullPointerException. So, I will assume your tasks array can look looks like this:

tasks = [task0, null, task2, task3, null, task5]

Then full_tasks will have a size of 4 but

for (int i=0; i <= full_tasks.length - 1; i++) {
        full_tasks[i] = new Assignment(tasks[i].name, tasks[i].days_due, tasks[i].time);
}

will throw a NPE as soon as i == 1 because tasks[1] is null.

So, if you want to fill full_tasks with only non-null tasks make sure you got the right indexes of tasks.

like image 71
Sascha Kolberg Avatar answered Nov 12 '22 16:11

Sascha Kolberg


Here's what I think

You are just finding the number elements that are not null. You don't know where in the array thest null's are present.

Suppose ONLY the first element is null. So realLength will be 7. The latter for loop runs from i=0 to i=7. When i=0, tasks[i].name tries to access the name field of the first element; but your first element happens to be null`. That's where things go wrong.

Solution:

There are a number of solutions. The most efficient one I can think of uses an ArrayList.

To get around using arrays, you should store the indices of all elements that are not null. That's one way.

Here's another:

for (Assignment task: tasks) {
  if (task != null) {
    realLength += 1;
  }
}
Assignment[] full_tasks = new Assignment[realLength];
int count = 0;
for (Assignment task: tasks) {
  if (task != null) {
    full_tasks[count] = new Assignment(task.name, tasks.days_due, task.time);
    count++;
  }
}
like image 33
Wololo Avatar answered Nov 12 '22 18:11

Wololo