在 Object 中還有一個(gè)重要的 toString 方法睬关,它會(huì)返回表示對(duì)象值的一個(gè)字符串诱担。下面是一個(gè)典型的例子。Point 類的 toString方法將返回下面這樣的字符串:
?java.awt.Point[x=10电爹,y=20]
絕大多數(shù)(但不是全部)的 toString 方法都遵循這樣的格式:類的名字蔫仙,隨后是一對(duì)方括號(hào)括起來(lái)的字段值。下面是 Employee 類中的 toString 方法的實(shí)現(xiàn):
public class Employee {
private String name;
private double salary;
private LocalDate hireDay;
...
@Override
public String toString() {
return "Employee[name=" + name +
",salary=" + salary +
",hireDay=" + hireDay + "]";
}
}
實(shí)際上丐箩,還可以設(shè)計(jì)得更好一些摇邦。最好通過(guò)調(diào)用 getClass().getName() 獲得類名的字符串,而不要將類名硬編碼寫(xiě)到 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 方法也可以由子類調(diào)用施籍。
設(shè)計(jì)子類的程序員應(yīng)該定義自己的 toString 方法,并加入子類的字段概漱。如果超類使用了 getClass().getName()丑慎,那么子類只要調(diào)用 super.toString() 就可以了。例如,下面是 Manager 類中的 toString 方法:
public class Manager extends Employee {
private double bonus;
...
@Override
public String toString() {
return super.toString() +
"[bonus=" + bonus + "]";
}
}
現(xiàn)在立哑,Manager 對(duì)象將打印輸出如下所示的內(nèi)容:
?Manager[name=...,salary=...,hireDay=...] [bonus=...]
隨處可見(jiàn) toString 方法的主要原因是:只要對(duì)象與一個(gè)字符串通過(guò)操作符 “+” 連接起來(lái)夜惭,Java 編譯器就會(huì)自動(dòng)地調(diào)用 toString 方法來(lái)獲得這個(gè)對(duì)象的字符串描述。
提示: 可以不寫(xiě) x.toString()
铛绰,而寫(xiě)作 "" + x
诈茧。這條語(yǔ)句將一個(gè)空串與 x 的字符串表示(也就是 x.toString())相連接。與 toString 不同的是捂掰,即使 x 是基本類型敢会,這條語(yǔ)句照樣能夠執(zhí)行。
如果 x 是一個(gè)任意對(duì)象这嚣,并調(diào)用
?System.out.println(x)
println 方法就會(huì)簡(jiǎn)單地調(diào)用 x.toString()
鸥昏,并打印輸出得到的字符串。
Object 類定義了 toString 方法姐帚,可以打印對(duì)象的類名和散列碼吏垮。例如,調(diào)用:
?System.out.println(System.out);
將輸出:
?java.io.PrintStream@7852e922
得到這樣的結(jié)果原因是 PrintStream 類的設(shè)計(jì)者沒(méi)有覆蓋 toString() 方法罐旗。
警告: 令人煩惱的是膳汪,數(shù)組繼承了 Object 類的 toString 方法,更有甚者九秀,數(shù)組類型將采用一種古老的格式打印遗嗽。例如:
?int[] luckyNumger = {2, 3, 5, 7, 11, 13}
?String s = "" + luckyNumger;
會(huì)生成字符串 “[I@52af6cff”(前綴 [I 表明是一個(gè)整型數(shù)組)。補(bǔ)救的方法是調(diào)用靜態(tài)方法 Arrays.toString鼓蜒。代碼:
?String s = Arrays.toString(luckyNumger);
將生成字符串:
?[2, 3, 5, 7, 11, 13]
痹换。
要想打印多維數(shù)組(即,數(shù)組的數(shù)組)都弹,則需要調(diào)用 Arrays.deepToString 方法娇豫。
toString 方法是一種非常有用的調(diào)試工具。在標(biāo)準(zhǔn)類庫(kù)中缔杉,許多類都定義了 toString 方法锤躁,以便用戶能夠獲得一些有關(guān)對(duì)象狀態(tài)的有用信息。
像下面這樣顯示日志信息非常有益:
?System.out.println("Current position = " + position);
提示: 強(qiáng)烈建議為自定義的每一個(gè)類增加 toString 方法或详。這樣做不僅自己受益系羞,所有使用這個(gè)類的程序員也會(huì)從這個(gè)日志記錄支持中受益匪淺。
java.long.Object 1.0
- Class getClass()
返回包含對(duì)象信息的類對(duì)象霸琴。
- boolean equals(Object otherObject)
比較兩個(gè)對(duì)象是否相等椒振,如果兩個(gè)對(duì)象指向同一塊存儲(chǔ)區(qū)域,方法返回 true梧乘;否則方法返回 false澎迎。要在自定義的類中覆蓋這個(gè)方法庐杨。
- String toString()
返回表示對(duì)象值的字符串。要在自定義的類中覆蓋這個(gè)方法夹供。
java.lang.Class 1.0
- String getName()
返回這個(gè)類的名字灵份。
- Class getSuperclass()
以 Class 對(duì)象的形式返回這個(gè)類的超類信息。
示例代碼
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;
// 認(rèn)知日期
private LocalDate hireDay;
/**
* Employee 構(gòu)造方法
* @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