web-dev-qa-db-fra.com

Exception de pointeur NULL, "Tentative de lecture d'un champ sur une référence d'objet null"

Je crée une application dans laquelle l'utilisateur tape une liste de tâches, et cette liste est enregistrée dans un tableau. Chaque tâche du tableau est une instance de la classe Assignment. Cependant, j'ai réalisé qu'en Java, il n'est pas possible d'ajouter un élément à un tableau après sa création. J'ai donc créé un tableau appelé tasks, composé de nombreuses valeurs nulles: Assignment[]tasks = {null, null, null, null, null, null, null, null, null, null, null, null};. Lorsque je veux ajouter une tâche au tableau, je remplace simplement la valeur null suivante par l'objet. Cependant, j'ai également besoin d'un tableau contenant uniquement les tâches, sans valeur NULL. J'ai donc créé un tableau appelé full_tasks pour tous les éléments non nuls:

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

Alors maintenant, le tableau full_tasks devrait être un tableau de toutes les tâches, dont aucune n'est nulle, non? Cependant, lorsque j'exécute l'application, elle ne peut pas lancer l'activité. Une erreur est due à une exception de pointeur 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)

La ligne sur laquelle l'erreur pointe est la suivante:

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

Je ne suis toujours pas tout à fait sûr de ce qu'est une référence d'objet null, mais je pense que cela signifie qu'un des éléments du tableau full_tasks est null. Cela serait-il correct? Et si c'est le cas, que puis-je faire pour m'assurer que le tableau full_tasks est seulement les éléments non nuls du tableau tasks?

Merci beaucoup!

Edit: la fonction constructeur de la classe d'affectation est:

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

Une référence null est simplement cette null. Dans votre code, c'est tasks[i].name où vous essayez d'appeler name sur tasks[i] alors tasks[i] est null.

Il y a un scénario auquel je peux penser, où votre code lancerait certainement une NullPointerException. Donc, je suppose que votre tableau de tâches peut ressembler à ceci:

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

Alors full_tasks aura une taille de 4 mais

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

jette unNPEdès que i == 1 car tasks[1] est null.

Donc, si vous voulez remplir full_tasks avec seulement des tâches non nulles, assurez-vous de disposer des bons index tasks.

2
Sascha Kolberg

Voici ce que je pense

Vous venez de trouver les éléments numériques qui ne sont pas nullname__. Vous ne savez pas où dans le tableau les nullname __ sont présents.

Supposons UNIQUEMENT que le premier élément est nullname__. Donc realLengthsera 7. La dernière boucle forva du i=0 au i=7. Lorsque i=0, tasks[i].name tente d'accéder au champ namedu premier élément; mais votre premier élément se trouve être null`. C'est là que les choses vont mal. 

Solution:

Il y a plusieurs solutions. Le plus efficace auquel je puisse penser utilise un ArrayListname__.

Pour vous déplacer en utilisant des tableaux, vous devez stocker les index de tous les éléments qui ne sont pas nullname__. C'est une façon.

Voici un autre: 

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

Il semble que vous tentiez de copier et de compacter le tableau tasks dans le tableau full_tasks (en supprimant les éléments nuls), mais vous procédez en partie de manière incorrecte, car vous accédez à tasks[i] dans la deuxième boucle sans vérifier si sa valeur est null.

Au lieu de:

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

vous pourriez écrire quelque chose comme ceci:

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

Mais encore une fois, pour résoudre votre problème initial, concernant le fait que vous ne puissiez ajouter aucun élément à un tableau, je suggère d’utiliser un ArrayList au lieu d’un simple tableau. Cela vous permet d'ajouter des éléments avec ArrayList.add(assignment) et de les supprimer à nouveau avec ArrayList.remove(index).

0
Floern

On dirait que la liste "tâches" est vide. Assurez-vous qu’il est rempli ou mettez un chèque nul Comme:

if(tasks[i] !=null) {

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

 }
0
Rehman

Vous pouvez considérer null comme quelque chose qui n'existe pas, par exemple, lorsque vous essayez d'obtenir task.name, où tâche est null , vous obtenez une erreur, car vous essayez d'obtenir un nom qui n'existe même pas.

En réalité, votre code vérifie actuellement le nombre d'éléments non nuls dans le tableau d'origine et tente d'extraire les n premiers éléments supplémentaires du tableau dans un nouveau tableau. 

c'est-à-dire que si la liste est {null, null, non-null, non-null}, elle a 2 éléments non nuls, mais votre code extrait à tort la liste des 2 premiers éléments qui sont {null, null}

Modifier, pour réellement faire ce que vous voulez:

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

Le problème dans votre code est ici:

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

Bien que vous comptiez la taille réelle, il pourrait y avoir une valeur null entre les deux qui le ferait pour obtenir un objet null à partir de la liste des tâches [i].


Une bonne idée pour résoudre ce problème consiste à utiliser une liste au lieu d'un tableau. Une liste peut être augmentée ou réduite à votre guise, il vous suffit d'ajouter ou de supprimer un élément de votre type d'objet. Par exemple:

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

Ensuite, vous pouvez utiliser list.size() pour obtenir la taille, savoir combien d’éléments sont présents ou pour supprimer le dernier élément. Et vous n'auriez aucun problème pour ajouter de nouveaux éléments à la liste.

0
George