11.JAVA-Object類之finalize(),clone(),toString()等方法覆寫
1.Object介紹
Object類是一個特殊的類,是所有類(包括數組,接口 )的父類,如果一個類沒有用extends明確指出繼承於某個類,那麽它默認繼承Object類,所以可以通過向上轉型的方法使用類型為Object的變量指向任意類型的對象。
- 本章主要實現覆寫Object類的clone(),toString()equals(),finalize()等最重要的方法。
2.覆寫finalize()
在之前我們學習析構方法時,便講過finalize().
參考之前學的finallize方法示例:3.JAVA-方法重載,類的封裝,構造/析構方法
從本章學習開始,才發現原來是通過覆寫Object類的finalize()實現的垃圾回收
3.覆寫clone()
如上圖所示,該方法是protected類型,不能在類外直接調用.該方法主要的功能是實現兩個對象深拷貝(兩個對象地址都是獨立的),我們平時寫的代碼"對象1 = 對象2"其實是淺拷貝(兩個對象地址是一致的,修改對象1便等於修改對象2).
3.1 註意事項
覆寫clone之前,我們需要實現Cloneable接口(該接口在java中自帶的,不需要自己寫),如果不實現的話,則調用clone時,將會報異常.並且覆寫clone時,可以將clone改為public類型,介紹如下所示:
3.2 覆寫Clone代碼如下
class Person implementsCloneable //實現Cloneble { public String name; public Person(String name) { this.name = name ; } public Object clone(){ //覆寫clone Person o = null; try{ o= (Person)super.clone(); }catch(CloneNotSupportedException e){ e.printStackTrace(); } return o; } } public class Test{ public static void main(String args[]) { Person p1=new Person("小王"); Person p2 = p1; p2.name = "小張"; System.out.println("p1 name:"+p1.name); System.out.println("p2 name:"+p2.name); System.out.println("通過Object超類下的clone方法實現深拷貝:"); p2 = (Person)p1.clone(); p2.name = "小王"; System.out.println("p1 name:"+p1.name); System.out.println("p2 name:"+p2.name); } }
運行打印:
如上圖所示,可以看到直接對對象進行賦值,其實是淺拷貝,而通過clone()則實現的深拷貝
4.覆寫toString()
覆寫toString()的意義在於:
- 方便打印一個對象的具體信息,並且由於是覆寫的Object類,所以通過向上轉換後,則可以確定參數的統一.方便程序設計.
4.1 覆寫toString代碼如下
class Teacher { String name; int age; Teacher(String name,int age) { this.name = name; this.age = age; } public String toString() { return "老師名字:"+name+" 年齡:"+age; } } class Student { String name; String clas; Student(String name,String clas) { this.name = name; this.clas = clas; } public String toString() { return "學生名字:"+name+" 班級:"+clas; } } public class Test { public static void printDesc(Object obj) //打印描述 { System.out.println(obj.toString()); } public static void main(String args[]){ printDesc(new Teacher("李芳芳",24)); //向上轉型 printDesc(new Student("小明","初1-6班"));//向上轉型 } }
運行打印:
從上面代碼可以看到, 我們直接通過Object參數,便兼容了不同類的一致性
5.覆寫equals()
覆寫equals()的意義和toString()類似,主要是方便程序設計,並且通過equals()可以判斷對象是否相同.
覆寫equals()時,則需要判斷的有:
- 兩個對象地址是否相同、
- 對象是否為NULL、
- 兩個對象是否為相同類、
- 兩個對象的內容是否一致...
由於代碼很簡單,就不寫了.
6.覆寫hashCode()
6.1 Object類中的hashCode()和String類中的hashCode()
hashCode()用來獲取一個對象的哈希值,一般用來比較用的,而 Object類中的hashCode是返回對象在內存中地址轉換成的一個int值(實際就是地址值)。所以如果沒有重寫hashCode方法,任何對象的hashCode都是不相等的。
而對於String類中的hashCode方法,則根據對象自身的字符串內容來生成一個哈希值
6.2 參考示例如下所示:
class Student //未覆寫hashCode()的類 { String name; String clas; Student(String name,String clas) { this.name = name; this.clas = clas; } } public class Test { public static void main(String args[]){ Student st1 = new Student("小明","初1-6班"); Student st2 = new Student("小明","初1-6班"); System.out.println("st1:"+st1.hashCode()); System.out.println("st2:"+st2.hashCode()); String str1 = new String("小明 初1-6班"); String str2 = new String("小明 初1-6班"); System.out.println("str1:"+str1.hashCode()); System.out.println("str2:"+str1.hashCode()); } }
運行打印:
如上圖可以看到,對於相同內容的st1和st2而言,它們的hash值完全不同,如果我們將它們使用到Hashtable之類的哈希表上的話,將會出現 st1和st2內容相同,卻存儲在表裏的位置卻不同,
並且比較st1和st2相等時,也會出現false.
因為判斷哈希表裏兩個對象相等時,也會先判斷hash值是否相等,再判斷是否equals().
目的:hash值能夠加快判斷速度,但是hash值也有可能值相同從而出現沖突,所以如果兩個對象相等時,會再次判斷一次equals().
6.3 接下來重寫修改上面類覆寫hashCode()
class Student { String name; String clas; Student(String name,String clas) { this.name = name; this.clas = clas; } public int hashCode() //覆寫hashCode() { return name.hashCode()*2+clas.hashCode(); } }
運行打印:
未完待續.
11.JAVA-Object類之finalize(),clone(),toString()等方法覆寫