简体   繁体   English

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

[英]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.数组中的每个任务都是Assignment类的一个实例。 However, I realized that in java it is not possible to add an element to an array after the array is created.但是,我意识到在 java 中不可能在创建数组后向数组添加元素。 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};所以,我所做的是创建一个名为tasks的数组,其中包含许多空值: 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:所以我为所有不为空的元素创建了一个名为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);
}

So now, the full_tasks array should be an array of all the tasks, none of which are null, right?所以现在, full_tasks数组应该是所有任务的数组,没有一个是空的,对吧? 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.我仍然不完全确定空对象引用是什么,但我认为这意味着full_tasks数组中的一个元素为空。 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?如果是,我该怎么做才能确保full_tasks数组只是tasks数组中的非空元素?

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

A null reference is just that null . null引用就是null In your code it is tasks[i].name where you try to call name on tasks[i] so tasks[i] is null .在您的代码中,您尝试在tasks[i].name上调用name的地方是tasks[i] ,因此tasks[i]null

There is one scenario I can think of, where your code would definitely throw a NullPointerException .我能想到一种情况,您的代码肯定会抛出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然后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);
}

will throw a NPE as soon as i == 1 because tasks[1] is null .一旦i == 1就会抛出NPE ,因为tasks[1]null

So, if you want to fill full_tasks with only non-null tasks make sure you got the right indexes of tasks .因此,如果您只想用非空任务填充full_tasks ,请确保您获得了正确的tasks索引。

Here's what I think这是我的想法

You are just finding the number elements that are not null .您只是在查找不为null的数字元素。 You don't know where in the array thest null 's are present.您不知道数组中的哪个位置存在null

Suppose ONLY the first element is null .假设只有第一个元素是null So realLength will be 7. The latter for loop runs from i=0 to i=7 .所以realLength将为 7。后者for循环从i=0运行到i=7 When i=0 , tasks[i].name tries to access the name field of the first element;i=0时, tasks[i].name尝试访问第一个元素的name字段; but your first element happens to be null`.但是你的第一个元素恰好是 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 .我能想到的最有效的方法是使用ArrayList

To get around using arrays, you should store the indices of all elements that are not null .要避免使用数组,您应该存储所有不为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++;
  }
}

Seems like "tasks" list is empty.似乎“任务”列表是空的。 Make sure its get populated or put a null check like:确保它被填充或进行空检查,例如:

if(tasks[i] !=null) {

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

 }

You can think of null as something not exists, for example when you try to get task.name , where task is null , you get error, because you try to get name from some something which does not even exists.您可以将 null 视为不存在的东西,例如,当您尝试获取task.name时,其中 task 为null ,您会收到错误,因为您试图从一些甚至不存在的东西中获取名称。

Actually what your code is doing now is check how many non-null items in the original array, and try to extract the extra the first n items from the array to a new array.实际上你的代码现在正在做的是检查原始数组中有多少非空项,并尝试从数组中提取额外的前 n 项到一个新数组中。

ie if the list is {null, null, non-null, non-null} , it has 2 non-null item, however your code wrongly extracts the list of the first 2 items which are {null, null}即如果列表是{null, null, non-null, non-null} ,它有 2 个非空项目,但是您的代码错误地提取了前 2 个项目的列表,它们是{null, null}

Edit, to actually do what you want:编辑,实际做你想做的事:

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

The problem in your code is here:您的代码中的问题在这里:

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

Although you're counting the real size, there could be some null value in between that is causing it to be get a null object from the list tasks[i].尽管您计算的是实际大小,但两者之间可能存在一些空值,导致它从列表任务 [i] 中获取空对象。


A good idea to solve this is by using a List instead of an Array.解决这个问题的一个好主意是使用列表而不是数组。 A List can be increased or decreased as you want, you just have to add or remove an item of your object type.列表可以根据需要增加或减少,您只需添加或删除您的对象类型的项目。 For example:例如:

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

Then you can use list.size() to get the size to know how many items are there, or to remove the last item.然后您可以使用list.size()来获取大小以了解那里有多少项,或者删除最后一项。 And you would have no problems to add new items to the list.而且您可以毫无问题地将新项目添加到列表中。

It seems you are trying to copy and compact the tasks array into the full_tasks array (removing the null elements), but you are doing this partially incorrect since you are accessing tasks[i] in the second loop without checking whether its is null.似乎您正在尝试将tasks数组复制并压缩到full_tasks数组中(删除空元素),但是您这样做部分不正确,因为您在第二个循环中访问tasks[i]而没有检查它是否为空。

Instead of:代替:

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

you could write something like this:你可以这样写:

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

But then again to solve your original problem, regarding the fact that you cannot add any elements to an array, I suggest to use anArrayList instead of a simple array.但是为了解决你原来的问题,关于你不能向数组添加任何元素的事实,我建议使用ArrayList而不是简单的数组。 This allows you to add items with ArrayList.add(assignment) and remove them again with ArrayList.remove(index) .这允许您使用ArrayList.add(assignment)添加项目并使用ArrayList.remove(index)再次删除它们。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 尝试从空对象引用中读取字段“ GlyphRun.color” - Attempt to read from field 'GlyphRun.color' on a null object reference 尝试从 AndroidDevMetrics 中的字段读取空对象引用 - Attempt to read from field in AndroidDevMetrics on a null object reference 哪个引用变量为null-尝试从null对象引用上的字段&#39;android.os.Handler android.support.v4.ama&#39;中读取 - which reference variable is null - Attempt to read from field 'android.os.Handler android.support.v4.a.m.a' on a null object reference 尝试在空指针对象上调用异常 - Attempt to invoke an exception on a null pointer object NullPointerException:尝试从空对象引用上的字段&#39;int android.app.Fragment.mContainerId&#39;读取 - NullPointerException: Attempt to read from field 'int android.app.Fragment.mContainerId' on a null object reference Android ViewGroup 崩溃:尝试从空对象引用上的字段“int android.view.View.mViewFlags”读取 - Android ViewGroup crash: Attempt to read from field 'int android.view.View.mViewFlags' on a null object reference 空指针异常:尝试在空对象引用Android上调用虚拟方法 - Null pointer exception: Attempt to invoke virtual method on a null object reference Android 尝试从 null object 参考上的字段 'android.view.View androidx.recyclerview.widget.RecyclerView$b0.a' 中读取 - Attempt to read from field 'android.view.View androidx.recyclerview.widget.RecyclerView$b0.a' on a null object reference java.lang.NullPointerException:尝试从空对象引用中的字段“ long org.opencv.core.Mat.nativeObj”读取 - java.lang.NullPointerException: Attempt to read from field 'long org.opencv.core.Mat.nativeObj' on a null object reference 使用导航抽屉时尝试从空对象引用上的字段&#39;int android.support.v4.app.Fragment.mContainerId&#39;读取 - Attempt to read from field 'int android.support.v4.app.Fragment.mContainerId' on a null object reference when using Navigation Drawer
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM