我已经指示建立一个学生类,包括不同的变量,包括字符串名称,int标记物理等。然后,我的目标是构建一个方法来读取包含这些数据的文本文件,而不使用ArrayList。之后,我需要对数组进行排序。但是我在将txt文件的数据放入数组时遇到了问题。
代码如下:
public class Main2{
public static void main(String[] args) throws FileNotFoundException {
String filename = "students.txt";
Student[] record = readData(filename);
record = new Student [record.length];
for(int i = 0; i < record.length; i++){
System.out.println(record[i]);
}
}
//Method for read data from the .txt file into an array
private static Student[] readData(String filename){
int arraysize = 0;
try{
Scanner s1 = new Scanner(new File(filename));
//Count elements in the file
while(s1.hasNext()){
arraysize++;
s1.next();
}
//Create an array and copy the elements into it
Student[] studentRecord = new Student[arraysize];
Scanner s2 = new Scanner(new File(filename));
for(int i = 0; i < arraysize; i++){
studentRecord[i].name = s2.next();
studentRecord[i].physic = s2.nextInt();
studentRecord[i].chemistry = s2.nextInt();
studentRecord[i].math = s2.nextInt();
studentRecord[i].average = (double)(studentRecord[i].physic + studentRecord[i].chemistry + studentRecord[i].math)/3;
// double roundedAvg = Math.round(average * 100.0) / 100.0;
// studentRecord[i].average = Math.round((physic + chemistry + math)/3 * 100.0)/100.0;
}
return studentRecord;
}
catch(FileNotFoundException e){
}
return null;
}
}
文本文件包括如下记录:
Jack 77 84 93
Tod 84 86 80
Name marksP marksC marksM
代码可以编译,但当我运行代码。它显示了
Exception in thread "main" java.lang.NullPointerException: Cannot assign field "name" because "<local3>[<local5>]" is null
at Main2.readData(Main2.java:40)
at Main2.main(Main2.java:10)
是因为学生班吗?但是我已经将Student Class属性初始化为:
public Student(String name, int m1, int m2, int m3, double avg){
this.name = name;
int.mark1 = m1;
...
}
我做错了什么?我如何修复代码?当我在Student类中初始化时,该名称不应该为空。
在您的for
循环中,您从文件中读取数据,您的studentRecord
尚未包含实际的Student
对象。到目前为止,它只是一个占位符,可以容纳指定数量的Student
对象。因此,您需要实际创建Student
对象来存储在指定的数组中。
为此,读取数据,将其临时存储在变量中,然后通过已经拥有的构造函数创建每个Student
对象。
所以它应该看起来像这样:
for(int i = 0; i < arraysize; i++){
String name = s2.next();
int physic = s2.nextInt();
int chemistry = s2.nextInt();
int math = s2.nextInt();
double average = (double)(physic + chemistry + math) / 3;
Student myStudent = new Student (name, physic, chemistry, math, average);
studentRecord[i] = myStudent;
}
另外,你现在计算数组大小不正确。您需要计算行数,而不是每个标记。更像这样:
while(s1.hasNextLine()){
arraysize++;
s1.nextLine();
}
我发现的第一个问题是您计算文件中学生人数的方式。如果你知道你的students.txt文件的行数正好等于学生人数(没有标签或任何可以延伸到多行的东西),那么你可以这样计数:
while(scan.hasNext()) {
lines++;
scan.nextLine();
}
第二个问题是关于数组的创建。当你像这样初始化一个数组时:
final Student[] students = new Students[length];
它将创建数组,它将充满null元素:[null, null, null,... ]
。但是这些null元素不是你的Student对象。所以你可以用空对象填充数组然后在后面的代码中改变它们的属性:
final Student[] students = new Students[length];
Arrays.fill(students, new Student("default", 100, 100, 100);
提示:您可以像这样将平均值的计算移到Student类的构造函数中,并根据用例链接尝试使用更小或更大的日期类型。:
public Student(String name, byte physics, byte chemistry, byte math) {
this.name = name;
this.physics = physics;
this.chemistry = chemistry;
this.math = math;
this.avg = (math + chemistry + physics) / 3.0;
}
现在我们不需要为Student对象设置或覆盖变量。当有重复的代码时,可能有更好的方法来编写它(不是所有时候)。
for (int i = 0; i < lines; i++) {
students[i] = new Student(fileScanner.next(), fileScanner.nextByte(), fileScanner.nextByte(), fileScanner.nextByte());
System.out.println(students[i]);
}
我认为你的问题是你没有完全理解当你执行
时发生了什么Student[] studentRecord = new Student[arraysize];
这将创建一个名为studentRecord
的数组,该数组具有特定的大小。它不会创建任何Student类型的对象放入这个数组。你的数组将只包含null。
要解决这个问题,你需要这样做:
for(int i = 0; i < arraysize; i++) {
studentRecord[i] = new Student();
studentRecord[i].name = s2.next();