Object類介紹
Object類位于java.lang包,是所有Java類的根父類(唯一沒有父類的類),所有類的直接或者間接父類。Java中的每個類都是由這個類擴展而來。
java.lang包在使用的時候無需顯示導入,編譯時由編譯器自動導入。
Java認為所有的對象都具備一些基本的共性內容,這些內容可以不斷的向上抽取,最終就抽取到了一個最頂層的類中的,該類中定義的就是所有對象都具備的功能。
如果在類的聲明中未使用extends關鍵字指明其父類,則默認父類為Object類。
public class Test [extends Object]{ // 默認繼承了Object類
//...
}
接收任意引用類型的對象
既然Object類是所有對象的父類,則肯定所有的對象都可以向Object進行轉換,在這其中也包含了數組和接口類型,即:一切的引用數據類型都可以使用Object進行接收。
使用Object接收接口實例:
public class Test {
public static void main(String[] args) {
A ab = new B() ; // 為接口實例化
Object obj = ab ; // 對象向上轉型
A a = (A)obj ; // 對象向下轉型
a.print();
}
}
interface A { // 定義接口A
public void print() ; // 定義抽象方法
}
class B implements A { // 子類實現接口
public void print(){ // 覆寫接口中的抽象方法
System.out.println("test") ;
}
}
使用Object接收數組:
public class Test {
public static void main(String[] args) {
int[] array = {1, 3, 5, 7, 9} ; // 定義數組
Object obj = array ; // 使用Object接收數組
print(obj) ; // 傳遞數組引用
}
public static void print(Object o){ // 接收一個對象
if(o instanceof int[]) { // 判斷對象的類型
int x[] = (int[])o ; // 向下轉型
for(int i=0;i<x.length;i++){ // 循環(huán)輸出
System.out.print(x + "\t") ;
}
}
}
}
Object的主要方法
Object類中定義了一些有用的方法,由于是根類,所以這些方法都在其他類中存在,一般是進行了重載或者覆蓋,實現了各自自己的具體功能。
public boolean equals(Object obj)
Object類中的equlas()方法用來檢測兩個對象是否等價,查看Object源碼為:
public boolean equals(Object obj) {
return (this == obj);
}
equals()只能比較引用類型,其作用與“==”相同,比較是否指向同一個對象(其實內部比較的就是兩個對象地址)。對象比較的是引用,即對象在內存中的內存地址,而基本數據類型比較的是值。
用“==”進行比較時,符號兩邊的數據類型必須兼容(可自動轉換的基本數據類型除外),否則編譯出錯。
equals()方法需要具有如下特點:
自反性(reflexive):任何非空引用x,x.equals(x)返回為true。
對稱性(symmetric):任何非空引用x和y,x.equals(y)返回true當且僅當y.equals(x)返回true。
傳遞性(transitive):任何非空引用x和y,如果x.equals(y)返回true,并且y.equals(z)返回true,那么x.equals(z)返回true。
一致性(consistent):兩個非空引用x和y,x.equals(y)的多次調用應該保持一致的結果,(前提條件是在多次比較之間沒有修改x和y用于比較的相關信息)。
約定:對于任何非空引用x,x.equals(null)應該返回為false。
Student s1 = new Student();
Student s2 = new Student();
System.out.println(s1 == s2); // false
Student s3 = s1;
System.out.println(s3 == s1); // true
System.out.println(s1.equals(s2)); // false
System.out.println(s1.equals(s1)); // true
System.out.println(s1.equals(s3)); // true
當用equals()方法進行比較時,對類File、String、Date及包裝類(Wrapper Class)來說,是比較類型及內容而不考慮引用的是否是同一個對象;因為在這些類中重寫了Object類的equals()方法。下面就是String重寫的equals()方法:
// 重寫了Object類中的equlas()方法
public boolean equals(Object anObject) {
// 判斷兩個字符串的內存地址是否相等,如果相等,就說明這兩個字符串是同一個
if (this == anObject) {
return true;
}
// 判斷參數對象是不是String類型的
if (anObject instanceof String) {
// 如果是,就向上轉型成一個String對象
String anotherString = (String)anObject;
// 對字符串逐個字符進行比較,每個字符都相等,返回true
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1 != v2)
return false;
i++;
}
return true;
}
}
return false;
}
public int hashCode()
返回該對象的哈希碼值。哈希值是根據哈希算法計算出來的一個值。這個值和地址值有關,但不是實際地址值。
該方法用于哈希查找,可以減少在查找中使用equals的次數,重寫了equals方法一般都要重寫hashCode方法。這個方法在一些具有哈希功能的Collection中用到。
一般必須滿足obj1.equals(obj2)==true,可以推出obj1.hashCode()==obj2.hashCode(),但是hashCode相等不一定就滿足equals。不過為了提高效率,應該盡量使上面兩個條件接近等價。如果不重寫hashcode(),在HashSet中添加兩個equals的對象,會將兩個對象都加入進去。
// 對象不同,哈希值一般也不同
Student s1 = new Student();
System.out.println(s1.hashCode()); // 366712642
Student s2 = new Student();
System.out.println(s2.hashCode()); // 1829164700
System.out.println("-------");
public final Class getClass()
返回Object運行時類,也就是說是字節(jié)碼文件對象。
不可重寫,要調用的話,一般和getName()聯合使用,如getClass().getName()。
Student s = new Student();
// getClass方法會返回一個Class類的實例對象,然后調用Class類的getName()方法返回全路徑名
System.out.println(s.getClass().getName()); // com.zwj.objectdemo.Student
public String toString()
Object 類的 toString 方法返回一個字符串,該字符串由類名(對象是該類的一個實例)、at 標記符“@”和此對象哈希碼的無符號十六進制表示組成。換句話說,該方法返回一個字符串,它的值等于: getClass().getName() + ‘@’ + Integer.toHexString(hashCode())
// toString方法:返回對象的字符串表示
System.out.println(s.toString()); // com.zwj.objectdemo.Student@7852e922
//直接輸出對象的名稱其實就是調用了對象的toString方法
System.out.println(s); //com.zwj.objectdemo.Student@7852e922
protected void finalize()
當垃圾回收器確定不存在對該對象的更多引用時,由對象的垃圾回收器調用此方法,用于垃圾回收。但是具體什么時間調用此方法不確定。
Java允許在類中定義一個名為finalize()的方法。它的工作原理是:一旦垃圾回收器準備好釋放對象占用的存儲空間,將首先調用其finalize()方法。并且在下一次垃圾回收動作發(fā)生時,才會真正回收對象占用的內存。
關于垃圾回收,有三點需要記住:
1)對象可能不被垃圾回收。只要程序沒有瀕臨存儲空間用完的那一刻,對象占用的空間就總也得不到釋放。
2)垃圾回收并不等于“析構”。
3)垃圾回收只與內存有關。使用垃圾回收的唯一原因是為了回收程序不再使用的內存。
finalize()的用途:
無論對象是如何創(chuàng)建的,垃圾回收器都會負責釋放對象占據的所有內存。這就將對finalize()的需求限制到一種特殊情況,即通過某種創(chuàng)建對象方式以外的方式為對象分配了存儲空間。
不過這種情況一般發(fā)生在使用“本地方法”的情況下,本地方法是一種在Java中調用非Java代碼的方式。
protected Object clone()
創(chuàng)建并返回此對象的一個副本,需要重寫該方法。
要克隆的類去實現Cloneable接口 ,Cloneable接口是標記接口,實現該接口的類就可以實現對象的復制。
public class Student implements Cloneable{
private String name; // 姓名
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
我們來測試一下:
public class StudentTest{
public static void main(String[] args) throws CloneNotSupportedException {
// 創(chuàng)建顯示對象
Student s = new Student();
s.setName("zwj");
// 克隆學生對象
Student cloneStu = (Student) s.clone();
// 引用
Student s2 = s;
System.out.println(s.getName()); // zwj,
System.out.println(cloneStu.getName()); // zwj
System.out.println(s2.getName()); // zwj
s2.setName("爪哇菌");
System.out.println(s.getName()); // 爪哇菌
System.out.println(cloneStu.getName()); // zwj
System.out.println(s2.getName()); // 爪哇菌
}
}
由以上代碼代碼可以看出Clone()方法的使用比較簡單,使用時注意如下幾點即可:
什么時候使用shallow Clone,什么時候使用deep Clone,這個主要看具體對象的域是什么性質的,基本型別還是reference variable。
調用Clone()方法的對象所屬的類必須實現(implements )Clonable接口,否則在調用Clone方法的時候會拋出CloneNotSupportedException。
---------------------
【轉載】
作者:下班后的爪哇菌
原文:https://blog.csdn.net/lxxiang1/a ... 874?utm_source=copy
本文版權歸黑馬程序員JavaEE培訓學院所有,歡迎轉載,轉載請注明作者出處。謝謝!
作者:黑馬程序員JavaEE培訓學院
首發(fā):http://java.itcast.cn/?skc