我有一个程序,它将学生的姓名和成绩作为用户输入,然后对它们执行一些操作,这与问题的范围无关。代码如下:
import java.io.*;
import java.util.Arrays;
import java.util.Scanner;
public class Student {
// Four attributes that define Student
private String name;
private double points;
private int startYear;
private int[] grades;
public Student(String name, double points, int startYear, int[] grades) {
this.name = name;
this.points = points;
this.startYear = startYear;
this.grades = grades;
}
//Constructor. Everyone starts with 0 points and this year
public static void main(String[] args) {
Scanner sc = new Scanner(System.in); //Create scanner
System.out.println("Please enter the number of students:");
int count = sc.nextInt(); // Number of students
System.out.println("Please enter the number of grades:");
int count1 = sc.nextInt(); // Number of grades
Student students[] = new Student[count]; // Create array of student objects based on previously entered value
int[] temp = new int[count1]; // Temporary array for storing grades entered
for (int i = 1; i < count + 1; i++) {
System.out.println("Please enter the name of student " + i);
String name = sc.next();
students[i - 1] = new Student(name,0.0,2018,temp); // Creating student object
System.out.println("Please enter grades of " + name);
for (int k = 0; k < count1; k++) {
int personal_grades = sc.nextInt();
temp[k] = personal_grades; //filling the temporary array
//System.out.println(grades.length); //for debugging
}
students[i - 1].setGrades(temp); //transferring from temporary array to student object array
students[i-1].printGrades();
}
System.out.println((students[0].name));
System.out.println((students[1].name));
System.out.println(Arrays.toString(students[0].grades));
System.out.println(Arrays.toString(students[1].grades));
for(int i = 0; i < count; i++) {
System.out.println("Grades of " + students[i].name + " are:");
//students[i].printGrades();
}
for(int i = 0; i < count; i++) {
System.out.println("Average of " + students[i].name + " is:");
// students[i].average();
}
int passed=0;
for(int i = 0; i < count; i++) {
if(students[i].average()>5.5)
{
passed++;
}
}
System.out.println(passed+" students passed!");
}
public void setGrades(int[] temp) {
this.grades = temp;
}
public int[] getGrades() {
return grades;
}
public void printGrades() {
System.out.println(Arrays.toString(grades));
}
public float average (){
int k = 0;
int sum=0;
float average=0;
while (k < this.grades.length) {
sum=sum+this.grades[k];
k++;
}
average = sum/(float)this.grades.length;
System.out.println(average);
return average;
}
}
我对代码的问题如下:setter方法似乎设置了所有创建的对象的值。以此测试运行为例:
您可以看到输入的最后一个学生的成绩出现在每个学生的记录中。我已经调试并发现它是导致这种情况的setGrades
方法。但是,我使用的是this
关键字 - 为什么它会为所有对象设置值呢?
你需要移动
int[] temp = new int[count1]; // Temporary array for storing grades entered
在外部for
循环内,否则所有创建的Student
s将引用相同的成绩数组,并且最终将获得最后一个学生的成绩。
这是因为你对所有人的等级使用相同的数组。
在第一个循环中移动temp = new int[count1];
应该修复它
请注意Student
的构造函数和Student::setGrades()
如何通过引用获得grades
。
这意味着对于每个Student
的实例,其grades
字段指向在其初始化期间接收的参数。
但是,您只初始化temp
一次,因此所有实例都指向相同的grade数组。更改此数组后,调用student.printGrades()
将打印共享数组的内容。
这可以通过在创建新的temp
实例之前在每次迭代时初始化Student
来解决;或者通过setGrades()
方法中的值复制数组:
public void setGrades(int[] temp) {
this.grades.clone(temp);
}
移动数组(temp
),将成绩保留在创建单个学生的循环中
for (int i = 1; i < count + 1; i++) {
...
int[] temp = new int[count1]; //The array holding the grades must be *specific* for each student
students[i - 1] = new Student(name, 0.0, 2018, temp); // Creating student object
...
students[i - 1].setGrades(temp); //transferring from temporary array to student object array
students[i - 1].printGrades();
}
在原始代码中,您只使用一个数组i。,e temp
始终指向同一个数组。初始化完第一个学生后,当您循环填充第二个学生的成绩时,您正在改变(或修改)为第一个学生创建的相同成绩数组。