
在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号