最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文帶你了解Java萬(wàn)物之基之Object類

 更新時(shí)間:2022年03月09日 15:29:46   作者:不想起床的小張  
Java是一門天然的面向?qū)ο蟮恼Z(yǔ)言。而所有我們手動(dòng)創(chuàng)造出來(lái)的類,都繼承于同一個(gè)類,即Object類。本文將通過(guò)示例為大家詳細(xì)介紹一下Java中的Object類,需要的可以參考一下

Java是一門天然的面向?qū)ο蟮恼Z(yǔ)言。而所有我們手動(dòng)創(chuàng)造出來(lái)的類,都繼承于同一個(gè)類,即Object類。

可以看一下Object類的結(jié)構(gòu)

native方法

首先,超類擁有一個(gè)native方法

private static native void registerNatives();
static {
    registerNatives();
}

Java中,用native關(guān)鍵字修飾的函數(shù)表明該方法的實(shí)現(xiàn)并不是在Java中去完成。而是被C/C++完成,并被編譯成了.ddl文件,由Java去調(diào)用。registerNatives()方法本身,主要作用是將C/C++中的方法映射到Java中的native方法,實(shí)現(xiàn)方法命名的解耦。同時(shí),也定義了一個(gè)靜態(tài)代碼塊,由此,每當(dāng)我們創(chuàng)建Java對(duì)象時(shí),都系統(tǒng)總是先調(diào)用靜態(tài)代碼塊,即調(diào)用native方法。該方法被private修飾,表明了這個(gè)方法是私有的,不被外部調(diào)用

getClass方法

通過(guò)此方法,可獲得類的Class實(shí)例,具體可見(jiàn)Java反射機(jī)制

hashCode方法

百度百科的定義如下:

哈希碼(HashCode),并不是完全唯一的,它是一種算法,讓同一個(gè)類的對(duì)象按照自己不同的特征盡量的有不同的哈希碼,但不表示不同的對(duì)象哈希碼完全不同。也有相同的情況,看程序員如何寫哈希碼的算法。

散列表(Hash table,也叫哈希表),是根據(jù)關(guān)鍵碼值(Key value)而直接進(jìn)行訪問(wèn)的數(shù)據(jù)結(jié)構(gòu),把關(guān)鍵碼值映射到表中一個(gè)位置來(lái)訪問(wèn)記錄,以加快查找的速度.

由此可見(jiàn),通過(guò)Java內(nèi)部的散列函數(shù),可以給每個(gè)實(shí)例化的對(duì)象分配一個(gè)內(nèi)存地址,并記錄在散列表中,便于在程序中查找、新建、對(duì)比對(duì)象時(shí)更加高效。

寫一個(gè)實(shí)例打印看看:

public class base {

    public static void main(String[] args) {

        Apple apple = new Apple();
        System.out.println(apple.hashCode());
        System.out.println(apple);
        System.out.println(Integer.valueOf("74a14482",16));

    }

}

class Apple {
}

打印結(jié)果:

1956725890
p2.Apple@74a14482
1956725890

進(jìn)程已結(jié)束,退出代碼0

可見(jiàn)對(duì)象的哈希地址為10進(jìn)制數(shù),與打印的原生16進(jìn)制地址相對(duì)應(yīng)

equals方法

Object equals() 方法用于比較兩個(gè)對(duì)象是否相等。

equals() 方法比較兩個(gè)對(duì)象,是判斷兩個(gè)對(duì)象引用指向的是同一個(gè)對(duì)象,即比較 2 個(gè)對(duì)象的內(nèi)存地址是否相等。

可見(jiàn)equals比較兩個(gè)對(duì)象是否相等時(shí),比較的是兩個(gè)對(duì)象的hashcode是否相等。因此,若要重寫equals方法,通常也要重寫hashcode方法。

例如,String類型并不是一個(gè)原生的數(shù)據(jù)類型(例如int,char,double等),而是Java重新封裝的對(duì)象。String、Integer等都重寫了equals方法,改變?yōu)楸容^值是否相等,而不是引用類型(hashcode)

例如String對(duì)equals方法的重新封裝:

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

其中,instanceof 是 Java 的保留關(guān)鍵字。它的作用是測(cè)試它左邊的對(duì)象是否是它右邊的類的實(shí)例,返回 boolean 的數(shù)據(jù)類型。源碼表示,會(huì)先匹配引用是否相同,相同則返回真,否則將String實(shí)例轉(zhuǎn)化為字符數(shù)組,并逐個(gè)匹配是否相等,即匹配值是否相等。

String同時(shí)也重寫了hashcode方法:

 public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

其中,hash默認(rèn)為0,所以重寫hash計(jì)算公式為:hash=s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

==和equals的區(qū)別

  • == :當(dāng)比較基本類型時(shí),則比較兩者的值是否相等;當(dāng)比較引用類型時(shí),則比較引用引用(hashcode)是否相等
  • equals:由源碼,比較引用是否相等,部分類型如String、Integer等重寫了equals方法,比較值是否相等

舉幾個(gè)例子:

public class base {

    public static void main(String[] args) {

        // new兩個(gè)String對(duì)象,但內(nèi)容相同
        String a = new String("xxx");
        String b = new String("xxx");
        System.out.println(a == b);    // 比較hash值,因?yàn)槭莾蓚€(gè)不同的實(shí)例化對(duì)象,所以不同,返回false
        System.out.println(a.equals(b)); // 比較內(nèi)容,均為“xxx”,返回true

        // 生成兩個(gè)引用
        String c = "xxx";
        String d = "xxx";
        System.out.println(c == d); // 比較hash值,因?yàn)橹赶蛲粋€(gè)引用,所以相同,返回true
        System.out.println(c.equals(d)); // 比較內(nèi)容,均為“xxx”,返回true
        
    }

}

總結(jié):equals 本質(zhì)上就是 ==,只不過(guò) String 和 Integer 等重寫了 equals 方法,把它變成了值比較,所以一般情況下 可理解為equals 比較的是值是否相等。

clone方法

Object clone() 方法用于創(chuàng)建并返回一個(gè)對(duì)象的拷貝。

clone 方法是淺拷貝,對(duì)象內(nèi)屬性引用的對(duì)象只會(huì)拷貝引用地址,而不會(huì)將引用的對(duì)象重新分配內(nèi)存,相對(duì)應(yīng)的深拷貝則會(huì)連引用的對(duì)象也重新創(chuàng)建。

由源碼文檔,clone方法只能實(shí)現(xiàn)淺拷貝,且類需要重寫clone方法,調(diào)用super.clone來(lái)獲取返回的對(duì)象,因?yàn)椴煌?,基類保護(hù)的實(shí)例方法子類無(wú)權(quán)訪問(wèn)。另外,object類本身沒(méi)有實(shí)現(xiàn)Cloneable接口,但我們自己寫的類需要繼承Cloneable接口,否則會(huì)總會(huì)拋出CloneNotSupportedException異常。

寫個(gè)例子:

public class base{

    public static void main(String[] args) throws CloneNotSupportedException {

        // 實(shí)例化一個(gè)Student對(duì)象
        Student student = new Student(18,"Tony");
        // 打印內(nèi)容
        System.out.println(student);

        // 克隆student實(shí)例
        Student anotherStudent = (Student) student.clone();
        // 打印克隆內(nèi)容
        System.out.println(anotherStudent);

    }

}

class Student implements Cloneable {
    int age;
    String name;

    Student(int age, String name) {
        this.age = age;
        this.name = name;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

打印結(jié)果:

Student{age=18, name='Tony'}
Student{age=18, name='Tony'}

進(jìn)程已結(jié)束,退出代碼0

淺拷貝和深拷貝

淺拷貝例子

當(dāng)拷貝的對(duì)象的成員有引用對(duì)象時(shí),例如在Student類中包含了另一個(gè)Teacher對(duì)象時(shí),被克隆的對(duì)象和克隆的對(duì)象指向同一個(gè)Teacher引用,所以當(dāng)改變Teacher的數(shù)據(jù)時(shí),克隆的對(duì)象也會(huì)隨之改變

寫個(gè)例子:

public class base {

    public static void main(String[] args) throws CloneNotSupportedException {

        // 實(shí)例化一個(gè)Teacher對(duì)象
        Teacher teacher = new Teacher(25,"JayChou");
        // 實(shí)例化一個(gè)Student對(duì)象
        Student student = new Student(18, "Tony",teacher);
        // 打印內(nèi)容
        System.out.println(student);
        // 克隆student實(shí)例
        Student anotherStudent = (Student) student.clone();
        System.out.println(anotherStudent);
        System.out.println("---------------------------------------");
        // 修改teacher數(shù)據(jù),并更新student
        teacher.setAge(30);
        student.setTeacher(teacher);
        // 打印修改后的student實(shí)例和克隆對(duì)象實(shí)例
        System.out.println(student);
        System.out.println(anotherStudent);

    }

}

class Student implements Cloneable {
    int age;
    String name;
    Teacher teacher;

    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }

    Student(int age, String name, Teacher teacher) {
        this.age = age;
        this.name = name;
        this.teacher = teacher;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", teacher=" + teacher +
                '}';
    }
}

class Teacher implements Cloneable {
    int age;
    String name;

    Teacher(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }

}

打印結(jié)果:

Student{age=18, name='Tony', teacher=Teacher{age=25, name='JayChou'}}
Student{age=18, name='Tony', teacher=Teacher{age=25, name='JayChou'}}
---------------------------------------
Student{age=18, name='fuck', teacher=Teacher{age=30, name='JayChou'}}
Student{age=18, name='Tony', teacher=Teacher{age=30, name='JayChou'}}

進(jìn)程已結(jié)束,退出代碼0

這就是淺拷貝的結(jié)果,因指向同一個(gè)引用,當(dāng)其中一個(gè)實(shí)例發(fā)生更新時(shí),會(huì)發(fā)生連鎖變化

所以相反,實(shí)現(xiàn)深拷貝,使得不會(huì)發(fā)生連鎖反應(yīng),讓克隆與被克隆對(duì)象徹底分離!

實(shí)現(xiàn)深拷貝

大致有一下思路:

不采用clone方法,重新new一個(gè)對(duì)象,將需要復(fù)制的對(duì)象所有屬性成員放進(jìn)去

 // 實(shí)例化一個(gè)Teacher對(duì)象
        Teacher teacher = new Teacher(25,"JayChou");
        // 實(shí)例化一個(gè)Student對(duì)象
        Student student = new Student(18, "Tony",teacher);
        // 打印內(nèi)容
        System.out.println(student);
        // new一個(gè)一模一樣的!
        Student anotherStudent = new Student(18,"Tony",new Teacher(25,"JayChou"));
        System.out.println(anotherStudent);
        System.out.println("---------------------------------------");
        // 修改teacher數(shù)據(jù),并更新student
        teacher.setAge(30);
        student.setTeacher(teacher);
        // 打印修改后的student實(shí)例和克隆對(duì)象實(shí)例
        System.out.println(student);
        System.out.println(anotherStudent);

打印結(jié)果:

Student{age=18, name='Tony', teacher=Teacher{age=25, name='JayChou'}}
Student{age=18, name='Tony', teacher=Teacher{age=25, name='JayChou'}}
---------------------------------------
Student{age=18, name='Tony', teacher=Teacher{age=30, name='JayChou'}}
Student{age=18, name='Tony', teacher=Teacher{age=25, name='JayChou'}}

進(jìn)程已結(jié)束,退出代碼0

重寫clone方法,將每個(gè)引用對(duì)象也實(shí)現(xiàn)克隆

@Override
    protected Object clone() throws CloneNotSupportedException {
        Student student = (Student) super.clone();
        student.setTeacher((Teacher) this.teacher.clone());
        return student;
    }

打印結(jié)果:

Student{age=18, name='Tony', teacher=Teacher{age=25, name='JayChou'}}
Student{age=18, name='Tony', teacher=Teacher{age=25, name='JayChou'}}
---------------------------------------
Student{age=18, name='Tony', teacher=Teacher{age=30, name='JayChou'}}
Student{age=18, name='Tony', teacher=Teacher{age=25, name='JayChou'}}

進(jìn)程已結(jié)束,退出代碼0

序列化

序列化的方式有很多,主要是工具比較多...這里我使用Apache Commons Lang序列化

首先,相關(guān)類都需要繼承序列化接口(接口并沒(méi)有實(shí)質(zhì)的實(shí)現(xiàn)內(nèi)容,僅僅作為一個(gè)標(biāo)志)

public class base {

    public static void main(String[] args) throws CloneNotSupportedException {

        // 實(shí)例化一個(gè)Teacher對(duì)象
        Teacher teacher = new Teacher(25,"JayChou");
        // 實(shí)例化一個(gè)Student對(duì)象
        Student student = new Student(18, "Tony",teacher);
        // 打印內(nèi)容
        System.out.println(student);
        // 序列化深拷貝
        Student anotherStudent = (Student) SerializationUtils.clone(student);
        System.out.println(anotherStudent);
        System.out.println("---------------------------------------");
        // 打印序列化后內(nèi)容 為字節(jié)流
        byte[] res = SerializationUtils.serialize(student);
        System.out.println(SerializationUtils.serialize(student));
        // 打印反序列化結(jié)果
        System.out.println(SerializationUtils.deserialize(res));
        System.out.println("---------------------------------------");
        // 修改teacher數(shù)據(jù),并更新student
        teacher.setAge(30);
        student.setTeacher(teacher);
        // 打印修改后的student實(shí)例和克隆對(duì)象實(shí)例
        System.out.println(student);
        System.out.println(anotherStudent);

    }

}

class Student implements Serializable {
    int age;
    String name;
    Teacher teacher;

    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }

    Student(int age, String name, Teacher teacher) {
        this.age = age;
        this.name = name;
        this.teacher = teacher;
    }

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", teacher=" + teacher +
                '}';
    }
}

class Teacher implements Serializable {
    int age;
    String name;

    Teacher(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }

}

打印結(jié)果:

Student{age=18, name='Tony', teacher=Teacher{age=25, name='JayChou'}}
Student{age=18, name='Tony', teacher=Teacher{age=25, name='JayChou'}}
---------------------------------------
[B@50040f0c
Student{age=18, name='Tony', teacher=Teacher{age=25, name='JayChou'}}
---------------------------------------
Student{age=18, name='Tony', teacher=Teacher{age=30, name='JayChou'}}
Student{age=18, name='Tony', teacher=Teacher{age=25, name='JayChou'}}

進(jìn)程已結(jié)束,退出代碼0

總結(jié):第一種方式笨笨的哈哈,第二種方式需要手動(dòng)重寫clone方法,當(dāng)對(duì)象復(fù)雜時(shí),就不是一個(gè)明智的選擇了。相比較之下,第三種當(dāng)時(shí)顯的十分方便帥氣,可由于底層實(shí)現(xiàn)的復(fù)雜,存在一定的系統(tǒng)開(kāi)銷。

toString方法

當(dāng)沒(méi)有重寫該方法時(shí),當(dāng)打印實(shí)例化對(duì)象時(shí),則返回類名與hash地址的16進(jìn)制拼接字符串。為便于人們閱讀,建議所有子類重寫該方法

例如我的Student類重寫了該方法:

class Student implements Serializable {
    int age;
    String name;
    Teacher teacher;

    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }

    Student(int age, String name, Teacher teacher) {
        this.age = age;
        this.name = name;
        this.teacher = teacher;
    }

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", teacher=" + teacher +
                '}';
    }
}

則打印該對(duì)象時(shí)會(huì)返回人們便于閱讀的內(nèi)容:

Student{age=18, name='Tony', teacher=Teacher{age=25, name='JayChou'}}

線程方法

wait(),wait(long),wait(long,int),notify(),notifyAll()分別用于線程的休眠于喚醒,在多線程內(nèi)容中再做詳解

finalize方法

到此這篇關(guān)于一文帶你了解Java萬(wàn)物之基之Object類的文章就介紹到這了,更多相關(guān)Java Object類內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java實(shí)現(xiàn)限流接口的示例詳解

    Java實(shí)現(xiàn)限流接口的示例詳解

    限流是對(duì)某一時(shí)間窗口內(nèi)的請(qǐng)求數(shù)進(jìn)行限制,保持系統(tǒng)的可用性和穩(wěn)定性,防止因流量暴增而導(dǎo)致的系統(tǒng)運(yùn)行緩慢或宕機(jī),本文主要來(lái)和大家聊聊如何使用java實(shí)現(xiàn)限流接口,感興趣的可以了解下
    2023-12-12
  • Java漢字轉(zhuǎn)拼音案例詳解

    Java漢字轉(zhuǎn)拼音案例詳解

    這篇文章主要介紹了Java漢字轉(zhuǎn)拼音案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • Java 實(shí)現(xiàn)限流器處理Rest接口請(qǐng)求詳解流程

    Java 實(shí)現(xiàn)限流器處理Rest接口請(qǐng)求詳解流程

    在工作中是否會(huì)碰到這樣的場(chǎng)景,高并發(fā)的請(qǐng)求但是無(wú)法全部執(zhí)行,需要一定的限流。如果你是使用的微服務(wù)框架,比如SpringCloud,可以使用Gateway增加限流策略來(lái)解決。本篇文章是在沒(méi)有框架的情況實(shí)現(xiàn)限流器
    2021-11-11
  • Java開(kāi)發(fā)學(xué)習(xí)之Bean的作用域和生命周期詳解

    Java開(kāi)發(fā)學(xué)習(xí)之Bean的作用域和生命周期詳解

    這篇文章主要介紹了淺談Spring中Bean的作用域,生命周期和注解,從創(chuàng)建到消亡的完整過(guò)程,例如人從出生到死亡的整個(gè)過(guò)程就是一個(gè)生命周期。本文將通過(guò)示例為大家詳細(xì)講講,感興趣的可以學(xué)習(xí)一下
    2022-06-06
  • mybatis教程之延遲加載詳解

    mybatis教程之延遲加載詳解

    本篇文章主要介紹了mybatis教程之延遲加載詳解。詳細(xì)介紹了延遲加載的意義和用法實(shí)現(xiàn),有興趣的可以了解一下
    2017-05-05
  • Java 如何繞過(guò)迭代器遍歷時(shí)的數(shù)據(jù)修改異常

    Java 如何繞過(guò)迭代器遍歷時(shí)的數(shù)據(jù)修改異常

    這篇文章主要介紹了Java 繞過(guò)迭代器遍歷時(shí)的數(shù)據(jù)修改異常的方法,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下
    2021-02-02
  • Java的線程阻塞、中斷及優(yōu)雅退出方法詳解

    Java的線程阻塞、中斷及優(yōu)雅退出方法詳解

    這篇文章主要介紹了Java的線程阻塞、中斷及優(yōu)雅退出方法詳解,Java中的線程阻塞是指當(dāng)一個(gè)線程無(wú)法繼續(xù)執(zhí)行時(shí),它會(huì)進(jìn)入阻塞狀態(tài),直到某個(gè)條件滿足后才能繼續(xù)執(zhí)行,線程阻塞可以通過(guò)多種方式實(shí)現(xiàn),需要的朋友可以參考下
    2023-10-10
  • Spring的編程式事務(wù)TransactionTemplate的用法詳解

    Spring的編程式事務(wù)TransactionTemplate的用法詳解

    TransactionTemplate提供了一種在代碼中進(jìn)行編程式事務(wù)管理的方式,使開(kāi)發(fā)人員能夠在方法級(jí)別定義事務(wù)的開(kāi)始和結(jié)束點(diǎn),本文介紹了Spring框架中TransactionTemplate的用法,感興趣的朋友跟隨小編一起看看吧
    2023-07-07
  • Java服務(wù)剛啟動(dòng)時(shí)接口超時(shí)排查全過(guò)程

    Java服務(wù)剛啟動(dòng)時(shí)接口超時(shí)排查全過(guò)程

    這篇文章主要為大家介紹了Java服務(wù)剛啟動(dòng)時(shí),一小波接口超時(shí)排查全過(guò)程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • 深入理解Java中的并發(fā)工具類CountDownLatch

    深入理解Java中的并發(fā)工具類CountDownLatch

    CountDownLatch?作為?Java?中的一個(gè)同步工具類,用于在多線程間實(shí)現(xiàn)協(xié)調(diào)和控制,本文主要來(lái)和大家講解一下JUC?工具類?CountDownLatch的使用,需要的可以參考一下
    2023-07-07

最新評(píng)論

阿图什市| 思茅市| 白水县| 仁寿县| 绩溪县| 忻州市| 印江| 济南市| 琼海市| 湘潭县| 沛县| 西畴县| 凤庆县| 商丘市| 青铜峡市| 江油市| 宜章县| 阳朔县| 东海县| 佳木斯市| 龙陵县| 灵宝市| 哈尔滨市| 龙南县| 海林市| 丽水市| 襄垣县| 尖扎县| 棋牌| 马尔康县| 山阳县| 泰来县| 舞阳县| 松桃| 龙泉市| 双流县| 柳林县| 武义县| 海原县| 巩留县| 芦溪县|