
1. 理解与完善 Student 类
首先,我们需要一个表示学生信息的类。这个 student 类应包含学生的姓名(string)和分数(int)。为了使数据可访问和修改,还需要提供相应的构造器、getter和setter方法。
原始的 Student 类设计:
import java.util.Scanner;
public class Student {
private String name;
private int score;
public Student() {
}
public Student(String name, int score){
this.name = name;
this.score = score;
}
public void setName(String name) {
this.name = name;
}
public void setScore(int score) {
this.score = score;
}
public void readInput() {
Scanner keyboard = new Scanner(System.in);
System.out.println("Please enter the student's name: ");
this.name = keyboard.next();
System.out.println("Please enter the student's score: ");
this.score = keyboard.nextInt();
}
public void writeOutput() {
System.out.println("The student's name and score: " + name + ", " + score + "%");
}
// 原始设计中的Getter方法有误
// public String getName(String name) {
// return this.name;
// }
// public int getScore(int score) {
// return score;
// }
}问题分析与修正: 原始 Student 类中的 getName(String name) 和 getScore(int score) 方法签名不正确。标准的Getter方法不应接受参数,它们的作用是返回私有成员变量的值。
修正后的 Student 类:
import java.util.Scanner; // 确保导入Scanner
public class Student {
private String name;
private int score;
public Student() {
// 默认构造器,可用于创建空对象
}
public Student(String name, int score){
this.name = name;
this.score = score;
}
// Setter方法
public void setName(String name) {
this.name = name;
}
public void setScore(int score) {
this.score = score;
}
// Getter方法:不应有参数
public String getName() { // 修正:移除参数
return this.name;
}
public int getScore() { // 修正:移除参数
return this.score; // 修正:返回实例变量this.score
}
// 从控制台读取学生信息
public void readInput() {
Scanner keyboard = new Scanner(System.in); // 每次调用都创建新Scanner可能不是最佳实践,但在此示例中可接受
System.out.println("Please enter the student's name: ");
this.name = keyboard.next();
System.out.println("Please enter the student's score: ");
this.score = keyboard.nextInt();
// keyboard.close(); // 在方法内部关闭Scanner可能会导致后续输入问题,通常在程序结束时统一关闭
}
// 输出学生信息
public void writeOutput() {
System.out.println("The student's name and score: " + name + ", " + score + "%");
}
}注意事项: 在实际应用中,Scanner 对象通常在程序的入口点创建一次,并作为参数传递或通过其他方式共享,以避免资源泄露和不必要的对象创建。
2. 实现成绩统计逻辑 (TestReporter 类)
TestReporter 类负责管理学生数组,并计算班级的平均分和最高分。
立即学习“Java免费学习笔记(深入)”;
原始的 TestReporter 类设计:
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Scanner;
public class TestReporter {
private int highestScore;
private double averageScore;
private Student[] ourClass;
private int numOfStudents;
public TestReporter(){
}
public void getData() {
Scanner keyboard = new Scanner(System.in);
System.out.println("Please enter the number of students");
numOfStudents = keyboard.nextInt();
ourClass = new Student[numOfStudents];
for (int i = 0; i < numOfStudents ; i++) {
ourClass[i] = new Student();
ourClass[i].readInput();
}
// keyboard.close(); // 同Student类,此处关闭Scanner可能导致问题
}
public void computeStats() {
double total = 0;
for (int i = 0; i < numOfStudents; i++) {
// 原始代码:total = total + ourClass[i]; // 错误:不能将Student对象直接加到double
}
// averageScore = total / ourClass.length; // 原始代码:在循环外计算,但total计算有误
}
public void displayResults() {
for (Student Student: ourClass) {
Student.writeOutput();
}
}
}问题分析与修正:
云点滴客户解决方案是针对中小企业量身制定的具有简单易用、功能强大、永久免费使用、终身升级维护的智能化客户解决方案。依托功能强大、安全稳定的阿里云平 台,性价比高、扩展性好、安全性高、稳定性好。高内聚低耦合的模块化设计,使得每个模块最大限度的满足需求,相关模块的组合能满足用户的一系列要求。简单 易用的云备份使得用户随时随地简单、安全、可靠的备份客户信息。功能强大的报表统计使得用户大数据分析变的简单,
-
computeStats 方法中的错误:
- total = total + ourClass[i];:ourClass[i] 是一个 Student 对象,不能直接与 double 类型的 total 相加。正确的做法是调用 ourClass[i].getScore() 获取分数。
- 没有计算 highestScore 的逻辑。
- highestScore 和 averageScore 应该更新类的成员变量,而不是在方法内部声明局部变量(除非有特殊需求)。
- displayResults 方法的调用顺序: 在显示结果之前,需要确保 computeStats 已经被调用,以更新 highestScore 和 averageScore。
修正后的 TestReporter 类:
import java.util.Scanner; // 仅需导入Scanner,其他可能不需要
public class TestReporter {
private int highestScore;
private double averageScore;
private Student[] ourClass;
private int numOfStudents;
public TestReporter(){
// 构造器可以进行一些初始化,例如将最高分初始化为0或Integer.MIN_VALUE
this.highestScore = 0; // 假设分数非负
this.averageScore = 0.0;
this.numOfStudents = 0;
}
// 获取学生数据
public void getData() {
Scanner keyboard = new Scanner(System.in);
System.out.println("Please enter the number of students:");
numOfStudents = keyboard.nextInt();
ourClass = new Student[numOfStudents];
for (int i = 0; i < numOfStudents ; i++) {
ourClass[i] = new Student();
System.out.println("\n--- Entering data for Student " + (i + 1) + " ---");
ourClass[i].readInput();
}
// 考虑到readInput内部也创建Scanner,此处不关闭,由系统或更上层管理
}
// 计算统计数据:平均分和最高分
public void computeStats() {
if (numOfStudents == 0 || ourClass == null) {
System.out.println("No student data available to compute stats.");
this.averageScore = 0.0;
this.highestScore = 0;
return;
}
double total = 0;
this.highestScore = 0; // 初始化最高分为0,适用于非负分数。若分数可能为负,应初始化为Integer.MIN_VALUE。
for (int i = 0; i < numOfStudents; i++) {
int currentScore = ourClass[i].getScore(); // 正确获取学生分数
total += currentScore; // 累加总分
if (currentScore > this.highestScore) {
this.highestScore = currentScore; // 更新最高分
}
}
this.averageScore = total / numOfStudents; // 计算平均分
}
// 显示结果
public void displayResults() {
// 在显示之前确保统计数据已计算
computeStats();
System.out.println("\n--- Student Details ---");
for (Student student : ourClass) { // 使用增强for循环遍历数组
student.writeOutput();
}
System.out.println("\n--- Class Statistics ---");
System.out.println("Total number of students: " + numOfStudents);
System.out.println("Average Score = " + String.format("%.2f", this.averageScore)); // 格式化输出平均分
System.out.println("Highest Score = " + this.highestScore);
}
// 主方法,用于运行程序
public static void main(String[] args) {
TestReporter reporter = new TestReporter();
reporter.getData(); // 获取学生数据
// reporter.computeStats(); // displayResults会调用computeStats,此处可省略
reporter.displayResults(); // 显示结果
}
}3. 完整的示例代码
为了方便读者运行和测试,我们将 Student 类和 TestReporter 类整合,并提供一个 main 方法作为程序的入口。
Student.java
import java.util.Scanner;
public class Student {
private String name;
private int score;
public Student() {
}
public Student(String name, int score){
this.name = name;
this.score = score;
}
public void setName(String name) {
this.name = name;
}
public void setScore(int score) {
this.score = score;
}
public String getName() {
return this.name;
}
public int getScore() {
return this.score;
}
public void readInput() {
Scanner keyboard = new Scanner(System.in); // 注意:实际应用中Scanner的管理
System.out.print(" Enter student's name: ");
this.name = keyboard.next();
System.out.print(" Enter student's score: ");
this.score = keyboard.nextInt();
// keyboard.close(); // 不在此处关闭
}
public void writeOutput() {
System.out.println("Name: " + name + ", Score: " + score + "%");
}
}TestReporter.java
import java.util.Scanner;
public class TestReporter {
private int highestScore;
private double averageScore;
private Student[] ourClass;
private int numOfStudents;
public TestReporter(){
this.highestScore = 0; // 初始化为0,假设分数非负
this.averageScore = 0.0;
this.numOfStudents = 0;
}
public void getData() {
Scanner keyboard = new Scanner(System.in);
System.out.println("Please enter the number of students:");
numOfStudents = keyboard.nextInt();
ourClass = new Student[numOfStudents];
for (int i = 0; i < numOfStudents ; i++) {
ourClass[i] = new Student();
System.out.println("\n--- Entering data for Student " + (i + 1) + " ---");
ourClass[i].readInput();
}
// keyboard.close(); // 不在此处关闭
}
public void computeStats() {
if (numOfStudents == 0 || ourClass == null) {
System.out.println("No student data available to compute stats.");
this.averageScore = 0.0;
this.highestScore = 0;
return;
}
double total = 0;
this.highestScore = 0; // 重新初始化,确保每次计算都是从头开始
for (int i = 0; i < numOfStudents; i++) {
int currentScore = ourClass[i].getScore();
total += currentScore;
if (currentScore > this.highestScore) {
this.highestScore = currentScore;
}
}
this.averageScore = total / numOfStudents;
}
public void displayResults() {
computeStats(); // 确保在显示前计算统计数据
System.out.println("\n--- Student Details ---");
for (Student student : ourClass) {
student.writeOutput();
}
System.out.println("\n--- Class Statistics ---");
System.out.println("Total number of students: " + numOfStudents);
System.out.println("Average Score = " + String.format("%.2f", this.averageScore));
System.out.println("Highest Score = " + this.highestScore);
}
public static void main(String[] args) {
TestReporter reporter = new TestReporter();
reporter.getData();
reporter.displayResults();
}
}4. 注意事项与最佳实践
- Getter/Setter 的正确用法: Getter 方法用于获取私有成员变量的值,不应接受参数。Setter 方法用于设置私有成员变量的值,通常接受一个与成员变量类型相同的参数。
- 变量初始化: 在计算最大值时,highestScore 应被初始化为一个足够小的值(例如 0 对于非负分数,或 Integer.MIN_VALUE 对于可能包含负数的情况),以确保任何有效分数都能被正确识别为最大值。
- 循环遍历对象数组: 使用传统的 for 循环(通过索引)或增强 for 循环(for (Student student : ourClass))都是有效的遍历方式。当需要访问数组索引时,传统 for 循环更合适;当仅需遍历元素时,增强 for 循环更简洁。
- 职责分离: TestReporter 类很好地体现了职责分离的原则。getData 负责数据输入,computeStats 负责数据计算,displayResults 负责数据输出。这种模块化设计提高了代码的可读性和可维护性。
- Scanner 资源管理: 在实际生产环境中,Scanner 对象应谨慎管理。频繁地创建和关闭 Scanner 可能会导致资源泄露或异常。通常建议在应用程序生命周期中只创建一次,并在程序结束时统一关闭。在本教程示例中,为了简化,readInput 和 getData 方法内部都创建了 Scanner,但在大型应用中应避免。
- 错误处理: 对于用户输入,应考虑添加错误处理机制,例如使用 try-catch 块来处理 InputMismatchException,以防止用户输入非数字字符导致程序崩溃。
总结
通过本教程,我们学习了如何在Java中有效地处理包含多种数据类型的对象数组。关键在于正确设计自定义类(如 Student),确保 Getter 和 Setter 方法的规范性,并通过遍历数组来访问对象的特定属性,进而执行统计计算。清晰的模块化设计和对细节(如变量初始化、资源管理)的关注是编写健壮、可维护代码的重要方面。掌握这些技能对于任何需要进行数据处理的Java开发者都至关重要。









