
在Java编程中,开发者经常会遇到一个常见问题:当尝试打印自定义类的对象实例或包含这些对象的集合(如数组)时,控制台输出的往往是一串类似内存地址的哈希码,而非对象内部的实际数据。例如,使用`Arrays.toString()`打印一个自定义对象数组时,我们可能会看到`[com.example.Student@1f32e575, com.example.Student@279f2327]`这样的输出。这对于调试和理解程序状态带来了不便。
所有Java类都隐式或显式地继承自java.lang.Object类。Object类提供了一个默认的toString()方法实现,其源码大致如下:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}这个默认实现返回的是“类名@对象的哈希码的十六进制表示”。这就是为什么在不进行任何修改的情况下,直接打印对象会看到哈希码的原因。Arrays.toString()方法在处理对象数组时,会遍历数组中的每个元素,并调用每个元素的toString()方法来获取其字符串表示,然后将这些表示连接起来。因此,要改变输出行为,我们需要改变对象本身的toString()行为。
解决上述问题的核心在于重写自定义类中的toString()方法。通过在类中提供一个自己的toString()实现,我们可以定义对象在被转换为字符串时应该如何显示。这个方法应该返回一个包含对象关键属性的、人类可读的字符串。
立即学习“Java免费学习笔记(深入)”;
以下是一个Student类的示例,演示了如何重写toString()方法:
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
public class Main {
private static class Student {
String fName; // First Name
String lName; // Last Name
int id; // Student ID
int score; // Score
public Student(String fName, String lName, int id, int score) {
this.fName = fName;
this.lName = lName;
this.id = id;
this.score = score;
}
public int getScore() {
return score;
}
@Override
public String toString() {
return "Student{id=" + id + ", fName='" + fName + "', lName='" + lName + "', score=" + score + "}";
}
}
// 辅助方法:检查字符串是否只包含字母
public static boolean isAlphabetic(String str) {
if (str == null || str.isEmpty()) {
return false;
}
for (char c : str.toCharArray()) {
if (!Character.isLetter(c)) {
return false;
}
}
return true;
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("请输入学生数量:");
int k = input.nextInt(); // 学生数量
Student[] students = new Student[k];
for (int i = 0; i < k; ) {
System.out.println("请输入学生ID:");
int id = input.nextInt();
String fName;
do {
System.out.println("请输入学生名:");
fName = input.next();
if (!isAlphabetic(fName)) {
System.out.println("输入错误!学生名必须只包含字母,请重新输入。");
}
} while (!isAlphabetic(fName));
String lName;
do {
System.out.println("请输入姓氏:");
lName = input.next();
if (!isAlphabetic(lName)) {
System.out.println("输入错误!姓氏必须只包含字母,请重新输入。");
}
} while (!isAlphabetic(lName));
System.out.println("请输入分数:");
int score = input.nextInt();
students[i++] = new Student(fName, lName, id, score);
}
// 使用匿名内部类实现Comparator进行分数降序排序
Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
// 降序排列,所以用s2的分数减s1的分数
return Integer.compare(s2.getScore(), s1.getScore());
}
});
System.out.println("\n排序后的学生信息:");
System.out.println(Arrays.toString(students));
input.close();
}
}在上述代码中,我们为Student类添加了一个toString()方法:
@Override
public String toString() {
return "Student{id=" + id + ", fName='" + fName + "', lName='" + lName + "', score=" + score + "}";
}通过@Override注解,我们明确表示这是对父类方法的一个重写。现在,当Arrays.toString(students)被调用时,它会为数组中的每个Student对象调用我们自定义的toString()方法,从而输出清晰、可读的学生信息,例如:
[Student{id=101, fName='Alice', lName='Smith', score=95}, Student{id=102, fName='Bob', lName='Johnson', score=88}]Arrays.sort(students, (s1, s2) -> Integer.compare(s2.getScore(), s1.getScore()));
通过正确重写toString()方法,我们可以有效地控制Java中自定义对象的字符串表示,从而极大地提升代码的可读性和调试效率。
以上就是Java自定义对象打印:告别哈希码,拥抱内容显示的详细内容,更多请关注php中文网其它相关文章!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号