日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Java 的toString() 和 equals()函数简单介绍

發(fā)布時間:2025/3/20 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 的toString() 和 equals()函数简单介绍 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

toString() 和 equals() 都是java面試中經(jīng)常問到的地方.

特別是1條經(jīng)典問題:? equals 和 "==" 的區(qū)別...


本文就從簡單介紹下這兩個object中的函數(shù).


一. toString()函數(shù)

我們首先看1個簡單的代碼例子:

package Object_kng.Object_baseMethod;class Ob_1{}public class Ob_tostring_1{public static void f(){Ob_1 a = new Ob_1();System.out.printf("%s\n", a.toString());//System.out.printf("%s\n", a); //ok same as below//System.out.println(a); //ok same as below//System.out.printf("%s\n", a.getClass().getName());//System.out.printf("%s\n", a.getClass().toString());} }

上面的例子定義了1個空的類 Ob_1. 在下面的啟動類中首先實例化類Ob_1 的一個對象.? 然后調(diào)用了a.toString()函數(shù).

上面代碼是能正確編譯和執(zhí)行的.


問題是既然Ob_1是1個空類, 里面并沒有定義toString()這個函數(shù), 為何還能調(diào)用呢.


1.1 java中所有的類都默認繼承基類Object.

原因很簡單, 因為Ob_1的toString()方法是繼承自類Object的.?

Java中所有類都是基類Object的派生子孫類.

如果1個類A在定義中沒有指明繼承哪個類, 那么類A就繼承了類Object!

如果類A extends B呢,? 因為B肯定也是Object類的子孫類, 所以無論如何類A肯定是基類Object的派生類or子孫類.


1.2 toString()是類Object內(nèi)定義的一個方法.

打開jdk api文檔, 我們可以查到toString()函數(shù)是如下介紹的:


toString

public String toString()
返回該對象的字符串表示。通常,toString 方法會返回一個“以文本方式表示”此對象的字符串。結(jié)果應是一個簡明但易于讀懂的信息表達式。建議所有子類都重寫此方法。
Object 類的 toString 方法返回一個字符串,該字符串由類名(對象是該類的一個實例)、at 標記符“@”和此對象哈希碼的無符號十六進制表示組成。換句話說,該方法返回一個字符串,它的值等于:

getClass().getName() + '@' + Integer.toHexString(hashCode())
?
返回:
該對象的字符串表示形式。


根據(jù)上面的的介紹, 我們簡單地得出如下的信息:

1. toString()函數(shù)返回1個String對象.

2. toString()函數(shù)可以被重寫, 而且jdk介紹中建議我們?yōu)樗蓄愔貙戇@個方法.

3. 不重寫這個方法的話, 返回值是 getClass().getName() + '@' + Integer.toHexString(hashCode())

4. toString()不是靜態(tài)方法, 必須實例化對象才能調(diào)用.


1.3 不重寫 toString()方法, 其返回值解釋

例如上面的代碼是沒有重寫toString()方法的.

執(zhí)行結(jié)果如下:

[java] Object_kng.Object_baseMethod.Ob_1@19c8f4

Object_kng.Object_baseMethod.Ob_1@19c8f45 就是a.toString()的返回值.

根據(jù)上面的解析, 我們得知

Object_kng.Object_baseMethod.Ob_1 是由? a.getClass().getName() 來的.? 這里實際上是類Ob_1的完整類名(包括所在包名).

而19c8f45 是 Integer.toHexString(a.hashCode()) 獲得的.


1.3.1 getClass()方法

這里順便解析一下getClass(),? getClass()方法也是屬于基類Object的1個方法, 它返回的是1個對象所屬的運行時類.

至于什么是運行時呢, 就是那個對象引用當前狀態(tài)指向的對象的所屬類.? 這個跟多態(tài)有關(guān).

本人語言表達能力有限, 還是用例子說明的吧:

package Object_kng.Object_baseMethod;class Ob_2{}class Ob_3 extends Ob_2{}public class Ob_getclass_1{public static void f(){Ob_2 a = new Ob_2();System.out.printf("%s\n", a.getClass());a = new Ob_3();System.out.printf("%s\n", a.getClass());} }
本例子有兩個空類, 其中Ob_3 繼承自 Ob_2

下面首先實力化1個Ob_2 的對象a, 然后輸出a.getClass() (實際上輸出a.getClass().toString())

然后把引用a 指向 Ob_3 的另1個對象(多態(tài)), 然后再輸出1次a.getClass().


執(zhí)行結(jié)果:

[java] class Object_kng.Object_baseMethod.Ob_2 [java] class Object_kng.Object_baseMethod.Ob_3

可以見到兩次輸出是不同的, 第一次是Ob_2, 第二次是Ob_3.

也就是說運行時類不是指 引用a是屬于哪個類, 而是指a 內(nèi)存指向的對象屬于哪個類, 這個需要多態(tài)的知識.


至于getClass().getName()就是獲取當前運行時類的完整類名了.


1.3.2 Integer.toHexString(a.hashCode())

那么"@"后面那串字符是什么呢, 實際上它是該對象的hash碼的16進制表示.

java中,每1個對象都有1個唯一的hashcode, 它跟這個對象的內(nèi)存地址有關(guān).


1.4 重寫方法的1個簡單例子:

package Object_kng.Object_baseMethod;class Point_1{private int x;private int y;public Point_1(int x, int y){this.x = x;this.y = y;}public String toString(){return "[" + x +"," + y +"]" ;} }public class Ob_tostring_2{public static void f(){Point_1 a = new Point_1(2,4);System.out.printf("%s\n", a.toString());System.out.printf("%s\n", a); //ok same as belowSystem.out.println(a); //ok same as below} }

上面定義了1個關(guān)于點的類, 有x, y的兩個int類型成員(坐標)

然后重寫了toString()方法. 不在輸出類名和hashcode, 改成輸出x和y的值, 并左一定的格式化.


輸出如下:

[java] [2,4] [java] [2,4] [java] [2,4]

1.5 重寫方法toString()方法的好處:

1. 方便自定義輸出對象的信息.?

?? 而原來的運行時類名和hashcode有可能不是我們需要的.


2. 由上面例子中, System.out.prinft(), 和 System.out.println()里面的參數(shù)只放對象名a的話, 實質(zhì)上會自動調(diào)用a.toString().

?? 這樣在coding當中就可以利用這兩個函數(shù)方便調(diào)試.


3. 實際上肯定java的自帶的類都重寫了toString()方法, 例如java.util.Date 日期這個類

1.6 toString()方法的一些小結(jié).

通過上面的例子, 我相信讀者最起碼清楚如下1點:

toString()是定義在類Object的1個非靜態(tài)方法.

這意味這個方法必須需要1個已實例化對象才能調(diào)用.


也就是為什么我們定義1個整形變量 int x時, 不能利用x.toString()方法把x轉(zhuǎn)化為字符串.

因為x只是1個基本變量, 而不是1個對象啊.



二.equals()函數(shù)

2.1 "==" 符號比較的是指向?qū)ο蟮膬?nèi)存地址


下面開始講另1個函數(shù)equals(), 在這之前我們看一下,另1個判斷是否相等的符號"=="

接下來又是1個例子:

package Object_kng.Object_baseMethod;class Ob_4{private int id;private String name;public Ob_4(int id, String name){this.id = id;this.name = name;} }public class Ob_equal_1{public static void f(){Ob_4 a = new Ob_4(1,"Kent");Ob_4 a2 = new Ob_4(1,"Kent");System.out.println((a == a2));a2 = a;System.out.println((a == a2));} }

輸出結(jié)果:

[java] false [java] true


上例子中定義了類Ob_4, 它有兩個成員id 和 name.

下面啟動類中,實例化了類Ob_4的兩個對象a 和 a2, a和a2擁有相同的id和name成員.


但是用 "==" 來比較a 和 a2的話, 它們兩者不相等的, 返回了false

接下來執(zhí)行a2 = a; 這個語句意思就是把引用a2 指向a所指向的對象, 這樣的話a2 和 a就指向Heap區(qū)的同一塊地址了.

再用"==" 比較a 和 a2的話,就返回了true.




由此可見, 用"=="來比較兩個對象的話, 實際是比較對象是否hashcode(), 只有兩個對象"完全"相同, 才會返回true.



2.2 equals默認比較的是指向?qū)ο蟮膬?nèi)存地址

實際上equals()也是基類Object的一個方法.

public boolean equals(Object obj)


由此可見:

1. 非靜態(tài)方法, 必須利用已實例化對象調(diào)用.

2. 返回boolean類型

3. 需要1個對象(Object)參數(shù),? 由于Object是java里所有其他類的超類, 這里也是運用了多態(tài).

4. 冇final關(guān)鍵字, equals方法可以被重寫.


我們將上面的代碼改一下, 將" == " 改成 equals:

package Object_kng.Object_baseMethod;class Ob_5{private int id;private String name;public Ob_5(int id, String name){this.id = id;this.name = name;} }public class Ob_equals_2{public static void f(){Ob_5 a = new Ob_5(1,"Kent");Ob_5 a2 = new Ob_5(1,"Kent");System.out.println((a.equals(a2)));a2 = a;System.out.println((a.equals(a2)));} }
輸出:

[java] false [java] true
見到輸出結(jié)果跟上面例子是一樣的, 所以基類Object的equals方法也是比較內(nèi)存的地址.


實際上equals()方法在基類Object的源代碼如下:

public boolean equals(Objectobj){

??? return (this == obj)

}

也就是equals調(diào)用了 "==", 基本上是等價的.

2.3 equals 和 " == " 并非比較對象的hashCode().

因為hashCode()跟內(nèi)存地址有關(guān), 所以也有人講equals 和 "=="比較的是對象的hashCode().


但這種說法是錯誤的, 因為hashCode()也是基類Object的方法, 也可以重寫.

我們來嘗試重寫hashCode()方法, 來證明觀點:

package Object_kng.Object_baseMethod;class Ob_6{private int id;private String name;public Ob_6(int id, String name){this.id = id;this.name = name;} public int hashCode(){return 1;} }public class Ob_equals_3{public static void f(){Ob_6 a = new Ob_6(1,"Kent");Ob_6 a2 = new Ob_6(2,"David");[System.out.println(a);System.out.println(a2);System.out.println((a.equals(a2)));System.out.println((a == a2));a2 = a;System.out.println((a.equals(a2)));System.out.println((a == a2));} }

輸出:

[java] Object_kng.Object_baseMethod.Ob_6@1[java] Object_kng.Object_baseMethod.Ob_6@1[java] false[java] false[java] true[java] true

上面例子中, 我們在類Ob_6里重寫了hashCode的方法, 都返回1.

下面實例化兩個對象a 和 a2, 而且兩個對象的 id, name成員都不一樣.

但是輸出對象信息(toString()) 方法, 見到@后面的數(shù)字都是1, 也就是它們的hashCode已經(jīng)相等.

但是后面的比較還是跟之前的例子一樣.

也就證明了 equals默認情況下 和 "=="都是比較對象的內(nèi)存地址, 而非hashCode().




2.4 重寫equals()方法.

但是實際生產(chǎn)中, 我需要比較兩個不同的對象, 如果兩者的所有成員相等, 我們就認為兩者相等.

這是我們就可以重寫equals()方法, 改變它的機制以適用我們的業(yè)務需要.


最常見的改寫方法:

package Object_kng.Object_baseMethod;class Ob_7{private int id;private String name;public Ob_7(int id, String name){this.id = id;this.name = name;} public boolean equals(Object obj){Ob_7 ob;try{ob = (Ob_7)obj;}catch(ClassCastException e){System.out.printf("warning: the object is not belonged to Class Ob_7!!\n");return false;}catch(Exception e){e.printStackTrace();return false;}if (this.id == ob.id && this.name == ob.name){return true;}return false;} }public class Ob_equals_4{public static void f(){Ob_7 a = new Ob_7(1,"Kent");Ob_7 a2 = new Ob_7(1,"Kent");Ob_7 a3 = new Ob_7(2,"David");System.out.println((a.equals(a2)));System.out.println((a.equals(a3)));System.out.println((a.equals(new Ob_6(1,"kent"))));a2 = a;System.out.println((a.equals(a2)));} }
這個例子在類Ob_7 中重寫了equals方法.

注意,重寫這個方法涉及了多態(tài)的知識, 必須將形參強制轉(zhuǎn)化為對應的類, 才可以比較成員.

為防止傳錯了其他類的對象的異常, 最好加上try{}語句來捕捉.


輸出結(jié)果:

符合我們的需要了, 只要id和name相等, 我們就認為這兩個對象相等:

[java] hello ant, it's the my meeting with ant![java] true[java] false[java] warning: the object is not belonged to Class Ob_7!![java] false[java] true

2.5 Java里有一些自帶的類也重寫了equals()方法.

最明顯的例子就是String類. 下面例子:

package Object_kng.Object_baseMethod;public class Ob_equals_5{public static void f(){String s1 = "abc";String s2 = new String("abc");System.out.println((s1.equals(s2)));System.out.println((s1 == s2));} }

輸出:

[java] true[java] false
上面定義了兩個字符串對象, 值都是"abc"

用equals比較兩者是相等的.

用 "==" 則不等.

由此可見String類改寫了equals方法, 當然更可能是String的其中1個超類改寫了equals方法.


2.5 Java里equals 和 "==" 的區(qū)別

以后大家可以這樣回答面試官:

1. "==" 可以比較基本類型(如 int 和 boolean)或?qū)ο?

2. equals是對象的非靜態(tài)方法, 只能用于比較對象, 不能比較基本類型.

3. "==" 用于對象時, 比較的是對象內(nèi)存地址, equals() 通常情況下也是會比較內(nèi)存地址.

4. 一些類如String() 改寫了equals()方法, 比較的是String對象的值, 而不是內(nèi)存地址.

5. 我們可以改寫equals()方法, 根據(jù)需要來比較兩個對象.







































總結(jié)

以上是生活随笔為你收集整理的Java 的toString() 和 equals()函数简单介绍的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。