java.lang.Object是JAVA中所有類層次結構的根,所有的對象包括數組都實現了Object類的方法。
構造器:
public Object()
方法:
1. clone()
該方法需要實現Cloneable接口,重寫clone方法才能使用;
該方法會返回一個一摸一樣的對象,但是該對象不等同於原來的對象
x.clone() != x;
例如:
class Person implements Cloneable{
public String name;
public int age;
public Person(String name,int age ) {
this.age = age;
}
public Person clone() throws CloneNotSupportedException {
return (Person) super.clone();
}
}
public class Run{
public static void main(String[] args) throws CloneNotSupportedException {
Person p1 = new Person("小明",18);
Person p2 = p1.clone();
Person p3 = p1;
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
System.out.println(p1==p2);
System.out.println(p1==p3);
}
}
輸出:
//後面的只是人爲加的註解
366712642 //p1的hashCode
1829164700 //p2的hashCode
false //p1==p2
true //p1==p3
該方法是完全克隆了一個對象,並不僅僅是創建一個引用指向原來的對象。
但是需要注意,如果一個對象裏面的屬性包含引用的話,那麼該引用屬性也要實現Cloneable接口,因爲引用在內存中存儲的只是引用對象的hash值,克隆也只是克隆了hash值而已。
例如:
class Body{
public int BODYNUM = 4;
}
class Person implements Cloneable{
public String name;
public int age;
public Body body; //body屬性
public Person(String name,int age,Body body ) {
this.name = name;
this.age = age;
this.body = body;
}
public Person clone() throws CloneNotSupportedException {
return (Person) super.clone();
}
}
public class Run{
public static void main(String[] args) throws CloneNotSupportedException {
Person p1 = new Person("小明",18,new Body());
Person p2 = p1.clone();
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
System.out.println(p1==p2);
System.out.println(p1.body==p2.body);
p1.body.BODYNUM = 5;
System.out.println(p2.body.BODYNUM);
}
}
輸出:
366712642
1829164700
false //p1==p2
true //p1.body==p2.body
5 //p2的body屬性的一個值
可以看到,修改了p1的body屬性,p2的 body屬性也修改了。那麼就說明了,其實p1的body跟p2的body實質上還是同一個,因爲克隆的只是引用值而已,引用還是指向內存中同一個區域。
這個時候,Body屬性必須也實現Cloneable接口
例如:
class Body implements Cloneable{
public int BODYNUM = 4;
public Body clone() throws CloneNotSupportedException {
return (Body) super.clone();
}
}
class Person implements Cloneable{
public String name;
public int age;
public Body body;
public Person(String name,int age,Body body ) {
this.name = name;
this.age = age;
this.body = body;
}
public Person clone() throws CloneNotSupportedException {
Person person = (Person) super.clone();
person.body = body.clone(); //可以認爲將包含引用的屬性都要自己拷貝一遍
return person;
}
}
public class Run{
public static void main(String[] args) throws CloneNotSupportedException {
Person p1 = new Person("小明",18,new Body());
Person p2 = p1.clone();
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
System.out.println(p1==p2);
System.out.println(p1.body==p2.body);
p1.body.BODYNUM = 5;
System.out.println(p2.body.BODYNUM);
}
}
輸出:
366712642
1829164700
false
false //p1的body與p2的body不一樣了
4 //修改p1的body後,p2並未受到修改
這也就是傳說中的深拷貝,即在重寫clone方法中拷貝所有的引用屬性;
2. equals(Object obj)
該方法具有如下特性:
- 自反性:對於任何非空引用x; x.equals(x)應當返回true;
- 對稱性:對於任何非空引用x,y;x.equals(y)返回true當且僅當y.equals(x)返回true;
- 傳遞性:對於任何非空引用 x,y,z,如果x.equals(y)=true,y.equals.(z)=true,那麼x.equals(z)=true
- 一致性:對於任何非空引用 x,y,調用多次x.equals(y)返回結果應該相同;
- 對於任何非空引用x,xequals(null)應該返回false;
源碼如下:
public boolean equals(Object obj) {
return (this == obj);
}
很多都會重寫該方法。
3. finalize()
是終止函數,JVM在進行垃圾回收的時候首先會調用這個函數,當某個對象被確認爲無用信息的時候,那麼就會釋放該對象的內存,但是不一定有效。
一般人爲不使用該方法。
class Person{
//重寫了Object類的finalize方法,當Person類被回收的時候首先調用該方法
public void finalize() throws Throwable{
System.out.println("回收前調用");
}
}
public class Run {
public static void main(String[] args) {
Person p = new Person();
p = null;
System.gc();
}
}
輸出:
回收前調用
表明gc的時候調用了Person類的finalize方法
但是需要注意,只有p沒有指向的時候,即被認爲是無用信息的時候纔會被回收,如果去掉上面的p=null,那麼還是不會有輸出。
4. getClass()
返回該對象運行時的類。
例如:
public class Run{
public static void main(String[] args) throws CloneNotSupportedException {
String a = "a";
System.out.println(a.getClass());
}
}
輸出:
class java.lang.String
5. hashCode()
該方法返回對象的hash值,具有如下特點:
- 同一對象調用多次該方法應該返回相同值
- 如果兩個對象通過equals方法返回true,那麼調用hashCode方法應該返回相同hash值
- 不是一定要“兩個對象通過equals方法返回true,那麼調用hashCode方法應該返回相同hash值”,但是通常應該這麼做,提高HashTable的性能
6. notify()
該方法喚醒在此同步監視器上等待的一個線程,如果有多個線程等待,則隨機喚醒一個。
- 如果在synchronized修飾的同步方法中使用,則可以直接使用該方法,因爲this就是同步監視器
- 如果在synchronized修飾的同步代碼塊中使用,則使用括號中的同步監視器來調用該方法。
7. notifyAll()
該方法喚醒在此同步監視器上等待的所有的線程。
8. toString()
該方法將任何對象轉換爲字符串類型
返回getClass().getName() + '@' + Integer.toHexString(hashCode())
例如:
public class Run {
public static void main(String[] args) {
Run r = new Run();
System.out.println(r.toString());
System.out.println(r.toString() instanceof String);
}
}
輸出:
hello.Run@15db9742
true
9. wait()
該方法將當天線程進入等待,直到有其他線程喚醒它。