空指针异常,“尝试从空对象引用上的字段读取”

时间:2015-08-29 14:25:09

标签: java android arrays nullpointerexception

我正在创建一个应用程序,用户在其中键入任务列表,并将该列表保存到数组中。数组中的每个任务都是Assignment类的实例。但是,我意识到在java中,在创建数组之后无法向数组添加元素。所以,我做的是创建了一个名为tasks的数组,它由许多空值组成:Assignment[]tasks = {null, null, null, null, null, null, null, null, null, null, null, null};。当我想向数组添加任务时,我只需用对象替换下一个空值。但是,我还需要一个只有任务的数组,没有空值。所以我为所有非空元素创建了一个名为full_tasks的数组:

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

现在,full_tasks数组应该是所有任务的数组,其中没有一个是null,对吧?但是,当我运行应用程序时,它无法启动活动,它说的错误是由空指针异常引起的:

 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)

错误指向的行是:

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

我仍然不完全确定null对象引用是什么,但我认为这意味着full_tasks数组中的一个元素为null。这是对的吗?如果是,我该怎么做才能确保full_tasks数组 tasks数组中的非空元素?

非常感谢你!

编辑:作业类的构造函数是:

public Assignment(String name, int days, int time) {
    this.name = name;
    this.days_due = days;
    this.time = time;
    this.toSortBy = "nothing";
}

6 个答案:

答案 0 :(得分:2)

null引用只是null。在您的代码中tasks[i].name,您尝试在name上致电tasks[i],因此tasks[i]null

我可以想到一个场景,你的代码肯定会抛出NullPointerException。 所以,我假设你的任务数组看起来像这样:

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

然后full_tasks的大小为4,但

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

会在i == 1后立即抛出 NPE ,因为tasks[1]null

因此,如果您希望仅使用非空任务填充full_tasks,请确保获得tasks的正确索引。

答案 1 :(得分:1)

这就是我的想法

您只是找到不是null的数字元素。你不知道null中存在的数组在哪里。

假设只有第一个元素是null。因此realLength将为7.后一个for循环从i=0运行到i=7。当i=0时,tasks[i].name尝试访问第一个元素的name字段;但你的第一个元素恰好是null。出现问题的地方。

<强>解决方案:

有许多解决方案。我能想到的最有效的方法是使用ArrayList

要使用数组,您应该存储非null的所有元素的索引。这是单向的。

这是另一个:

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

答案 2 :(得分:0)

似乎&#34;任务&#34;列表是空的。确保它已填充或进行空检查 喜欢:

if(tasks[i] !=null) {

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

 }

答案 3 :(得分:0)

您可以认为null不存在,例如当您尝试获取task.name,其中任务 null 时,您会收到错误,因为您尝试从某些人那里获取名称甚至不存在的东西。

实际上你的代码现在正在做的是检查原始数组中有多少非空项,并尝试将数组中的前n项额外提取到新数组。

即。如果列表为{null, null, non-null, non-null},则它有2个非空项,但是您的代码错误地提取前{2}项的列表{null, null}

编辑,实际执行您想要的操作:

ArrayList<Assignment> fullTaskList = new ArrayList<Assignment>();
for (Assignment task: tasks) {
    if (task != null) {
        fullTaskList.add(task);
    }
}
//optional
Assignment[] fullTasks = fullTaskList.toArray(new Assignment[fullTaskList.size()]);

答案 4 :(得分:0)

您的代码中存在问题:

(tasks[i].name, tasks[i].days_due, tasks[i].time).

虽然您正在计算实际大小,但两者之间可能存在一些空值,导致它从列表任务[i]中获取空对象。

解决此问题的一个好主意是使用List而不是Array。可以根据需要增加或减少列表,只需添加或删除对象类型的项目即可。例如:

List<Assignment> list = new ArrayList<>();
Assignment assignment1 = new Assignment(etc.);
list.add(assignment1);
list.get(0) //-> returns the Assignment object that you added.

然后,您可以使用list.size()来获取大小,以了解有多少项目,或删除最后一项。您可以毫无问题地将新项目添加到列表中。

答案 5 :(得分:0)

您似乎正在尝试将tasks数组复制并压缩到full_tasks数组中(删除空元素),但由于您正在访问tasks[i],因此这部分不正确在第二个循环中,不检查它是否为空。

而不是:

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

你可以这样写:

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

但是再次解决原始问题,关于无法向数组中添加任何元素的事实,我建议使用ArrayList而不是简单的数组。这样您就可以使用ArrayList.add(assignment)添加项目,然后使用ArrayList.remove(index)重新删除它们。