Java Object
一、什么是Java Object
Java Object 類是所有類的父類,也就是說 Java 的所有類都繼承了 Object,子類可以使用 Object 的所有方法。(得了,就是Object就是所有類的爸爸)
Object 類位于 java.lang 包中,編譯時(shí)會(huì)自動(dòng)導(dǎo)入,我們創(chuàng)建一個(gè)類時(shí),如果沒有明確繼承一個(gè)父類,那么它就會(huì)自動(dòng)繼承 Object,成為 Object 的子類。
Object 類可以顯示繼承,也可以隱式繼承,以下兩種方式時(shí)一樣的:
顯示繼承:
public class Test extends Object{
}
隱式繼承:
public class Test{
}
下面我們來分析一下Object的源碼:
package java.lang;
public class Object {
private static native void registerNatives();
static {
registerNatives();
}
//獲取對(duì)象的運(yùn)行時(shí)對(duì)象的類
public final native Class<?> getClass();
//獲取對(duì)象的 hash 值
public native int hashCode();
//比較兩個(gè)對(duì)象是否相等
public boolean equals(Object obj) {
return (this == obj);
}
//創(chuàng)建并返回一個(gè)對(duì)象的拷貝
//clone 方法是淺拷貝,對(duì)象內(nèi)屬性引用的對(duì)象只會(huì)拷貝引用地址,而不會(huì)將引用的對(duì)象重新分配內(nèi)存,相對(duì)應(yīng)的深拷貝則會(huì)連引用的對(duì)象也重新創(chuàng)建。
//淺克隆復(fù)制出來的對(duì)象的所有變量都含有與原來的對(duì)象相同的值,而所有的對(duì)其他對(duì)象的引用仍然指向原來的對(duì)象。也就是說,克隆之后的對(duì)象和之前的對(duì)象仍存在一些關(guān)聯(lián),克隆程度不高,因此也被稱為淺克隆。
//而深克隆復(fù)制出來的所有變量都含有與原來的對(duì)象相同的值,那些引用其他對(duì)象的變量將指向復(fù)制出來的新對(duì)象,而不再是原有的那些被引用的對(duì)象。換言之,深復(fù)制把要復(fù)制的對(duì)象所引用的對(duì)象都復(fù)制了一遍。
protected native Object clone() throws CloneNotSupportedException;
//返回對(duì)象的字符串表示形式
public String toString() {
return getClass().getName() "@" Integer.toHexString(hashCode());
}
//喚醒在該對(duì)象上等待的某個(gè)線程
public final native void notify();
public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException {
if (timeout < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos > 0) {
timeout ;
}
wait(timeout);
}
public final void wait() throws InterruptedException {
wait(0);
}
//當(dāng) GC (垃圾回收器)確定不存在對(duì)該對(duì)象的有更多引用時(shí),由對(duì)象的垃圾回收器調(diào)用此方法。
protected void finalize() throws Throwable { }
}
二、Object類的方法
1、創(chuàng)建并返回一個(gè)對(duì)象的拷貝protected Object clone()
**
* @Description: $ clone()案例
* @Author: dyq
* @Date: $2021年2月4日
*/
public class CloneTest implements Cloneable {
// 聲明變量
String name;
int age;
public static void main(String[] args) {
// 創(chuàng)建對(duì)象
CloneTest obj1 = new CloneTest();
// 初始化變量
obj1.name = "科隆";
obj1.age = 20;
// 打印輸出
System.out.println(obj1.name); // 科隆
System.out.println(obj1.age); //20
try {
// 創(chuàng)建 obj1 的拷貝
CloneTest obj2 = (CloneTest) obj1.clone();
// 使用 obj2 輸出變量
System.out.println("clone后:");
System.out.println(obj2.name); // 科隆
System.out.println(obj2.age); //20
} catch (Exception e) {
System.out.println(e);
}
}
}
結(jié)果輸出:
科隆
20
clone后:
科隆
20
clone 方法是淺拷貝 ,對(duì)象內(nèi)屬性引用的對(duì)象只會(huì)拷貝引用地址,而不會(huì)將引用的對(duì)象重新分配內(nèi)存,相對(duì)應(yīng)的深拷貝則會(huì)連引用的對(duì)象也重新創(chuàng)建。 那么淺克隆跟深克隆有什么區(qū)別? 淺克隆復(fù)制出來的對(duì)象的所有變量都含有與原來的對(duì)象相同的值,而所有的對(duì)其他對(duì)象的引用仍然指向原來的對(duì)象。也就是說,克隆之后的對(duì)象和之前的對(duì)象仍存在一些關(guān)聯(lián),克隆程度不高,因此也被稱為淺克隆。 而深克隆復(fù)制出來的所有變量都含有與原來的對(duì)象相同的值,那些引用其他對(duì)象的變量將指向復(fù)制出來的新對(duì)象,而不再是原有的那些被引用的對(duì)象。換言之,深復(fù)制把要復(fù)制的對(duì)象所引用的對(duì)象都復(fù)制了一遍。
2、比較兩個(gè)對(duì)象是否相等 boolean equals(Object obj)
Object equals() 方法用于比較兩個(gè)對(duì)象是否相等 。
equals() 方法比較兩個(gè)對(duì)象,是判斷兩個(gè)對(duì)象引用指向的是同一個(gè)對(duì)象,即比較 2 個(gè)對(duì)象的內(nèi)存地址是否相等。
注意 :如果子類重寫了 equals() 方法,就需要重寫 hashCode() 方法,比如 String 類就重寫了 equals() 方法,同時(shí)也重寫了 hashCode() 方法。
該方法返回值為布爾型,則如果兩個(gè)對(duì)象相等返回 true,否則返回 false。
案例:
/**
* @Description: equals()案例$
* @Author: dyq
* @Date: 2021年2月4日$
*/
public class equalsTest {
public static void main(String[] args) {
// Object 類使用 equals() 方法
// 創(chuàng)建兩個(gè)對(duì)象
Object obj1 = new Object();
Object obj2 = new Object();
// 判斷 obj1 與 obj2 是否相等
// 不同對(duì)象,內(nèi)存地址不同,不相等,返回 false
System.out.println(obj1.equals(obj2)); // false
// obj1 賦值給 obj3
// String 重寫了 equals() 方法
// 對(duì)象引用,內(nèi)存地址相同,相等,返回 true
Object obj3 = obj1;
System.out.println(obj1.equals(obj3)); // true
// String 類使用 equals() 方法
// 創(chuàng)建兩個(gè)對(duì)象
String obj4 = new String();
String obj5 = new String();
// 判斷 obj4 與 obj5 是否相等
// 初始化的兩個(gè)對(duì)象都為 null,所以是相等,返回 true
System.out.println(obj4.equals(obj5)); // true
// 給對(duì)象賦值
obj4 = "哥哥";
obj5 = "哥";
// 判斷 obj4 與 obj5 是否相等
// 兩個(gè)值不同,內(nèi)存地址也不同,所以不相等,返回 false
System.out.println(obj4.equals(obj5)); // false
}
}
結(jié)果:
false
true
true
false
3、當(dāng) GC (垃圾回收器)確定不存在對(duì)該對(duì)象的有更多引用時(shí),由對(duì)象的垃圾回收器調(diào)用此finalize() 方法。
Object finalize() 方法用于實(shí)例被垃圾回收器回收的時(shí)觸發(fā)的操作。
在GC準(zhǔn)備釋放對(duì)象所占用的內(nèi)存空間之前,它將首先調(diào)用finalize()方法
finalize()方法中一般用于釋放非Java 資源(如打開的文件資源、數(shù)據(jù)庫連接等),或是調(diào)用非Java方法(native方法)時(shí)分配的內(nèi)存。
4、獲取對(duì)象的運(yùn)行時(shí)對(duì)象的類 Class<?> getClass()
Object getClass() 方法用于獲取對(duì)象的運(yùn)行時(shí)對(duì)象的類。 示例:
/**
* @Description: $getClass
* @Author: dyq
* @Date: $
*/
public class getClassTest {
public static void main(String[] args) {
// getClass() with Object
Object obj1 = new Object();
System.out.println("obj1 的類為: " obj1.getClass());
// getClass() with String
String obj2 = new String();
System.out.println("obj2 的類為: " obj2.getClass());
// getClass() with ArrayList
ArrayList<Integer> obj3 = new ArrayList<>();
System.out.println("obj3 的類為: " obj3.getClass());
// 創(chuàng)建 getClassTest 類的對(duì)象
getClassTest classTest = new getClassTest();
// getClassTest 繼承 Object 類,Object 是所有類的超類
// 調(diào)用 getClass() 方法
System.out.println("classTest的類為:" classTest.getClass());
}
}
結(jié)果:
obj1 的類為: class java.lang.Object
obj2 的類為: class java.lang.String
obj3 的類為: class java.util.ArrayList
classTest的類為:class com.Colltion.Test.getClassTest
5、獲取對(duì)象的 hash 值 int hashCode()
返回對(duì)象是哈希值,是一個(gè)整數(shù),表示在哈希表中的位置。
示例:
import java.util.ArrayList;
/**
* @Description: $hashCode()
* @Author: dyq
* @Date: $
*/
public class hashCodeTest {
public static void main(String[] args) {
// Object 使用 hashCode()
Object obj = new Object();
System.out.println(obj.hashCode());
//String 和 ArrayList 類都繼承了 Object,所以可以直接使用 hashCode() 方法:
// String 使用 hashCode()
String str = new String();
System.out.println(str.hashCode()); // 0
// ArrayList 使用 hashCode()
ArrayList<Integer> list = new ArrayList<>();
System.out.println(list.hashCode()); // 1
//如果兩個(gè)對(duì)象相等,則它們的哈希值也是相等的
// Object 使用 hashCode()
Object obj1 = new Object();
// obj1 賦值給 obj2
Object obj2 = obj1;
// 判斷兩個(gè)對(duì)象是否相等
System.out.println(obj1.equals(obj2)); // true
// 獲取 obj1 與 obj2 的哈希值
System.out.println(obj1.hashCode()); // 1163157884
System.out.println(obj2.hashCode()); // 1163157884
}
}
結(jié)果:
460141958
0
1
true
1163157884
1163157884
6、喚醒在該對(duì)象上等待的某個(gè)線程void notify()
notify() 方法只能被作為此對(duì)象監(jiān)視器的所有者的線程來調(diào)用。
一個(gè)線程要想成為對(duì)象監(jiān)視器的所有者,可以使用以下 3 種方法:
執(zhí)行對(duì)象的同步實(shí)例方法 使用 synchronized 內(nèi)置鎖 對(duì)于 Class 類型的對(duì)象,執(zhí)行同步靜態(tài)方法
一次只能有一個(gè)線程擁有對(duì)象的監(jiān)視器。
如果當(dāng)前線程不是此對(duì)象監(jiān)視器的所有者的話會(huì)拋出 IllegalMonitorStateException 異常。
來源:https://www./content-1-845951.html