我正在用Java编写一个程序,从文件中读取一些内容,并将所有内容存储在数组中。阵列中的每个插槽都是一个链表。我得到一个空指针异常,我不知道为什么。我对编程很陌生,我有一种可怕的感觉,这是我看不到的显而易见的东西,但每个看过它的人都会花上两秒钟的时间来弄清楚。。。然后我会觉得自己很愚蠢,但无论如何,这是。。。
根据我的调试器(我使用的是Eclipse),NPE在GiveJob类中。我已经用所有的大写字母标记了这条线,以便于找到它
我对NPE的第一个想法是,它一定与我有一个结构数组这一事实有关。据我所知,在使用Java时,对象数组中的每个槽都会自动初始化为null,我认为这将包括一个structs数组。我错了吗?
非常感谢任何帮助,因为我已经为此困惑了很长一段时间:-p
这是数组的类:
public class Person{
String name;
Jobs jobs;
}
这是链接列表的类:
public class Jobs{
String typeOfJob;
Jobs next;
}
这是给人一份工作的课程:
public void GiveJob(String personName, String newJob int N, Person[] people){
//go through the array of people to see if the person already exists
for(int i=0; i<N; i++){
//check to see if the person has already been added
if(people[i].jobs != null){ //NULL POINTER EXCEPTION
if(people[i].jobs.compareToIgnoreCase(newJob) == 0){
//if the person has been added, check to see if the job has
//already been added
Jobs currentNode = people[i].jobs;
while(currentNode.next != null){
//if the job has already been added, break
if(currentNode.typeOfJob.compareToIgnoreCase(newJob) == 0){
break;
}
currentNode = currentNode.next;
}
//if the job has already been added, break
if(currentNode.typeOfJob.compareToIgnoreCase(newJob) == 0){
break;
}
else{
Jobs tempNode = new Jobs();
tempNode.typeOfJob = newJob;
tempNode.next = null;
people[i].jobs.next = tempNode;
}
}//end if the job has already been added
}
//if the person has not been added yet, add him/her
else if(people[i] == null){
people[i].name = personName;
Jobs tempNode = new Jobs();
tempNode.typeOfJob = newJob;
tempNode.next = null;
people[i].jobs = tempNode;
break;
}
}//end for(int i=0; i<N; i++) - checking if the city has been added already
}//end addToAdjList method
}//end AdjacencyList class
这是包含main的类:
import java.io.*;
import java.util.*;
public class LookingForAJob {
public static void main(String[] args) {
//read in file
try{
File filename = new File("jobListing.txt");
Scanner fin = new Scanner(filename);
//read in the number of people (N) from file
int N = fin.nextInt();
//read in the number of jobs available (M) from file
int M = fin.nextInt();
//create a new instance of GiveJob
GiveJob jobSearch = new GiveJob();
//Create the array to put the people into
Person people[] = new Person[N];
//read in information from file
for(int i=0; i<M; i++){
//get person's name
String personName = fin.next();
//get job name
String jobName = fin.next();
//put what was read in from the file into an linked list
jobSearch.GiveJob(personName, jobName, N, people);
}//end for(int i=0; i<M; i++)
}//end try
catch(FileNotFoundException e){
System.err.println("Input file not found for reading!");
System.exit(0);
}
catch(Exception e){
System.err.println("Input file not in correct format");
System.exit(0);
}
}
}
您的代码似乎有很多错误-不幸的是,您试图减少问题中发布的代码数量(这通常是一件好事)也适得其反,因为这使得您更难确定代码中的错误以及复制粘贴的东西时的错误。
在我开始向您解释一些东西之前,请注意,您可能需要查看一些网站或其他地方,这些网站或地方有助于从C语言过渡到Java,因为您在一些基本问题上出错了。这并不是你的编程能力的问题,你只是不知道Java与C的区别,比如如何做条件语句。
无论如何,我认为问题是,你的类中的值,事实上,类本身还没有初始化/实例化(你已经命名了它们,因为你现在可以为它们设置值等等,但它们实际上还没有任何值)。让我们先处理一些小问题,您需要实例化类中的值,如Jobs和Person。实现这一点的方法是通过构造函数(如果你不确定我所说的内容,请看一看Java编程网站或书籍的介绍)。在确保name
之类的值不为null之后,您将不得不在某个地方实例化Person
类。您似乎希望在GiveJob
方法中执行此操作(该方法以不合适的样式命名,并且缺少其中一个参数的类型声明)。因此,您必须实例化Person对象(类似于people[i] = new Person(/*args*/)
)。
您要求解决的特定问题在于,您的Person数组中还没有实例化的Person。但是,您正试图(再次以不适当的方式)访问该Person的变量。此人不存在,属于null
类型。null
没有属于它的jobs
变量。因此,您会得到一个空指针错误。
@棘轮怪胎和@SQiShER有办法修复它,并适当地显示。然而,您仍然需要查看基本的Java编码指南,以帮助您适应新的情况和适当的风格方法。
Person people[] = new Person[N];
这只是创建了一个大小为N的数组,其中填充了NULL
。我没有看到任何初始化代码然后在GiveJob
函数中调用people[i].job
。像这样的
for(int i=0; i<N ;i++ ){
people[i] = new Person();
}
for(int i=0; i<N; i++){
//check to see if the person has already been added
if(people[i].jobs != null){ //NULL POINTER EXCEPTION
相反,你应该像这样遍历你的数组:
for(int i=0; i<people.length; i++){
if(people[i].jobs != null){
}
在那一行中,逗号也不见了:
public void GiveJob(String personName, String newJob int N, Person[] people)
字符串之后,int 之前
交换if around:首先检查人员是否已添加,然后检查其工作:
for(int i=0; i<people.length; i++){
//if the person has not been added yet, add him/her
if(people[i] == null){
people[i] = new Person();
people[i].name = personName;
Jobs tempNode = new Jobs();
tempNode.typeOfJob = newJob;
tempNode.next = null;
people[i].jobs = tempNode;
break;
}
//check to see if the person has already been added
if(people[i].jobs != null){ //NULL POINTER EXCEPTION
if(people[i].jobs.compareToIgnoreCase(newJob) == 0){
//if the person has been added, check to see if the job has
//already been added
Jobs currentNode = people[i].jobs;
while(currentNode.next != null){
//if the job has already been added, break
if(currentNode.typeOfJob.compareToIgnoreCase(newJob) == 0){
break;
}
currentNode = currentNode.next;
}
//if the job has already been added, break
if(currentNode.typeOfJob.compareToIgnoreCase(newJob) == 0){
break;
}
else{
Jobs tempNode = new Jobs();
tempNode.typeOfJob = newJob;
tempNode.next = null;
people[i].jobs.next = tempNode;
}
}//end if the job has already been added
}
}
一个简单的解决方案是更改if条件的顺序,以便首先检查数组元素是否为null,如果为null,则通过分配一个新的Person
实例来初始化它,如下所示:people[i] = new Person()
固定代码:
if(people[i] == null){
people[i] = new Person(); // ADD THIS LINE TO FIX THE NPE
people[i].name = personName;
Jobs tempNode = new Jobs();
tempNode.typeOfJob = newJob;
tempNode.next = null;
people[i].jobs = tempNode;
break;
} else if(people[i].jobs != null){
if(people[i].jobs.compareToIgnoreCase(newJob) == 0){
//if the person has been added, check to see if the job has
//already been added
Jobs currentNode = people[i].jobs;
while(currentNode.next != null){
//if the job has already been added, break
if(currentNode.typeOfJob.compareToIgnoreCase(newJob) == 0){
break;
}
currentNode = currentNode.next;
}
//if the job has already been added, break
if(currentNode.typeOfJob.compareToIgnoreCase(newJob) == 0){
break;
}
else{
Jobs tempNode = new Jobs();
tempNode.typeOfJob = newJob;
tempNode.next = null;
people[i].jobs.next = tempNode;
}
}//end if the job has already been added
}
您需要这样做,因为您使用Person people[] = new Person[N];
创建的Array的元素仍然为null,因此您尝试访问的属性的内存尚未分配。Java没有任何类似于C结构的东西,所以结构只是一个简单的Java对象,在访问其字段之前,它需要用new进行实例化。