【问题标题】:Null pointer exception, "Attempt to read from field on a null object reference"空指针异常,“尝试从空对象引用上的字段读取”
【发布时间】:2015-11-24 01:29:52
【问题描述】:

我正在制作一个应用程序,用户在其中键入任务列表,并将该列表保存到数组中。数组中的每个任务都是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 数组应该是所有任务的数组,其中没有一个是空的,对吧?但是,当我运行该应用程序时,它无法启动活动,它说是由空指针异常引起的错误:

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

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

非常感谢!

编辑:赋值类的构造函数是:

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

【问题讨论】:

  • 您在作业中的“名称”变量为空。你能发布你正在使用的构造函数的代码吗?
  • 我添加了上面的代码

标签: java android arrays nullpointerexception


【解决方案1】:

null 引用就是 null。在您的代码中,它是tasks[i].name,您尝试在tasks[i] 上调用name,所以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 索引。

【讨论】:

  • 非常感谢!这个答案非常有帮助。我改变了我的 for 循环,使它只接受非空元素,现在它可以工作了!
【解决方案2】:

这是我的想法

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

假设只有第一个元素是null。所以realLength 将是7。后者for 循环从i=0 运行到i=7。当i=0tasks[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++;
  }
}

【讨论】:

    【解决方案3】:

    您可以将 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】:

      你的代码有问题:

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

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


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

      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】:

        您似乎正在尝试将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) 再次删除它们。

        【讨论】:

          【解决方案6】:

          似乎“任务”列表是空的。确保它被填充或进行空检查 喜欢:

          if(tasks[i] !=null) {
          
          full_tasks[i] = new Assignment(tasks[i].name, tasks[i].days_due,  tasks[i].time);
          
           }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-06-07
            • 1970-01-01
            • 1970-01-01
            • 2017-07-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-11-04
            相关资源
            最近更新 更多