Setter 为 class 中的每个对象设置值

Setter sets value for every object in class

我有一个程序,将学生的姓名和成绩作为用户输入,然后对其进行一些操作,这些操作与问题的范围无关。代码如下:

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 关键字 - 为什么它会为所有对象设置值?

移动数组 (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();

}

在您的原始代码中,您只使用了一个数组,即 temp 一直指向同一个数组。完成第一个学生的初始化后,当您循环填充第二个学生的成绩时,您正在改变(或修改)为第一个学生创建的 same 成绩数组。

您需要移动

int[] temp = new int[count1]; // Temporary array for storing grades entered

在外部 for 循环内,否则所有创建的 Student 都将引用相同的成绩数组,并且都将以最后一个学生的成绩结束。

请注意 Student 的构造函数和 Student::setGrades() 如何通过引用获得 grades

这意味着对于每个 Student 的实例,其 grades 字段指向在其初始化期间接收到的参数。

但是,您只初始化 temp 一次,因此所有实例都指向同一个成绩数组。更改此数组后,调用 student.printGrades() 将打印共享数组的内容。

这可以通过在每次迭代时初始化 temp 来解决,然后再创建新的 Student 实例;或者通过在 setGrades() 方法中按值 复制数组

public void setGrades(int[] temp) {
    this.grades.clone(temp);
}

这是因为你对每个人的所有成绩使用同一个数组。

搬家 temp = new int[count1]; 第一个循环内应该修复它