1.Object概述: 類Object是類層次結構的根類。每個類都使用Object作為超類。所有對象(包括數組)都實現這個類的方法。
2.構造方法詳細信息:
Object只有一個無參構造方法,因為object中沒有屬性
public Object()
3.常用成員方法:
protected Object clone()
boolean equals(Object obj)
protected void finalize()
Class<?> getClass()
int hashCode()
String toString()
public final Class getClass():
從final看出子類不能被重寫, 任何一個對象它的 getClass() 行為是一致。
返回值是 Object 的運行時類型。返回值類型是Class: 類類型
Class概述:Class 類的實例表示正在運行的 Java 應用程序中的類和接口。枚舉是一種類,注解是一種接口。
Class類中有一個public String getName():返回該對象的運行時類的全限定名(包名.類名)。可以在得到getClass的方法返回值Class類的時候通過getName獲取當前正在運行的類名。
例如:
1 package com.cskaoyan.object; 2 public class ObjectDemo_02 { 3 public static void main(String[] args){ 4 Object obj=new Object(); 5 Class cl1=obj.getClass(); 6 String name1=cl1.getName(); 7 System.out.println("name1 = " + name1);//name1 = java.lang.Object 8 System.out.println("------------------------------------------" ); 9 Object obj2=new Student(); 10 Class cl2=obj2.getClass(); 11 String name2=cl2.getName(); 12 System.out.println("name2 = " + name2);//name2 = com.cskaoyan.object.Student 14 15 } 16 }
public int hashCode():
返回該對象的哈希碼值。
默認實現:這一般是通過將該對象的 內部地址 轉換 成一個整數來實現的
hashcode()的常規協定:
1) 一致性. 如果一個對象進行比較的信息沒有發生修改,那么在一次程序運行期間,它們的hash值要一致。
2) 相等性. 如果兩個對象通過 equals 比較是相等的,那么它們的 hashcode 也要相等。
3) 哈希碰撞概率低. 如果兩個對象不相等,那么它們的 hashcode 最好不相等,這個可以提高哈希 表的性能。
哈希碼值相關知識:
哈希方程:哈希函數可以把任意長度的輸入數據映射成一個固定長度的輸出結果,返回值就為哈希碼值
*MD4是麻省理工學院教授Ronald Rivest於1990年設計的一種信息摘要算法。它是一種用來測試信息完整性的密碼散列函數的實行。其摘要長度為128位。這個算法影響了后來的算法如MD5、SHA家族和RIPEMD等。
*MD5消息摘要算法(英語:MD5 Message-Digest Algorithm),一種被廣泛使用的密碼散列函數,可以產生出一個128位(16字節)的散列值(hash value),用於確保信息傳輸完整一致。MD5由美國密碼學家羅納德·李維斯特(Ronald Linn Rivest)設計,於1992年公開,用以取代MD4算法。
*SHA家族:安全散列算法(英語:Secure Hash Algorithm,縮寫為SHA)是一個密碼散列函數家族,是FIPS所認證的安全散列算法。能計算出一個數字消息所對應到的,長度固定的字符串(又稱消息摘要)的算法。且若輸入的消息不同,它們對應到不同字符串的機率很高。
一些常用的哈希算法:
public String toString(): (建議所有子類都重寫此方法。)
返回該對象的字符串表示。結果應是一個簡明但易於讀懂的信息表達式。
默認實現:return getClass().getName() + "@" + Integer.toHexString(hashCode());
例如:
1 public class ObjectDemo_04 { 2 public static void main(String[] args) { 3 Object obj=new Object(); 4 String s=obj.toString(); 5 System.out.println("s = " + s);//s = java.lang.Object@1540e19d 6 System.out.println(obj);//java.lang.Object@1540e19d 7 } 8 }
注意:直接打印對象,會默認調用toString()方法。
public boolean equals(Object obj):
指示其他某個對象是否與此對象"相等"。
默認實現: return (this == obj); 判斷兩個對象的地址值是否相等 (是否是同一個對象)
分兩種情況判斷是否需要重寫equals()方法:
實體類:
一個對象對應一個實體。沒有必要重寫 Object 中的 equals();
值類:
例如:String, Point(成員變量為為橫坐標和縱坐標),因為在現實生活中這種類型的類,當值都相同就可以看作同一個對象,所以需要重寫 equals 方法。
值類重寫方法需要將關鍵域進行比較:
例如:Rectangle(長方形類):
關鍵域:length, width
衍生域:area, perimeter
無關域:color
根據關鍵域進行比較
Point類重寫equals()方法例如:
1 @Override 2 //注意,因為是重寫Object類的equals方法,所以參數列表不能改變,還應該是Object object 3 public boolean equals(Object object){ 4 if(object instanceof Point){ 5 Point point=(Point) object; 6 return x==point.x&&y==point.y; 7 } 8 } 9 }
equals方法常規協定:
equals 方法在非空對象引用上實現相等關系:
自反性:對於任何非空引用值 x,x.equals(x) 都應返回true。
對稱性:對於任何非空引用值 x 和 y,當且僅當 y.equals(x) 返回true時,x.equals(y)才應返回 true。
傳遞性:對於任何非空引 用值 x、y 和 z,如果x.equals(y)返回 true,並且y.equals(z)返回 true,那么 x.equals(z) 應返回 true。
一致性:對於任何非空引用值 x 和 y,多次調用 x.equals(y) 始終返回 true 或始終返回 false,前提是對象上 equals 比較中所用的信息沒有被修改。
非空性:對於任何非空引用值 x,x.equals(null) 都應返回 false。
注意事項:當此方法被重寫時,通常有必要重寫hashCode方法,並協定相等對象,都要有相同的哈希碼。
用比較的元素作為根據來寫hashCode方法。
使用idea生成的equals方法有一個缺陷,子類和父類進行比較的時候,返回值為false違反了里氏替換原則(凡是能夠使用父類的地方都可以它的子類替換)。
protected void finalize() throws Throwable
概述:當垃圾回收器回收這個對象時,會自動調用此方法。子類重寫 finalize 方法,以釋放資源。
默認實現:什么都沒做,空實現。
finalize:
1. 可以自己調用, 該對象沒有被回收。
2. 當垃圾回收器回收這個對象時,會自動調用此方法。
3. 釋放資源最好不要放在 finalize() 里面。為什么?
原因是:垃圾回收線程是一個優先級低的線程,當一個對象變成垃圾后,並不會馬上被回 收,因此資源得不到立刻釋放。
怎么釋放資源呢?
try ... catch ... finally(異常處理)語句釋放資源
protected Object clone() throws CloneNotSupportedException
概述:創建並返回此對象的一個"副本".
這個方法是protected修飾的,只有類在同一個包中才能使用,而Object在lang包下,所以我們想要調用這個方法就必須去重寫這個方法。
但是如果重寫得方法不實現Cloneable
接口則會報出異常:CloneNotSupportedException。
Cloneable(空接口, 標記接口):
此類實現了 Cloneable 接口,以指示 Object.clone() 方法可以合法地對該類實例進行按字段復制。
如果在沒有實現 Cloneable 接口的實例上調用 Object 的 clone 方法,則會導致拋出CloneNotSupportedException異常。
一個接口沒有定義任何內容,叫做空接口,在Java中往往起標記作用。
淺拷貝和深拷貝:
淺拷貝:對基本數據類型進行值傳遞,對引用數據類型進行引用傳遞般的拷貝,此為淺拷貝。
深拷貝:對基本數據類型進行值傳遞,對引用數據類型,創建一個新的對象,並復制其內容,此為深拷貝。
深拷貝和淺拷貝的應用場景:
1.對於基本數據類型我們不需要考慮淺拷貝和深拷貝,使用等號便可復制值。
2.對於復合數據類型使用等號屬於淺拷貝,僅復制該字段值,如數組則復制地址,這個時候需要考慮是否使用需要深拷貝。
Java的默認實現是淺拷貝和深拷貝?
淺拷貝
舉例:
1 public class ObjectDemo7 { 2 public static void main(String[] args) throws CloneNotSupportedException { 3 // Object obj = new Object(); 4 // obj.clone(); 5 Student s1 = new Student("Henson_z", 18); 6 Student s2 = s1.clone(); 7 // System.out.println(s1.equals(s2)); 8 // System.out.println(s2); 9 // System.out.println(s1 == s2); 10 System.out.println(s1.getName().equals(s2.getName())); // true 11 System.out.println(s1.getName() == s2.getName()); // false 12 } 13 }
因為name 是String類型的是引用變量,從 System.out.println(s1.getName() == s2.getName()); // false中可以看出s1和s2的name是指向同一個變量的,所以java中的拷貝為淺拷貝
在java中怎么實現深拷貝?
對引用數據類型,創建一個新的對象,並復制其內容。
舉例:(單層關系的深拷貝)
//在Student重寫clone()方法時,name屬於String類型的成員變量,如果直接調用super.clone()(即Object類的clone方法)方法進行復制,只進行了淺拷貝
//所以對於name成員變量要創建一個新的對象,並復制內容
protected Student clone() throws CloneNotSupportedException { Student s = (Student) super.clone(); s.name = new String(name); return s; }
舉例:(多層關系的深拷貝)
1 package com.cskaoyan.object; 2 /* 3 對 FirstLevel 實現深拷貝。 5 分析: 6 1. 實現 cloneable 接口 7 2. 重寫 clone 方法。 8 */ 9 public class FirstLevel implements Cloneable{ 10 int a; 11 SecondLevel secondLevel; 12 13 @Override 14 protected FirstLevel clone() throws CloneNotSupportedException { 15 // return super.clone(); 16 FirstLevel fl = (FirstLevel) super.clone(); 17 // 對 SecondLevel 進行深拷貝不是 FirstLevel 的職責。 18 /*SecondLevel sl = new SecondLevel(); 19 sl.b = fl.secondLevel.b; 20 sl.s = new String(fl.secondLevel.s);*/ 21 SecondLevel clone = secondLevel.clone(); 22 fl.secondLevel = clone; 23 return fl; 24 } 25 }
1 package com.cskaoyan.object; 2 3 public class SecondLevel implements Cloneable{ 4 int b; 5 String s; 6 7 @Override 8 protected SecondLevel clone() throws CloneNotSupportedException { 9 SecondLevel sl = (SecondLevel) super.clone(); 10 sl.s = new String(s); 11 return sl; 12 } 13 }