【JAVA |再談接口、Object、內部類】Object類中子類重寫,Cloneable 接口、比較器、內部類

??謝謝大家捧場,祝屏幕前的小伙伴們每天都有好運相伴左右,一定要天天開心哦!???
🎈🎈作者主頁:?🎈丠丠64-CSDN博客🎈


???帥哥美女們,我們共同加油!一起進步!???

目錄

一、前言

二、Obiect類

1.獲取對象信息的打印

2.比較類中對象的異同

-equals方法

-hashcode方法

三、接口實現實例

-Comparable接口

-排序一個數組成員元素

1.直接使用接口Comparable

2.構造新的比較器

四、對象的拷貝

1.Cloneable拷貝

-淺拷貝

-深拷貝


一、前言

上一篇我們介紹了抽象類以及接口的相關知識,這篇我們來接著探討一下關于接口的實例,并且認識一下所有類的父類Object


二、Obiect類

Object時JAVA中默認提供的一個類,所有的類都是繼承Oject,換句話來說Oject是所有類的父類,這樣就可以說在有需要實現一些功能的時候,子類方法就可以用重寫來實現

1.獲取對象信息的打印

我們首先來看這樣一段代碼

public class Person {public int age;public String name;public Person(int age, String name) {this.age = age;this.name = name;}
}
public class Test {public static void main(String[] args){Person person = new Person(16,"張三");System.out.println(person);} 
}

我們目的想要實現傳入變量名字以后,打印出對應的成員屬性,傳入println()中是否能實現呢?

事實卻是輸出了這樣一個值,為什么呢?我們跳轉println函數定義去看

我們發現實現的最終函數是這個toString()前半部分是全路徑,后面部分是類似地址一樣的東西(后面會說)


toString()是Object的子類,所以我們只需要重寫toString(),就可以隨意實現我們的功能,所以修改一下這個代碼重寫toString()

public class Person {public int age;public String name;public Person(int age, String name) {this.age = age;this.name = name;}@Overridepublic String toString() {return "Person{" + "age=" + age + ", name='" + name + '\'' + '}';}
}

即可實現我們的功能


2.比較類中對象的異同

首先我們先來看一段代碼

        Person person1 = new Person(16,"張三");System.out.println(person1);Person person2 = new Person(16,"張三");System.out.println(person2);System.out.println(person1 == person2);

對于兩個不同的變量,但是里面的成員屬性卻相同,比較person1和person2,他兩會相等嗎?

運行結果來看,兩者是不同的,我們屏蔽掉剛寫的toString()來看一下結果

發現原來是他們類似于地址一樣的東西不一樣!兩個對象比較的其實是類似于地址的地址!

兩個對象以不同的位置進行分配


-equals方法

在JAVA在有一個方法也是用來比較兩個對象是否相等,就是equals(),我們跳轉到定義去看

System.out.println(person1.equals(person2));

我發現它的定義只是這樣(其中的this指誰調用equals誰就是this),跟剛才的person1 == person2沒有區別,我們要實現我們的功能,對成員中的屬性進行比較,因為equals是Object的子類,就要對其進行重寫

@Overridepublic boolean equals(Object o) {if (this == o) {        return true;        //如果指向同一個對象為真}if (o == null || getClass() != o.getClass()) {return false;        //如果對象屬性為空或者不是一個東西了為假}Person person = (Person) o;//向下轉型比較屬性值//判斷對象中各個屬性,都為真才為真return age == person.age && Objects.equals(name, person.name);}

通過調用自己重寫的方法,這樣這段代碼就可以實現我們所需要的功能了,比較兩個對象中各屬性是否相等

        System.out.println(person1.equals(person2));

比較對象中內容是否相同的時候,一定要重寫 equals方法?????????

-hashcode方法

剛才在調用toString方法時我們看見了hashCode()這個方法,他幫我算了一個具體的對象位置,該方法是一個native方法,底層是由C/C++代碼寫的。我們看不到。

public native int hashCode();

我們來看一下這兩個的值為多少?

System.out.println(person1.hashCode());
System.out.println(person2.hashCode());

因為兩者所分配的空間不同,所以對象位置也不相同,返回的值也就不相同,倘若我們現在想要實現,為兩個名字相同,年齡相同的對象,將存儲在同一個位置,hashcode是Object的子類,我們就要重寫hashcode()方法

 @Overridepublic int hashCode() {return Objects.hash(age, name);}

再輸出我們結果,發現經過一系列算法,兩個對象出現了同一位置

兩個對象的hash值不一樣,hashcode方法用來確定對象在內存中存儲的位置是否相同

三、接口實現實例

我們先看這樣一個代碼

public class Student {public int age;public String name;public Student(int age, String name) {this.age = age;this.name = name;}@Overridepublic String toString() {return "Student{" +"age=" + age +", name='" + name + '\'' +'}';}}

當我們想實現兩個變量之間的比較,是不是直接比較他們兩個變量是否相等然后返回布爾值就行了呢?答案是錯的,引用類型變量不可以這樣比較,直接比較會報錯

public class Test {public static void main(String[] args){Student student1 = new Student(12,"小明");Student student2 = new Student(15,"小美");System.out.println(student1 > student1);}}


-Comparable接口

自定義想要比較大小,就要實現這個接口

我們應該在Student這個類給它加上一個Comparable接口,再把Student傳進去就可以進行比較了

public class Student implements Comparable<Student>{public int age;public String name;public Student(int age, String name) {this.age = age;this.name = name;}@Overridepublic String toString() {return "Student{" +"age=" + age +", name='" + name + '\'' +'}';}}

但是我們發現還是會報錯,我們跳轉過去定義查看

發現需要按照自己的需求去重寫這個compareTo方法

假如說我們需要按照年齡去比較兩個對象,于是就可以這樣重寫

@Overridepublic int compareTo(Student o) {return this.age - o.age;  //大于輸出正數,小于輸出負數,相等輸出0}

這樣就不會報錯了

System.out.println(student1.compareTo(student2));
System.out.println(student2.compareTo(student1));

輸出結果

-排序一個數組成員元素

1.直接使用接口Comparable

先實現一個學生的類,并且使用接口Comparable

public class Student implements Comparable<Student>{public int age;public String name;public Student(int age, String name) {this.age = age;this.name = name;}@Overridepublic String toString() {return "Student{" +"age=" + age +", name='" + name + '\'' +'}';}@Overridepublic int compareTo(Student o) {return this.age - o.age;  //大于輸出正數,小于輸出負數,相等輸出0}
}

定義一個學生的數組

Student[] students = new Student[3];students[0] = new Student(18,"小明");
students[1] = new Student(15,"小禮");
students[2] = new Student(21,"小花");

然后根據冒泡排序對學生的年齡對其排序

public static void my_sort(Comparable[] comparable){for (int i = 0; i < comparable.length - 1; i++) {for (int j = 0; j < comparable.length - 1 - i; j++) {if (comparable[j].compareTo(comparable[j+1]) > 0){Comparable tmp = comparable[j];comparable[j] = comparable[j+1];comparable[j+1] = tmp;}}}}

打印出結果,對其學生年齡進行排序

my_sort(students);
System.out.println(Arrays.toString(students));

結果成立

但是這種方法也有很大的危害,對類的侵入性比較強,也不夠靈活


2.構造新的比較器

所以基于上述的的危害我們可以進行優化

對于年齡比較,我們新建一個類AgeComparator,并對其compare進行重寫即可

class AgeComparator implements Comparator<Student> {@Overridepublic int compare(Student o1,Student o2) {return o1.age - o2.age;  }
}

對于名字比較,我們新建一個類NameComparator,并對其compare進行重寫即可

class NameComparator implements Comparator<Student> {@Overridepublic int compare(Student o1, Student o2) {return o1.name.compareTo(o2.name);}
}

我們來實現一下,分別以年齡跟名字比較

        Student student1 = new Student(12,"zahngsan");Student student2 = new Student(15,"lisi");NameComparator nameComparator = new NameComparator();System.out.println(nameComparator.compare(student1, student2));AgeComparator ageComparator = new AgeComparator();System.out.println(ageComparator.compare(student1, student2));

結果成立,且互不干擾,這就是比較器的好處,比較靈活,對類的侵入性不強


四、對象的拷貝

我們先構造一個類,并且實例化一個對象

public class Person {public int age;public Person(int age) {this.age = age;}@Overridepublic String toString() {return "Person{" +"age=" + age +'}';}
}
public class Test {public static void main(String[] args){Person person1 = new Person(19);}
}

實例化的對象person1他在內存中是這樣分配的,對象的屬性在堆區開辟了空間地址由persin1保存

倘若我們要實現對變量person1進行一份拷貝,如何實現呢?


1.Cloneable拷貝

我們先介紹Cloneable接口,我們先跳轉過定義,可以看到是一個空接口

又稱為標記接口:證明當前類是可以被克隆的

我們實例化第二個對象,用JAVA中提供的clone 方法,創建一個對象的 "拷貝"

Person person2 = person1.clone();

但是我們發現報錯了,我們還要經過以下三步

clone屬于Obiect中的方法,我們轉到clone的定義,發現他的訪問權限是protected,直接訪問不到只能夠重寫這個方法

但是同時呢我們發現還多了一個 throws CloneNotSupportedException這樣的東西,必須是編譯時處理,所以我們也要在main主函數上加上 throws CloneNotSupportedException

同時呢用我們發現它的返回值為Object,父類訪問子類中的方法就是發生向下轉型強轉為Person類型

    @Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
public class Test {public static void main(String[] args) throws CloneNotSupportedException {Person person1 = new Person(19);Person person2 = (Person) person1.clone();}
}

同時也要加接口,來證明這個類可以被克隆

public class Person implements Cloneable{public int age;public Person(int age) {this.age = age;}@Overridepublic String toString() {return "Person{" +"age=" + age +'}';}protected Object clone() throws CloneNotSupportedException {return super.clone();}
}

不加接口則會報錯

至此編譯正常通過

public class Test {public static void main(String[] args) throws CloneNotSupportedException {Person person1 = new Person(19);Person person2 = (Person) person1.clone();System.out.println(person1);System.out.println(person2);}
}

成功克隆


-淺拷貝

我們來看以下的這段代碼

構造了個Money、Perso兩個類,重寫了clone

class Money {public double m = 99.99;
}class Person implements Cloneable{public Money money = new Money();@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}

person1拷貝一份persona2,并且修改persinal2的值,理想的結果應該是persinal2的m值被修改,person1的不變

public class Test{public static void main(String[] args) throws CloneNotSupportedException {Person person1 = new Person();Person person2 = (Person) person1.clone();System.out.println("通過person2修改前的結果");System.out.println(person1.money.m);System.out.println(person2.money.m);person2.money.m = 13.6;System.out.println("通過person2修改后的結果");System.out.println(person1.money.m);System.out.println(person2.money.m);}

但是輸出結果并不是這樣,我們發現persona1中的m也被修改了,為什么會這樣呢?

我們發現拷貝只拷貝了一份新的對象,并沒有拷貝對象中的元素,對象中的元素位置沒有被改變,兩個對象中的m指向了同一塊內存,同一個嗎,對象中的元素沒有被克隆,所以兩者都可以修改,這種沒有完全拷貝就稱為淺拷貝


-深拷貝

? 我們對以上的代碼進行修改,將clone進行重寫,將對象中的對象也進行拷貝,這個問題就解決了

@Overrideprotected Object clone() throws CloneNotSupportedException {Person tmp = (Person) super.clone();tmp.money = this.money.clone();}

深淺拷貝說白了就是重寫clone方法實現的,方法內部實現的不一樣


希望對你有幫助

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/14460.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/14460.shtml
英文地址,請注明出處:http://en.pswp.cn/web/14460.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Internet動態路由選擇—RIP與OSPF

剛做完網絡層動態路由選擇的實驗&#xff0c;寫下此篇記錄實驗過程&#xff0c;鞏固學習成果。 參考書目&#xff1a;《計算機網絡》北京理工大學出版社-劉陽老師編 路由選擇可分為兩種策略&#xff1a; - 靜態路由選擇策略 - 動態路由選擇策略 靜態路由即管理員手動配置路由…

Java 商品入庫系統 案例

測試類 package 練習.商品入庫系統;import java.util.ArrayList; import java.util.Scanner; public class Test {public static final int Enrool 1;public static final int Search 2;public static final int Delect 3;public static final int Exit 4;public static…

在docker上部署postgresSQL主從

文章目錄 一、主從規劃二、創建PostgresSQL的Docker鏡像三、主庫部署1、建立pgsql主庫的data地址2、啟動docker鏡像3、docker內操作4、修改配置文件 四、部署從數據庫1、建立psql備庫的data地址2、啟動docker鏡像3、備庫從主庫同步4、檢查是否同步 五、測試主從數據庫 一、主從…

#2495. 滑動窗口 /【模板】單調隊列

題目描述 有一個長為 ( n ) 的序列 ( a )&#xff0c;以及一個大小為 ( k ) 的窗口。現在這個窗口從左邊開始向右滑動&#xff0c;每次滑動一個單位&#xff0c;求出每次滑動后窗口中的最大值和最小值。例如&#xff1a; 數組是 ([1, 3, -1, -3, 5, 3, 6, 7])&#xff0c; ( …

【深度強化學習】關于同一設備上cuda和gpu計算結果不一致問題

文章目錄 問題描述關于seed: 跟原文一致補充:萬能seed 問題結論cpu和gpu差異來源分析浮點數精度的差異補充報錯&#xff1a;Expected all tensors to be on the same device&#xff01;常見運算上的差異累加運算的差異exp運算的差異matmul運算的差異 forward上的差異&#xff…

【LeetCode 隨筆】面試經典 150 題【中等+困難】持續更新中。。。

文章目錄 189. 輪轉數組122. 買賣股票的最佳時機 II55. 跳躍游戲45. 跳躍游戲 II274. H 指數 &#x1f308;你好呀&#xff01;我是 山頂風景獨好 &#x1f49d;歡迎來到我的博客&#xff0c;很高興能夠在這里和您見面&#xff01; &#x1f49d;希望您在這里可以感受到一份輕松…

機器學習云環境搭建

在 https://support.huaweicloud.com/browsertg-obs/obs_03_1003.html 下載對應版本的 OBS Broswer 軟件&#xff0c;如圖&#xff0c;紅框內的為安裝文件&#xff0c;藍色框內的為對應安裝文件的校驗文件&#xff08;無需下載&#xff09; 以 64 位機為例&#xff0c;下載完…

景源暢信電商:抖店需要的成本高嗎?

在數字化時代的浪潮中&#xff0c;短視頻平臺迅速崛起&#xff0c;成為連接用戶與商家的新橋梁。抖音作為其中的佼佼者&#xff0c;不僅改變了人們的娛樂方式&#xff0c;也催生了新型的電商模式——抖店。許多人好奇&#xff0c;入駐這樣一個充滿活力的平臺&#xff0c;需要承…

618知識狂歡,挑本好書,點亮智慧生活!

618精選編程書單&#xff1a;提升你的代碼力 一年一度的618又到啦&#xff01;今年的618就不要亂買啦&#xff0c;衣服買多了會被淘汰&#xff0c;電子產品買多了會過時&#xff0c;零食買多了會增肥&#xff0c;最后怎么看都不劃算。可是如果你購買知識&#xff0c;堅持閱讀&a…

第N2周:Embeddingbag與Embedding詳解

&#x1f368; 本文為&#x1f517;365天深度學習訓練營 中的學習記錄博客&#x1f356; 原作者&#xff1a;K同學啊 | 接輔導、項目定制&#x1f680; 文章來源&#xff1a;K同學的學習圈子 目錄 什么是詞嵌入&#xff1f; Embedding與EmbeddingBag詳解 Embedding Embeddi…

代碼隨想錄算法訓練營第十七天|LeetCode110 平衡二叉樹、LeetCode257 二叉樹的所有路徑

題1&#xff1a; 指路&#xff1a;LeetCode110 平衡二叉樹 思路與代碼&#xff1a; 左右子樹的高度差小于等于1。對于這個題&#xff0c;遞歸比迭代方便太多&#xff0c;我也想過迭代&#xff0c;但是我沒有寫出來&#xff0c;大家可以自己試一下。遞歸代碼如下&#xff1a;…

如何為ChatGPT編寫有效的提示詞:軟件開發者的指南

作為一名軟件開發者&#xff0c;特別是使用Vue進行開發的開發者&#xff0c;與ChatGPT等AI助手高效互動&#xff0c;可以極大地提升你的開發效率。本文將深入探討如何編寫有效的提示詞&#xff0c;以便從ChatGPT中獲取有用的信息和幫助。 1. 明確目標 在編寫提示詞之前&#…

后端之路第二站(正片)——SprintBoot之:分層解耦

很抽象&#xff0c;我自己也不好理解&#xff0c;僅作為一個前端轉后端的個人理解 一、先解釋一個案例&#xff0c;以這個案例來分析“三層架構” 這里我先解釋一下黑馬程序員里的這個案例&#xff0c;兄弟們看視頻的可以跳過這節課&#xff1a;Day05-08. 請求響應-響應-案例_…

【webrtc】m98:Call的創建及Call對音頻接收處理

call中多個流共享相同的輔助組件 這幾個是與外部共用的 線程傳輸send控制module 線程任務隊列工廠call的輔助組件中各種統計以及接收測的cc是自己創建的 call自己的多個輔助組件是外部傳遞來的 call 創建多個接收流 這里用一個set 來保存所有指針,并沒有要map的意思:

【因果推斷從入門到精通二】隨機實驗3

目錄 檢驗無因果效應假說 硬幣投擲的特殊性何在&#xff1f; 檢驗無因果效應假說 無因果效應假說認為&#xff0c;有些人存活&#xff0c;有些人死亡&#xff0c;但接受mAb114治療而不是ZMapp與此無關。在174例接受mAb14治療的患者中&#xff0c;113/17464.9%存活了28天&…

【MySQL精通之路】InnoDB(6)-磁盤結構

主要博客&#xff1a; 【MySQL精通之路】InnoDB存儲引擎-CSDN博客 1 表 2 索引 【MySQL精通之路】InnoDB(6)-磁盤結構(2)-索引-CSDN博客 3 表空間 【MySQL精通之路】InnoDB(6)-磁盤結構(3)-表空間-CSDN博客 4 雙寫緩沖區 【MySQL精通之路】InnoDB(6)-磁盤結構(4)-雙寫緩沖…

修改MySQL root用戶密碼

ALTER USER ‘root’‘localhost’ IDENTIFIED BY ‘new_password’; ALTER USER ‘root’‘%’ IDENTIFIED BY ‘new_password’; 》 SET GLOBAL read_only OFF; select * from mysql.user;

Java入門基礎學習筆記47——ArrayList

什么是集合呢&#xff1f; 集合是一種容器&#xff0c;用來裝數據的&#xff0c;類似數組。 有數組&#xff0c;為什么還要學習集合呢&#xff1f; 數組定義完成并啟動后&#xff0c;長度就固定了。 而集合是大小可變&#xff0c;開發中用的最多的。 集合的特點&#xff1a;大…

匯聚榮科技有限公司優點有哪些?

在當今快速發展的科技時代&#xff0c;企業之間的競爭愈發激烈。作為一家專注于科技創新與研發的公司&#xff0c;匯聚榮科技有限公司憑借其卓越的技術實力和創新能力&#xff0c;在業界樹立了良好的口碑。那么&#xff0c;匯聚榮科技有限公司究竟有哪些優點呢?接下來&#xf…