在學習繼承的時候,提到過,所有的類都是直接或者間接地繼承Object類。由此可見,Object類是很重要的一個類。今天就來談談Object類。
類 Object 是類層次結構的根類。每個類都使用 Object 作爲超類。所有對象(包括數組)都實現這個類的方法。
下面來談談Object類中的方法。
構造方法
構造方法是公共的。可以創建對象。
getClass()方法
該方法是一個公共的final的方法。
- 方法 返回此 Object 的運行時類。返回的 Class 對象是由所表示類的 static synchronized 方法鎖定的對象。
- 可以通過Class類中的一個方法,獲取對象的真實類的全名稱。
public String getName();
舉例:
public class Demo {
public static void main(String[] args) {
Object o = new Object();
System.out.println(o.getClass());
}
}
結果:
class java.lang.Object
hashCode()方法
方法是公共的方法,返回值類型爲int類型。
- 方法返回該對象的哈希碼值。默認情況下,該方法會根據對象的地址來計算。支持此方法是爲了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。
- 不同對象的,hashCode()一般來說不會相同。但是,同一個對象的hashCode()值肯定相同。
- 不是對象的實際地址值,可以理解爲邏輯地址值。
舉例:
public class Demo {
public static void main(String[] args) {
Object o = new Object();
System.out.println(o.hashCode());
}
}
結果:
460141958
toString()方法
方法爲公共的方法,返回值類型爲String。
- 返回該對象的字符串表示。
源代碼:
public String toString() {
return getClass().getName() + “@” + Integer.toHexString(hashCode());
} - 它的值等於:
getClass().getName() + ‘@’ + Integer.toHexString(hashCode()) - 由於默認情況下的數據對我們來說沒有意義,一般建議重寫該方法。(怎麼重寫, 一般是將該類的所有的成員變量組成返回即可)
- 在代碼裏,直接輸出對應的名稱,就是調用對象的toString()方法。
舉例:
public class Demo {
public static void main(String[] args) {
Object o = new Object();
System.out.println(o);
}
}
結果:
java.lang.Object@1b6d3586
重寫toString()方法:
public class Demo {
public static void main(String[] args) {
Object o = new Student();
System.out.println(o);
}
}
class Student{
String name;
int age;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
重寫後的結果爲:
Student{name='null', age=0}
equals()方法
方法爲公共的方法,返回值類型爲boolean類型。
- 指示其他某個對象是否與此對象“相等”。
源代碼:
public boolean equals(Object obj) {
return (this == obj);
} - 默認情況下比較的是對象的引用是否相同。
- 由於比較對象的引用沒有意義,一般建議重寫該方法。一般用於比較成員變量的值是否相等。
==和equals()的區別:
- ==:是一個關係運算符,用於比較運算符的兩端是否相等。若爲比較運算符的兩端爲基本數據類型,則比較的是值是否相等;若爲對象,則比較的是對象的地址值是否相等。
- equals():是一個方法,默認比較的是兩個對象的地址值是否相等。
舉例:
public class Demo {
public static void main(String[] args) {
Object o = new Object();
Object o1 = new Object();
System.out.println(o.equals(o1));
}
}
結果:
false
重寫後的equals()方法:
public class Demo {
public static void main(String[] args) {
Student s1 = new Student("小明",20);
Student s2 = new Student("小明",20);
System.out.println(s1.equals(s2));
}
}
class Student {
String name;
int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
}
結果爲:
true
clone()方法
方法是受保護的,只能在本類、同一包下(子類和無關類)、不同包下(子類)三種情況下調用clone()方法。
- 由於clone()的權限修飾符是受保護的,在用的時候,需要讓該類重寫該方法,並把該方法的權限修飾符改爲public。
- 使用clone()方法採用的是淺克隆的方式。
對象淺克隆要注意的細節:
- 如果一個對象需要調用clone的方法克隆,那麼該對象所屬的類必須要實現Cloneable接口。
- Cloneable接口只不過是一個標識接口而已,沒有任何方法。
- 對象的淺克隆就是克隆一個對象的時候,如果被克隆的對象中維護了另外一個類的對象,這時候只是克隆另外一個對象的地址,而沒有把另外一個對象也克隆一份。
- 對象的淺克隆也不會調用到構造方法的。
舉例:
public class Demo2 {
public static void main(String[] args) throws CloneNotSupportedException{
Teacher teacher = new Teacher("張老師",35);
Teacher teacher1 = (Teacher) teacher.clone();
}
}
class Teacher extends Object implements Cloneable{
String name;
int age;
public Teacher(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public void show() {
System.out.println(name);
System.out.println(age);
}
}
teacher和teacher1指向的是一模一樣的內存空間,但兩個內存空間的地址值是不一樣的,即改變一個內存空間的變量值不會影響另一個空間的變量的值。
舉例:
public class Demo2 {
public static void main(String[] args) throws CloneNotSupportedException{
Teacher teacher = new Teacher("張老師",35);
teacher.show();
Teacher teacher1 = (Teacher) teacher.clone();
teacher1.name="劉老師";
teacher1.age=30;
teacher1.show();
}
}
class Teacher extends Object implements Cloneable{
String name;
int age;
public Teacher(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public void show() {
System.out.println(name);
System.out.println(age);
}
}
結果:
張老師
35
劉老師
30
針對 “對象的淺克隆就是克隆一個對象的時候,如果被克隆的對象中維護了另外一個類的對象,這時候只是克隆另外一個對象的地址,而沒有把另外一個對象也克隆一份。” 這種情況進行分析:
舉例說明:
public class Demo2 {
public static void main(String[] args) throws CloneNotSupportedException {
Teacher teacher = new Teacher("張老師", 35);
teacher.play.name = "打籃球";
teacher.show();
Teacher teacher1 = (Teacher) teacher.clone();
teacher1.name = "劉老師";
teacher1.age = 30;
teacher1.play.name = "踢足球";
teacher1.show();
teacher.show();
}
}
class Play {
String name;
public Play() {
}
}
class Teacher extends Object implements Cloneable {
String name;
int age;
Play play = new Play();
public Teacher(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public void show() {
System.out.println(name + play.name);
}
}
結果:
張老師打籃球
劉老師踢足球
張老師踢足球
分析:
對象的深克隆:採用IO流來實現。使用 ObjectOutputStream 將對象寫入文件中,然後再用ObjectInputStream讀取回來。