在 Java 类中定义 toString 方法(学习 Java 编程语言 050)
在 Object 中还有一个重要的 toString 方法,它会返回表示对象值的一个字符串。下面是一个典型的例子。Point 类的 toString方法将返回下面这样的字符串:
java.awt.Point[x=10,y=20]
绝大多数(但不是全部)的 toString 方法都遵循这样的格式:类的名字,随后是一对方括号括起来的字段值。下面是 Employee 类中的 toString 方法的实现:
public class Employee { private String name; private double salary; private LocalDate hireDay; ... @Override public String toString() { return "Employee[name=" + name + ",salary=" + salary + ",hireDay=" + hireDay + "]"; } }
实际上,还可以设计得更好一些。最好通过调用 getClass().getName() 获得类名的字符串,而不要将类名硬编码写到 toString 方法中。
public class Employee { private String name; private double salary; private LocalDate hireDay; ... @Override public String toString() { return getClass().getName() + "[name=" + name + ",salary=" + salary + ",hireDay=" + hireDay + "]"; } }
这样的 toString 方法也可以由子类调用。
设计子类的程序员应该定义自己的 toString 方法,并加入子类的字段。如果超类使用了 getClass().getName(),那么子类只要调用 super.toString() 就可以了。例如,下面是 Manager 类中的 toString 方法:
public class Manager extends Employee { private double bonus; ... @Override public String toString() { return super.toString() + "[bonus=" + bonus + "]"; } }
现在,Manager 对象将打印输出如下所示的内容:
Manager[name=...,salary=...,hireDay=...] [bonus=...]
随处可见 toString 方法的主要原因是:只要对象与一个字符串通过操作符 “+” 连接起来,Java 编译器就会自动地调用 toString 方法来获得这个对象的字符串描述。
提示: 可以不写
x.toString(),而写作
"" + x。这条语句将一个空串与 x 的字符串表示(也就是 x.toString())相连接。与 toString 不同的是,即使 x 是基本类型,这条语句照样能够执行。
如果 x 是一个任意对象,并调用
System.out.println(x)
println 方法就会简单地调用
x.toString(),并打印输出得到的字符串。
Object 类定义了 toString 方法,可以打印对象的类名和散列码。例如,调用:
System.out.println(System.out);
将输出:
java.io.PrintStream@7852e922
得到这样的结果原因是 PrintStream 类的设计者没有覆盖 toString() 方法。
警告: 令人烦恼的是,数组继承了 Object 类的 toString 方法,更有甚者,数组类型将采用一种古老的格式打印。例如:
int[] luckyNumger = {2, 3, 5, 7, 11, 13}
String s = "" + luckyNumger;
会生成字符串 “[I@52af6cff”(前缀 [I 表明是一个整型数组)。补救的方法是调用静态方法 Arrays.toString。代码:
String s = Arrays.toString(luckyNumger);
将生成字符串:
[2, 3, 5, 7, 11, 13]。
要想打印多维数组(即,数组的数组),则需要调用 Arrays.deepToString 方法。
toString 方法是一种非常有用的调试工具。在标准类库中,许多类都定义了 toString 方法,以便用户能够获得一些有关对象状态的有用信息。
像下面这样显示日志信息非常有益:
System.out.println("Current position = " + position);
提示: 强烈建议为自定义的每一个类增加 toString 方法。这样做不仅自己受益,所有使用这个类的程序员也会从这个日志记录支持中受益匪浅。
java.long.Object 1.0
- Class getClass()
返回包含对象信息的类对象。
- boolean equals(Object otherObject)
比较两个对象是否相等,如果两个对象指向同一块存储区域,方法返回 true;否则方法返回 false。要在自定义的类中覆盖这个方法。
- String toString()
返回表示对象值的字符串。要在自定义的类中覆盖这个方法。
java.lang.Class 1.0
- String getName()
返回这个类的名字。
- Class getSuperclass()
以 Class 对象的形式返回这个类的超类信息。
示例代码
import java.time.LocalDate; import java.util.Objects; /** * * @author bpx * @version 1.0.0 * @since 1.7.1 * * */ public class Employee { // 姓名 private String name; // 薪资 private double salary; // 认知日期 private LocalDate hireDay; /** * Employee 构造方法 * @param name 员工姓名 * @param salary 员工工资 * @param year 入职年 * @param month 入职月 * @param day 入职日 */ public Employee(String name, double salary, int year, int month, int day) { Objects.requireNonNull(name, "The name cannot be null"); this.name = name; this.salary = salary; hireDay = LocalDate.of(year, month, day); } /** * 获得员工姓名 * @return 用户姓名 */ public String getName() { return name; } /** * 获得员工工资 * @return 工资 */ public double getSalary() { return salary; } /** * 获得用户入职日期 * @return 入职日期 * @throws NullPointerException */ public LocalDate getHireDay() { return hireDay; } /** * 增加工资 * @param byPercent 百分比 */ public void raiseSalary(double byPercent) { double raise = salary * byPercent / 100; salary += raise; } @Override public boolean equals(Object otherObject) { // a quick test to see if the objects are identical if (this == otherObject) return true; // must return false if the explicit parameter is null if (otherObject == null) return false; // if the classes don't match, they can't be equal if (getClass() != otherObject.getClass()) return false; // now we know otherObject is a non-null Employee Employee other = (Employee) otherObject; // test whether the fields have identical values return Objects.equals(name, other.name) && salary == other.salary && Objects.equals(hireDay, other.hireDay); } @Override public int hashCode() { return Objects.hash(name, salary, hireDay); } @Override public String toString() { String str = "%s[name=%s, salary=%.2f, hireDay=%s]"; return String.format(str, getClass().getName(), name, salary, hireDay); } }
import java.util.Objects; public class Manager extends Employee { private double bonus; public Manager(String name, double salary, int year, int month, int day) { super(name, salary, year, month, day); this.bonus = 0; } public void setBonus(double bonus) { this.bonus = bonus; } public double getSalary() { double baseSalary = super.getSalary(); return baseSalary + bonus; } @Override public boolean equals(Object otherObject) { if (!super.equals(otherObject)) return false; Manager other = (Manager) otherObject; // super.equals checked that this and otherObject belong to the same class return bonus == other.bonus; } @Override public int hashCode() { return Objects.hash(super.hashCode(), bonus); } @Override public String toString() { return super.toString() + "[bonus=" + bonus + "]"; } }
public class Testing { public static void main(String[] args) { Employee alicel = new Employee("Alice Adams" , 75000 , 1987, 12, 15); Employee alice2 = alicel; Employee alice3 = new Employee("Alice Adams", 75000, 1987, 12, 15); Employee bob = new Employee("Bob Brandson" , 50000, 1989, 10, 1); System.out.println("alicel == alice2: " + (alicel == alice2)); System.out.println("alicel == alice3: " + (alicel == alice3)) ; System.out.println("alicel.equals(alice3): " + alicel.equals(alice3)); System.out.println("alicel.equals(bob): " + alicel.equals(bob)) ; System.out.println("bob.toString(): " + bob); Manager carl = new Manager("Carl Cracker", 80000 , 1987, 12, 15) ; Manager boss = new Manager("Carl Cracker", 80000 , 1987, 12, 15) ; boss.setBonus(5000); System.out.println("boss.toString(): " + boss); System.out.println("carl.equals(boss): " + carl.equals(boss)) ; System.out.println("alicel.hashCode(): " + alicel.hashCode()) ; System.out.println("alice3.hashCode(): " + alice3.hashCode()) ; System.out.println("bob.hashCode(): " + bob.hashCode()); System.out.println("carl.hashCode(): " + carl.hashCode()); } }
输出:
alicel == alice2: true alicel == alice3: false alicel.equals(alice3): true alicel.equals(bob): false bob.toString(): com.xiang117.corejava.Employee[name=Bob Brandson, salary=50000.00, hireDay=1989-10-01] boss.toString(): com.xiang117.corejava.Manager[name=Carl Cracker, salary=80000.00, hireDay=1987-12-15][bonus=5000.0] carl.equals(boss): false alicel.hashCode(): -808853550 alice3.hashCode(): -808853550 bob.hashCode(): -624019882 carl.hashCode(): -2004699436
- [bxd学习java基本点]13泛型类,泛型方法,当定义二种类型的泛型方法时,用迭代器的方法
- 【java学习记录】2.定义一个计算矩形面积、立方体和球体体积的类,该类完成计算的方法用静态方法实现
- 14. JAVA 枚举(Enum、类集EnumMap&EnumSet 、实现接口、定义抽象方法) ----- 学习笔记
- JAVA学习笔记1,基本语法,变量,数组,定义调用方法,输入输出
- Java学习-数组的定义及其基本方法语法(1)
- java学习笔记day04-方法的定义格式
- Java final 类和方法(学习 Java 编程语言 041)
- Java学习-050-AES256 之 java.security.InvalidKeyException: Illegal key size or default parameters 解决方法
- java中equals与hashCode还有tostring方法学习记录
- java学习笔记--基础知识--内部类---在方法中定义
- Java-day07 学习笔记 数组复制、排序及方法的定义、调用
- 多态Object类toString方法学习笔记ObjectDemo.java
- 【java学习记录】7.定义一个接口ArearInterface,其中包含一个方法,计算面积三角形、矩形、圆形的面积
- JAVA语言学习_04(类的toString()方法)
- java学习路线__基础入门向__方法的定义与使用__7
- [ Java学习 ] toString方法 和 equals方法
- java 二维数组的定义 与 二维数组输出的两种方法for each与Arrays.deepToString方法
- Java学习之面向对象(1.Object类,(1)toString方法,(2)equals方法,2.对象转型(casting),3.动态绑定与多态,4.抽象类(abstract),5.Final关键字)
- [bxd学习java基本点]13泛型类,泛型方法,当定义二种类型的泛型方法时,用迭代器的方法
- 在 Java 类中实现 hashCode 方法(学习 Java 编程语言 049)