初識java——javaSE (6)接口的實現——比較器與深拷貝,淺拷貝

文章目錄

  • 前言
  • 一 比較器
    • 1.1 關于兩個對象的比較
    • 1.2 Comparable接口:
    • 1.3 Arrays.sort方法的實現
    • 1.4 比較器的實現
      • Comparator接口
  • 二 深拷貝與淺拷貝
    • 2.1 淺拷貝:
      • Cloneable接口:
      • clone方法:
      • 實現拷貝:
      • 淺拷貝:
    • 2.2 深拷貝:


前言


上一篇博客并沒有將接口的內容闡述完畢,這篇博客繼續闡述!

一 比較器

1.1 關于兩個對象的比較

在比較單個基本數據類型時,我們可以通過關系運算符進行比較。
 public class Test {public static void main(String[] args) {int age1 = 10;int age2 = 8;System.out.println(age1 > age2);}

在這里插入圖片描述

但是當比較對象等引用數據類型時,便不能僅僅通過關系運算符進行比較了。
class Student {String name;int age;public Student(int age, String name) {this.age = age;this.name = name;}}public class Test {public static void main(String[] args) {Student student1 = new Student(10,"張三");Student student2 = new Student(12,"李四");System.out.println(student1>student2);}}

在這里插入圖片描述

要進行對象間的比較,需要確定進行比較的規則是什么,比較哪一個屬性。

1.2 Comparable接口:

Comparable接口中的compareTo 方法用于進行對象間屬性的比較。

在這里插入圖片描述
compareTo是一個抽象方法,我們需要重寫:

//創建一個Student類,實現Comparable接口
class Student implements Comparable<Student> {String name;int age;public Student(int age, String name) {this.age = age;this.name = name;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
//重寫compareTo方法@Overridepublic int compareTo(Student o) {//比較年齡:if(this.age == o.age){return 0;}else if(this.age>o.age){return 1;}else {return -1;}}//比較姓名//  return this.name.compareTo(o.name);}public class Test {public static void main(String[] args) {Student student1 = new Student(10,"張三");Student student2 = new Student(12,"李四");System.out.println(student1.compareTo(student2));

在這里插入圖片描述
結果為-1 ,表明student1的年齡比student2的年齡小。
代碼分析:
Student類實現了Comparable接口,
<>是泛型的標記,以后會闡述到,比較那個類,就將類名填寫在<>中!

對象間的比較本質上依然是對象屬性之間的比較。

1.3 Arrays.sort方法的實現

如果創建一個對象數組,使得數組中的這些對象按照某種規則進行排序
則可以使用Array.sort方法

class Student implements Comparable<Student> {String name;int age;public Student(int age, String name) {this.age = age;this.name = name;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic int compareTo(Student o) {//比較年齡:if(this.age == o.age){return 0;}else if(this.age>o.age){return 1;}else {return -1;}}//比較姓名//  return this.name.compareTo(o.name);}public class Test {public static void main(String[] args) {Student[] arr1 = new Student[3];arr1[0] = new Student(10, "王五");arr1[1] = new Student(8, "李四");arr1[2] = new Student(9, "張三");Student[] arr1 = {student1,student2,student3};System.out.println("排序前:"+Arrays.toString(arr1));Arrays.sort(arr1);System.out.println("排序后:"+Arrays.toString(arr1));}
}

在這里插入圖片描述
排序后,年齡從小到大,依次遞增。

如果不實現Comparable接口,會怎么樣呢?
在這里插入圖片描述
在這里插入圖片描述
結果表明Student類型,不能轉換成Comparable類型,這是怎么回事,我們調用Arrays.sort方法進行排序,與轉換類型有什么關系?

這里我們需要手動實現一下Arrays.sort方法

 public  static  void mysort(Comparable[] comparables){// 用接口數組接收實現接口的數組   采用冒號排序的方式//比較的趟數!for (int i = 0;i<comparables.length-1 ;i++){for (int j = 0; j<comparables.length - 1-i;j++){if(comparables[j].compareTo(comparables[j+1])>0){//如果數組前面元素的值大于數組后面元素的值,則交換引用的值,這是升序Comparable tmp  = comparables[j];comparables[j]  = comparables[j+1];comparables[j+1] = tmp;}}}}

代碼分析: 問題就在于 if(comparables[j].compareTo(comparables[j+1])>0) 這條語句
我們通過接口類型數組來接收實現了接口的數組,并且對compareTo方法進行調用!

在上個例子中,因為沒有Student沒有實現Comparable接口,所以會發生Student類型無法發生向上轉型成Comparable接口類型的情況。

調用自己實現的mysort方法:

class Student implements Comparable<Student> {String name;int age;public Student(int age, String name) {this.age = age;this.name = name;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}public int compareTo(Student o) {//比較年齡:if(this.age == o.age){return 0;}else if(this.age>o.age){return 1;}else {return -1;}}//比較姓名//  return this.name.compareTo(o.name);}public class Test {public static void main(String[] args) {Student[] arr1 = new Student[3];arr1[0] = new Student(10, "王五");arr1[1] = new Student(8, "李四");arr1[2] = new Student(9, "張三");System.out.println("排序前:" + Arrays.toString(arr1));mysort(arr1);System.out.println("排序后:" + Arrays.toString(arr1));}}

在這里插入圖片描述

1.4 比較器的實現

在上面實現compareTo方法時,我們只能比較某一固定的屬性,比如年齡或者名字,
這比較有局限性,總不能當需要比較某一屬性時,再去修改類的實現。解決方案:當需要比較某一屬性時,就調用相關的類!

Comparator接口

在這里插入圖片描述
如圖所示:Comparator接口中有一個compare抽象方法。
我們可以創建不同的類來實現此接口,當需要比較不同的屬性值時,調用不同的類:

舉例:

//在單獨一個java文件中
package demo1;import java.util.Comparator;
//創建一個NameComparator類,實現Comparator接口
public class NameComparator implements Comparator<Student> {@Override//實現接口中的抽象方法,用于進行名字之間的比較!public int compare(Student o1, Student o2) {return o1.name.compareTo(o2.name);}
}

o1.name之所以可以引用compareTo方法是因為String類中重寫了compareTo方法:
在這里插入圖片描述

//在另一個java文件中
package demo1;import java.util.Comparator;
//實現Comparator接口
public class AgeComparator implements Comparator<Student> {@Overridepublic int compare(Student o1, Student o2) {return o1.age - o2.age;}
}
package demo1;import java.util.Arrays;
import java.util.Comparator;//接口的應用!
// 比較兩個對象的嘗試!
// 實現關于comparable接口!
class Student implements Comparable<Student> {String name;int age;public Student(int age, String name) {this.age = age;this.name = name;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}public int compareTo(Student o) {//比較年齡:if(this.age == o.age){return 0;}else if(this.age>o.age){return 1;}else {return -1;}}//比較姓名//  return this.name.compareTo(o.name);}public class Test {public static void main(String[] args) {Student[] arr1 = new Student[3];arr1[0] = new Student(10, "王五");arr1[1] = new Student(8, "李四");arr1[2] = new Student(9, "張三");System.out.println("排序前:" + Arrays.toString(arr1));//創建一個NameComparator對象。NameComparator nameComparator   =  new NameComparator();//進行名字間的比較!//Arrays.sort方法可以接收第二個參數!Arrays.sort(arr1,nameComparator);System.out.println("排序后:" + Arrays.toString(arr1));}}

這是按照姓名排序的結果:
在這里插入圖片描述

按照年齡排序,則調用AgeComparator類:

     System.out.println("排序前:" + Arrays.toString(arr1));AgeComparator ageComparator = new AgeComparator();//根據年齡進行比較!Arrays.sort(arr1,ageComparator);System.out.println("排序后:"+Arrays.toString(arr1));

排序后,年齡從小到大!
在這里插入圖片描述

我們通過創建不同的實現Comparator的類,并實現抽象方法compare,
當需要比較某一屬性時,即調用某一屬性對應類進行比較,這就是比較器的思想與實現!

二 深拷貝與淺拷貝

2.1 淺拷貝:

 所謂拷貝即將一個對象復制一份,由另一個引用指向新復制出的對象。

Cloneable接口:

要進行拷貝的類,需要先實現Cloneable接口.
在這里插入圖片描述

Cloneable接口是一個空接口,代表著實現此接口的類可以被拷貝!

clone方法:

clone方法是Object類中用來拷貝對象的方法。
在這里插入圖片描述

此方法被Native修飾,說明它是由C/C++等其他編程語言實現,不能查看其具體實現。

實現拷貝:

package demo1;public class Person implements Cloneable{   //實現空接口的類,代表可以拷貝String name;int age ;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}
}
package demo1;
// 淺拷貝public class Test {public static void main(String[] args) {Person person1 = new Person("張三",10);Person person2 =  person1.clone();}
}

(1)此時編譯器報警告:
在這里插入圖片描述

盡管clone方法的訪問權限是protected且Test也是Object的子類,但是當person1調用clone方法時,
是在Person類的外部,所以報錯。

解決這個問題,我們需要在子類中重寫clone方法:

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

(2) 此時編譯器又報警告:

在這里插入圖片描述
這是異常的問題,以后會闡述到,解決這個問題,在main方法后,加上一條語句即可:

在這里插入圖片描述
(3)編譯器又報警告的原因是:
方法的返回值類型為Object類型,我們需要將其強制為Person類型。

package demo1;
// 淺拷貝public class Test {public static void main(String[] args) throws CloneNotSupportedException{Person person1 = new Person("張三",10);Person person2 = (Person) person1.clone();System.out.println(person1);System.out.println(person2);}
}

在這里插入圖片描述

此刻,內存中情況如下:
在這里插入圖片描述

淺拷貝:

拷貝的情況講完了,那什么是淺拷貝呢?
當對象中有對象的創建時,此時只拷貝外部的對象,而不拷貝內部的對象,稱為淺拷貝!
舉例:

package demo1;
//創建一個Person類,實現接口
public class Person implements Cloneable{   //實現空接口的類,代表可以拷貝String name;int age ;Money money1 = new Money(10);public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}
//重寫克隆方法@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
package demo1;
//創建一個Money類
public class Money {int moneycount ;public Money(int moneycount) {this.moneycount = moneycount;}
}
package demo1;
// 淺拷貝public class Test {public static void main(String[] args) throws CloneNotSupportedException{Person person1 = new Person("張三",10);Person person2 = (Person) person1.clone();System.out.println("修改前:"+person1.money1.moneycount);System.out.println("修改前:"+person2.money1.moneycount);
//僅僅修改person2中的money對象的值,會不會改變person1中的值?person2.money1.moneycount = 20;System.out.println("修改后:"+person1.money1.moneycount);System.out.println("修改后:"+person2.money1.moneycount);}
}

在這里插入圖片描述

在內存中情況:
在這里插入圖片描述

這種未將對象 中的對象 拷貝的不徹底拷貝,我們稱為淺拷貝!

2.2 深拷貝:

深拷貝也就是將對象中的對象也進行拷貝, 
這需要對Person類中的clone方法進行重寫:
并且對Money類按照Person類中的格式進行重寫編寫

代碼:

//Person類
package demo1;public class Person implements Cloneable{   //實現空接口的類,代表可以拷貝String name;int age ;Money money1 = new Money(10);public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}@Override//重寫后的方法protected Object clone() throws CloneNotSupportedException {Person tmp = (Person) super.clone();    //誰調用了super方法,不需要this指定對象。//對于對象中的對象也進行拷貝!tmp.money1 = (Money) this.money1.clone();return tmp;}
}
//Money類
package demo1;public class Money implements Cloneable {int moneycount ;public Money(int moneycount) {this.moneycount = moneycount;}
//也重寫clone方法@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
//測試類
package demo1;
// 淺拷貝public class Test {public static void main(String[] args) throws CloneNotSupportedException{Person person1 = new Person("張三",10);Person person2 = (Person) person1.clone();System.out.println("修改前:"+person1.money1.moneycount);System.out.println("修改前:"+person2.money1.moneycount);person2.money1.moneycount = 20;System.out.println("修改后:"+person1.money1.moneycount);System.out.println("修改后:"+person2.money1.moneycount);}

在這里插入圖片描述
結果表明,此時深拷貝成功,修改person2中的money值,不會改變person1中的值!

在內存中的展示:
在這里插入圖片描述

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

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

相關文章

Python3 筆記:Python的所有關鍵字

查看Python的關鍵字首先需要用import導入keyword模塊 import keyword # 查看Python的所有關鍵字&#xff0c;先用import導入keyword模塊 print(keyword.kwlist) 運行結果&#xff1a; [False, None, True, and, as, assert, async, await, break, class, continue, def, …

MQ如何保證消息不丟失

MQ如何保證消息不丟失 問題分析具體分析及解決方案RabbitMQ生產者RabbitMQ配置消費者 KafkaKafka配置消費者 問題分析 從Kafka和RabbitMQ進行分析&#xff0c;MQ消息丟失的情況有生產者推送消息時數據丟失&#xff0c;MQ中間件宕機情況下數據丟失&#xff0c;消費者消費時消息…

GoLand map中的并發問題——為什么會造成并發問題?該怎么解決?

GoLand map中的并發問題——為什么會造成并發問題&#xff1f;該怎么解決&#xff1f; 問題提出原因解析具體原因競態檢測器 如何解決并發問題呢&#xff1f;方法一 &#xff1a; 使用sync.Mutex方法二&#xff1a; 使用sync.Map我們首先了解一下sync.Map的常用方法&#xff1a…

2024.5.24.python.exercise

# python文件操作 # f open("打字版.txt", "a", encoding"UTF-8") # writer input("請輸入你想要寫入到文件的內容") # f.write(writer) # f.flush() # f.close() # f open("打字版.txt", "r", encoding"…

代碼隨想錄算法訓練營第三十九天 | 738.單調遞增的數字、968.監控二叉樹 (可以跳過)

監控二叉樹同樣的等代碼隨想錄刷完后&#xff0c;再回頭來看&#xff0c;先跳過 738.單調遞增的數字 代碼隨想錄 解題思路 例如&#xff1a;98&#xff0c;一旦出現strNum[i - 1] > strNum[i]的情況&#xff08;非單調遞增&#xff09;&#xff0c;首先想讓strNum[i - 1]--…

游戲引擎支持腳本編程的好處

哈嘍呀&#xff0c;大家好&#xff0c;淼淼又來和大家見面啦&#xff0c;咱們今天來聊聊游戲引擎&#xff0c;游戲引擎作為現代游戲開發的核心&#xff0c;它集成了圖形渲染、物理模擬、音頻處理、動畫系統、輸入輸出控制等多種復雜技術于一體&#xff0c;為開發者提供了一個高…

ASP+ACCESS基于WEB網上留言板

摘要 本文概述了ACCESS數據庫及其相關的一些知識&#xff0c;著重論述ACCESS數據庫和ASP的中間技術&#xff0c;構建一個簡單的留言板。具體的實現是構造一個留言板系統&#xff0c;能很方便的和同學溝通和交流。留言板具有功能強大、使用方便的特點。用戶以個人的身份進入&am…

瑞芯微RV1126——人臉識別源碼分析

本節內容主要分為3部分&#xff0c;第一部分是流程結構圖;第二部分為人臉識別代碼流程;第三部分為具體的代碼分析。 1.流程結構圖 2.人臉識別代碼流程 1、人臉數據的初始化&#xff1a; init_all_rockx_face_data();init_face_data();2、創建rtsp會話&#xff0c;這里包括發…

一個典型的分布式緩存系統是什么樣的?no.32

分布式 Redis 服務 由于本課程聚焦于緩存&#xff0c;接下來&#xff0c;我將以微博內的 分布式 Redis 服務系統為例&#xff0c;介紹一個典型的分布式緩存系統的組成。 微博的 Redis 服務內部也稱為 RedisService。RedisService 的整體架構如圖所示。主要分為Proxy、存儲、集…

產品推薦 | 基于Xilinx XCKU115的半高PCIe x8 硬件加速卡

一、板卡概述 本板卡系我公司自主研發&#xff0c;采用Xilinx公司的XCKU115-3-FLVF1924-E芯片作為主處理器&#xff0c;主要用于FPGA硬件加速。板卡設計滿足工業級要求。如下圖所示&#xff1a; 二、功能和技術指標 板卡功能 參數內容 主處理器 XCKU115-3-FLVF1924-E 板卡…

UE4/UE5像素流送云推流:多人訪問不穩定、畫面糊、端口占用多等

UE4/UE5想要實現網頁訪問&#xff0c;很多工程師會選擇guan方的像素流送。但這個技術要求在模型開發初期就接入。對于一些已有UE模型是無法進行流化的。雖然也可以解決新UE模型的網頁訪問問題&#xff0c;但在實際的應用中&#xff0c;點量云流也收到很多反饋說&#xff0c;使用…

netty-socketio 集群隨記

實現netty-socketio集群的方式 代碼實例 PostConstructpublic void subscribe() {pubSubStore.subscribe(PubSubType.DISPATCH, new PubSubListener<DispatchMessage>() {Overridepublic void onMessage(DispatchMessage message) {log.debug("subscribe: {}"…

Python爬取B站視頻:封裝一下

&#x1f4da;博客主頁&#xff1a;knighthood2001 ?公眾號&#xff1a;認知up吧 &#xff08;目前正在帶領大家一起提升認知&#xff0c;感興趣可以來圍觀一下&#xff09; &#x1f383;知識星球&#xff1a;【認知up吧|成長|副業】介紹 ??如遇文章付費&#xff0c;可先看…

大數據Hadoop之-工具HIVE(一)

大數據Hadoop之——數據倉庫Hive HIVE介紹Hive是基于Hadoop的一個數據倉庫(Data Aarehouse,簡稱數倉、DW),可以將結構化的數據文件映射為一張數據庫表,并提供類SQL查詢功能。是用于存儲、分析、報告的數據系統。 在Hadoop生態系統中,HDFS用于存儲數據,Yarn用于資源管理…

解釋Spring Bean的生命周期

Spring Bean的生命周期涉及到Bean的創建、配置、使用和銷毀的各個階段。理解這個生命周期對于編寫高效的Spring應用和充分利用框架的功能非常重要。下面是Spring Bean生命周期的主要步驟&#xff1a; 1. 實例化Bean Spring容器首先將使用Bean的定義&#xff08;無論是XML、注…

使用Golang調用騰訊云郵件模版發送郵件

文章目錄 一、騰訊云郵件模版創建1.1 發信域名配置1.2 發信地址設置1.3 發信模版設置 二、通過Golang發送郵件2.1 代碼示例2.2 代碼說明 三、常見問題3.1 UnsupportedRegion3.2 InvalidTemplateID 本文檔介紹了如何使用Golang編寫代碼&#xff0c;通過騰訊云郵件服務&#xff0…

【Linux】中的常見的重要指令(中)

目錄 一、man指令 二、cp指令 三、cat指令 四、mv指令 五、more指令 六、less指令 七、head指令 八、tail指令 一、man指令 Linux的命令有很多參數&#xff0c;我們不可能全記住&#xff0c;我們可以通過查看聯機手冊獲取幫助。訪問Linux手冊頁的命令是 man 語法: m…

白嫖免費圖床!CloudFlare R2太香了!

1 為啥要折騰搭建一個專屬圖床&#xff1f; 技術大佬寫博客都用 md 格式&#xff0c;要在多平臺發布&#xff0c;圖片就得有外鏈后續如博客遷移&#xff0c;國內博客網站如掘金&#xff0c;簡書&#xff0c;語雀等都做了防盜鏈&#xff0c;圖片無法遷移 2 為啥選擇CloudFlare…

對話太醫管家CEO徐晶:數字化技術正在為健康管理行業帶來新平衡丨數字思考者50人...

ITValue 鈦媒體特別專題策劃《數字思考者50人》&#xff1a;探訪中國深刻的數字化思考者群體。我們理解的“TechThinker”&#xff0c;涵蓋了中國數字化浪潮中的技術踐行者、政策制定者與投資決策者。在這場長達10年的乘風破浪中&#xff0c;每個人都在分享技術進步的果實&…

leetcode445-Add Two Numbers II

題目 給你兩個 非空 鏈表來代表兩個非負整數。數字最高位位于鏈表開始位置。它們的每個節點只存儲一位數字。將這兩數相加會返回一個新的鏈表。 你可以假設除了數字 0 之外&#xff0c;這兩個數字都不會以零開頭。 示例1&#xff1a; 輸入&#xff1a;l1 [7,2,4,3], l2 [5,6…