【Java基礎篇 | 面向對象】—— 聊聊什么是接口(下篇)

個人主頁:兜里有顆棉花糖
歡迎 點贊👍 收藏? 留言? 加關注💓本文由 兜里有顆棉花糖 原創
收錄于專欄【JavaSE_primary】
本專欄旨在分享學習JavaSE的一點學習心得,歡迎大家在評論區交流討論💌
在這里插入圖片描述

上篇(【Java基礎篇 | 面向對象】—— 聊聊什么是接口(上篇))中我們已經對Java接口中有了一定的了解。本篇中我們將對Java接口進行更進一步的學習。加油吧!!!

目錄

  • 一、接口使用實例
    • 比較器(Comparator)
  • 二、Clonable接口和深拷貝
    • 淺拷貝
    • 深拷貝
  • 三、Object類
    • 對象比較equals()方法
    • hashcode()方法

一、接口使用實例

首先我們要使用記住一句話,對象與對象之間進行比較的話一定要實現對應的接口。只有我們實現了對應的接口之后才能證明這兩個對象是可比較的

現在有一個整數數組,我們當然可以使用sort()方法來對這個整數數組進行升序或者降序排序。但是如果我們現在有一個學生類對象呢我們是無法直接拿兩個學生類對象進行直接排序的。此時我們應該參照學生類中的某個屬性來對這個學生類對象進行排序以達到我們想要的排序效果。

現在我們就以學生類中的年齡屬性來進行排序吧:

我們在進行自定義類型的對象比較的時候,一定要實現可以比較的接口。比如如果我們的Student類實現Comparable接口, 并實現其中的compareTo方法。否則的話自定義類型的對象是無法進行比較的。

如下圖就是我們實現的Comparable接口中的compareTo方法。
在這里插入圖片描述
如果我們要比較兩個對象的引用的話(兩個學生類對象按照年齡來進行排序),我們可以這樣來寫,請看:
在這里插入圖片描述
如果我們要比較的是一個學生類對象數組的話(按照年齡來進行比較),我們可以這樣,請看:
在這里插入圖片描述
運行結果如下:
在這里插入圖片描述

現在我們來試著使用自己寫一個排序方法(冒泡排序)來對學生類對象進行排序。
請看下面我們自己實現的冒泡排序來對學生類對象按照年齡進行排序。代碼如下:
在這里插入圖片描述
運行結果如下:
在這里插入圖片描述
現在我們來對上述冒泡排序中的代碼進行解釋:
排序的時候我們排序的是一個學生數組(按照年齡來進行排序),所以我們在進行排序的時候底層一定會去調用compareTo方法,所以冒泡排序中的參數一定為Comparable[] comparables,即接口數組。另外array數組(即學生類對象數組)中的每個元素都是一個學生類對象,而且每個學生類對象都實現了compareTo方法

比較器(Comparator)

好了,現在我們換一種排序的寫法。上述學生類中有年齡也有分數,如果我們一會想依據年齡進行排序,一會又想用分數進行排序的話,如果按照compareTo()方法完成上述排序的話,那么根據我們比較依據的不同那么compareTo()方法中的內容也是不一樣的(即我們需要修改compareTo方法中的內容)。
在這里插入圖片描述
請看上圖,上圖中的compareTo()只能對學生類對象中的年齡進行排序而無法對學生類中的成績進行排序,所以排序的內容就比較單一。此時我們就需要Comparator接口

好了,現在我們利用Comparator接口來實現學生類對象的排序工作,代碼如下圖,請看:
在這里插入圖片描述

具體代碼如下,請看:

import com.sun.javaws.IconUtil;
import java.util.Comparator;class Student{public String name;public int age;public double score;public Student(String name, int age, double score) {this.name = name;this.age = age;this.score = score;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", score=" + score +'}';}
}
// 這里我們利用了解耦的思想
class AgeComparator implements Comparator<Student> {@Overridepublic int compare(Student o1, Student o2) {return o1.age - o2.age;}
}
class ScoreComparator implements Comparator<Student>{@Overridepublic int compare(Student o1,Student o2) {return (int)(o1.score - o2.score);}
}
public class Test {public static void main(String[] args) {Student student1 = new Student("jkl",1,87.3);Student student2 = new Student("ajk",2,87.3);// 依據年齡進行比較AgeComparator ageComparator = new AgeComparator();int ret = ageComparator.compare(student1,student2);System.out.println("ret = " + ret);// 依據成績進行比較ScoreComparator scoreComparator = new ScoreComparator();int ret2 = scoreComparator.compare(student1,student2);System.out.println("ret = " + ret2);}
}

運行結果如下:
在這里插入圖片描述
對比一下這兩種接口(Comparator接口Comparable接口):經過上述的演示,我們不難發現Comparator接口更加的靈活。

二、Clonable接口和深拷貝

淺拷貝

淺拷貝概念:淺拷貝是指在對一個對象進行拷貝時,只拷貝對象本身和其中的基本數據類型,而不拷貝對象內部的引用類型。因此,在淺拷貝的對象中,引用類型的變量指向的依舊是原始對象中的引用。

下面來進行舉例。

現在我們有一個Student學生類,如下圖:
在這里插入圖片描述
同時新創建了一個學生類對象student1,該對象對應的內存結構圖如下:
在這里插入圖片描述
現在我們想要把student引用所指向的對象克隆出來一份,如下圖的克隆方式是錯誤的:
在這里插入圖片描述
要解決上述錯誤的話,我們需要修改三個地方。如下圖在這里插入圖片描述
好了,現在重新運行一下程序,發現還是會報錯,請看:
在這里插入圖片描述
我們需要實現一個接口以證明當前的類是可以進行克隆的。
在這里插入圖片描述
運行結果如下:
在這里插入圖片描述

淺拷貝的對象中,引用類型的變量指向的依舊是原始對象中的引用。請看舉例:
在這里插入圖片描述
運行結果如下:
在這里插入圖片描述
解釋:通過調用clone()方法,創建了student1的一個克隆對象student2。克隆的實現是通過調用Object類的clone()方法來完成的。
輸出結果顯示了兩次student1.m.money和student2.m.money的值,分別為52.0。這是因為淺拷貝只是簡單地復制字段的值,而對于引用類型的字段,只復制了引用地址,并沒有復制該引用指向的實際對象。因此,student1和student2的m字段引用同一個Money對象。

在這里插入圖片描述

深拷貝

深拷貝是指在對一個對象進行拷貝時,不僅拷貝對象本身和其中的基本數據類型,同時也拷貝對象內部的引用類型。因此,在深拷貝的對象中,引用類型的變量指向的是全新的對象。

好了,現在來總結一下:clone方法是Object類中的一個方法,調用這個方法可以創建一個對象的 “拷貝”. 但是要想合法調用 clone 方法,必須要先實現Clonable接口, 否則就會拋出CloneNotSupportedException異常.

下面是深拷貝的代碼舉例:

class Money implements Cloneable {public double money;@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
class Student implements Cloneable {public int age;public Money m = new Money();public Student(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"age=" + age +'}';}@Overrideprotected Object clone() throws CloneNotSupportedException {//return super.clone();Student tmp = (Student)super.clone();tmp.m = (Money)this.m.clone();return tmp;}
}
public class Test {public static void main(String[] args) throws CloneNotSupportedException {Student student1 = new Student(21);student1.m.money = 52.0;Student student2 = (Student)student1.clone();System.out.println(student1.m.money);System.out.println(student2.m.money);System.out.println("分割線--------------");student1.m.money = 18.8;System.out.println(student1.m.money);System.out.println(student2.m.money);}
}

運行結果如下:
在這里插入圖片描述
在這里插入圖片描述
好了,現在我們再來回顧一下什么是深拷貝:深拷貝就是在拷貝對象的同時創建一個新的對象,并將原對象中的所有數據逐個拷貝到新對象中去,包括成員變量引用的其他對象。這樣可以確保原對象和拷貝對象之間的數據相互獨立,互不影響。

三、Object類

在Java中,所有的類都直接或間接地繼承自java.lang.Object類。Object類是Java類層次結構中的根類,它提供了一些通用的方法和功能,可以在所有類中使用。可以這么認為,Object類是所有類的父類。所以在Java中,即使我們不顯式地在類聲明中使用extends關鍵字繼承Object類,所有的類仍然會隱式地繼承Object類。這是因為Object類是Java類層次結構中的根類,所有的類都直接或間接繼承自它。

對象比較equals()方法

在這里插入圖片描述
如上圖:使用equals()方法來比較兩個對象是否相等。
如果在Student類中沒有重寫equals()方法,則默認會使用Object類中的equals()方法,它執行的是比較對象引用的相等性(即比較兩個對象在內存中的地址是否相同)。
因此,上圖中的代碼的最終結果就是False但是,如果我想要按照我們自己的方式來比較這兩個對象是否相等的話我們就需要自己去重寫equals()方法

現在,如果以兩個對象的年齡是否相等為依據來判斷兩個對象是否相等的話,重寫的equals()方法如下:
在這里插入圖片描述
如果我們相比較對象中的內容是否相等的話,我們需要根據自己的判斷依據來重寫Object類中的equals()方法

hashcode()方法

hashcode()方法用于返回對象的hash碼,相當于對象的標識符,它可以將對象轉換為整數以便更好的比較、存儲對象。

好了,現在來舉個栗子,假設當兩個對象的年齡是一樣的話,那么我們認為這兩個對象存儲的位置是相同的,請看代碼:
在這里插入圖片描述
運行結果如下:
在這里插入圖片描述
如上圖中的運行結果,雖然兩個對象的年齡是不同的,但是這兩個對象存儲的位置確實相同的,這與我們判斷兩個對象是否相同的判斷依據發生了沖突。
此時我們就需要自己重寫hashcode()方法。

最終代碼如下,請看:

import java.util.Objects;class Money implements Cloneable {public double money;@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Money money1 = (Money) o;return Double.compare(money1.money, money) == 0;}@Overridepublic int hashCode() {return Objects.hash(money);}
}
class Student implements Cloneable {public int age;public Money m = new Money();public Student(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"age=" + age +'}';}@Overrideprotected Object clone() throws CloneNotSupportedException {//return super.clone();Student tmp = (Student)super.clone();tmp.m = (Money)this.m.clone();return tmp;}@Overridepublic boolean equals(Object obj) {Student student = (Student)obj;return age == student.age;}@Overridepublic int hashCode() {return Objects.hash(age, m);}
}
public class Test {public static void main(String[] args) {Student student1 = new Student(19);Student student2 = new Student(19);System.out.println(student1.hashCode());System.out.println(student2.hashCode());}
}

運行結果如下:
在這里插入圖片描述
此時就說明這兩個對象的位置是相同的。

小總結:

  • hashcode()方法用來確定對象在內存中存儲的位置是否相同。
  • 實際上,hashcode()在散列表中才會用到(在散列表中hashcode()的作用就是獲取對象的散列碼,進而確定該對象在散列表中的位置);然而hashcode()在其它情況下沒多大用。
  • 如果一個類沒有重寫hashCode()equals() 方法,那么它將使用從Object類繼承而來的默認實現。如果默認實現的hashCode()equals()方法不符合我們的需求,此時我們就需要自己重寫hashCode()equals()方法。
  • 定義一個自定義類型時,應該養成重寫hashCode()equals()方法的習慣。

好了,本文到這里就結束了,再見啦友友們!!!
在這里插入圖片描述

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

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

相關文章

SpringBoot 自動裝配原理詳解

什么是 SpringBoot 自動裝配&#xff1f; 我們現在提到自動裝配的時候&#xff0c;一般會和 Spring Boot 聯系在一起。但是&#xff0c;實際上 Spring Framework 早就實現了這個功能。Spring Boot 只是在其基礎上&#xff0c;通過 SPI 的方式&#xff0c;做了進一步優化。 Spr…

解決npm install時報:gyp ERR! configure error

報錯內容&#xff1a; npm ERR! gyp ERR! cwd C:\Users\zccbbg\code\my\examvue\node_modules\node-sass npm ERR! gyp ERR! node -v v16.13.1 npm ERR! gyp ERR! node-gyp -v v3.8.0 npm ERR! gyp ERR! not ok npm ERR! Build failed with error code: 1 解決辦法&#xff1a;…

自行編寫一個簡單的shell!

本文旨在編寫一個簡單的shell外殼程序&#xff01;功能類似于shell的一些基本操作&#xff01;雖然不能全部實現shell的一些功能&#xff01;但是通過此文章&#xff0c;自己寫一個簡單的shell程序也是不成問題&#xff01;并且通過此文章&#xff0c;可以讓讀者對linux中一些環…

C#基礎面試題集

C#基礎 1. 簡述值類型和引用類型有什么區別2. C# String類型比 stringBuilder 類型的優勢是什么?3.面向對象的三大特點4.請簡述private&#xff0c;public&#xff0c;protected&#xff0c;internal的區別5.結構體和類6.請描述Interface與抽象類之間的不同7.在類的構造函數前…

藍橋杯:貨物擺放--因數存到數組里的技巧--減少運算量的方法

小藍有一個超大的倉庫&#xff0c;可以擺放很多貨物。 現在&#xff0c;小藍有 n 箱貨物要擺放在倉庫&#xff0c;每箱貨物都是規則的正方體。小藍規定了長、寬、高三個互相垂直的方向&#xff0c;每箱貨物的邊都必須嚴格平行于長、寬、高。 小藍希望所有的貨物最終擺成一個大…

go自帶rpc框架生產環境使用demo

基礎使用 序列化使用自帶gob協議 server package mainimport ("net""net/rpc" )// 定義一個handler結構體 type HelloService struct { }// 定義handler方法,大小寫&#xff0c;參數&#xff0c;返回值都是固定的&#xff0c;否則無法注冊 func (receiv…

數據庫事務:保障數據一致性的基石

目錄 1. 什么是數據庫事務&#xff1f; 1.1 ACID特性解析 2. 事務的實現與控制 2.1 事務的開始和結束 2.2 事務的隔離級別 3. 并發控制與事務管理 3.1 并發控制的挑戰 3.2 鎖和并發控制算法 4. 最佳實踐與性能優化 4.1 事務的劃分 4.2 批處理操作 5. 事務的未來發展…

Qt OpenCV 學習(文章鏈接匯總)

Qt OpenCV 學習&#xff08;一&#xff09;&#xff1a;環境搭建 Qt OpenCV 學習&#xff08;二&#xff09;&#xff1a;兩個簡單圖片識別案例 Qt OpenCV 學習&#xff08;三&#xff09;&#xff1a;跟蹤視頻中的運動物體 Qt OpenCV 學習&#xff08;四&#xff09;&#xff…

SpringSecurity6 | 自定義登錄頁面

?作者簡介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;熱愛Java后端開發者&#xff0c;一個想要與大家共同進步的男人&#x1f609;&#x1f609; &#x1f34e;個人主頁&#xff1a;Leo的博客 &#x1f49e;當前專欄&#xff1a; Java從入門到精通 ?特色專欄&#xf…

高工氫電年會 | 未勢能源解超朋博士受邀出席并做主題演講

12月4日&#xff0c;以“戰略重構 商業覺醒”為主題的2023高工氫電年會在深圳舉辦&#xff0c;未勢能源副總裁解超朋博士受邀出席開幕式論壇&#xff0c;以《把握機遇、直面挑戰&#xff0c;迎接氫車規模化推廣時代》為主題發表演講&#xff0c;并參與圓桌論壇研討。 氫勢已來&…

【Linux】resolv.conf 文件

resolv.conf resolv.conf 文件 是 DNS 的 client 端使用的文件&#xff0c;用于設置 DNS 服務器的 ip 地址以及 DNS 域名&#xff0c;還可以配置域名搜索順序等等。主要包含如下關鍵字&#xff1a;nameserver、domain、search、sortlist、options。設置的格式都是 關鍵字空格 …

管理類聯考——數學——真題篇——按知識分類——數據

文章目錄 排列組合2023真題&#xff08;2023-05&#xff09;-數據分析-排列組合-組合-C運算-至少-需反面思考真題&#xff08;2023-08&#xff09;-數據分析-排列組合-相鄰不相鄰-捆綁法插空法-插空法注意空位比座位多1個&#xff0c;是用A&#xff1b;捆綁法內部排序用A&#…

Linux(centos, ubuntu) 快速安裝anaconda;5秒安裝anaconda

1.下載Anaconda安裝腳本: 首先&#xff0c;訪問Anaconda的官方下載頁面&#xff1a;https://www.anaconda.com/products/distribution 在頁面上&#xff0c;選擇適用于Linux的Python 3.x版本的Anaconda安裝腳本。也可以使用wget或curl命令從終端下載。示例&#xff1a; wget …

2023中國(海南)國際高爾夫旅游文化博覽會 暨國際商界峰層·全球華人高爾夫精英巡回賽 全國潁商自貿港行盛大啟幕

2023中國&#xff08;海南&#xff09;國際高爾夫旅游文化博覽會&#xff08;以下簡稱“海高博”&#xff09;暨全國潁商走進海南自貿港于12月7-9日在海口觀瀾湖盛大開幕。該活動由中國國際貿易促進委員會海南省委員會、海南省旅游和文化廣電體育廳主辦&#xff0c;中國國際商會…

C語言中getchar函數

在 C 語言中&#xff0c;getchar() 是一個標準庫函數&#xff0c;用于從標準輸入&#xff08;通常是鍵盤&#xff09;讀取單個字符。它的函數原型如下&#xff1a; int getchar(void);getchar() 函數的工作原理如下&#xff1a; 當調用 getchar() 函數時&#xff0c;它會等待…

最新版本11.17的YOLOv8加入注意力方法

本文基于11.17版本,以往版本略有不同,可查看改進YOLOv8,教你YOLOv8如何添加20多種注意力機制進行參考 放入注意力代碼,以biformer注意力為例 import torch import torch.nn as nn import torch.nn.functional as Fdef position(H, W, is_cuda=

探索 Python 中鏈表的實現:從基礎到高級

# 更多資料獲取 &#x1f4da; 個人網站&#xff1a;ipengtao.com 鏈表是一種基礎的數據結構&#xff0c;它由一系列節點組成&#xff0c;每個節點都包含數據和指向下一個節點的引用。在Python中&#xff0c;可以使用類來實現鏈表&#xff0c;本文將介紹如何實現鏈表&#xff…

c語言編程題經典100例——(90~95例)

1,寫一個函數&#xff0c;實現數字的加密和解密。 下面是一個簡單的C語言函數&#xff0c;可以實現數字的加密和解密。這個函數采用簡單的加密算法&#xff0c;將輸入的數字乘以一個固定的密鑰&#xff0c;然后加上一個固定的偏移量。解密過程就是將加密后的數字減去偏移量&am…

《C++新經典設計模式》之第18章 備忘錄模式

《C新經典設計模式》之第18章 備忘錄模式 備忘錄模式.cpp 備忘錄模式.cpp #include <iostream> #include <vector> #include <memory> using namespace std;// 保存對象內部狀態&#xff0c;必要時恢復 // 在不破壞封裝性的前提下&#xff0c;捕獲對象的內部…

(C)一些題11

1. #include<stdio.h> #include<string.h> void main() { char *s1"ABCDEF"&#xff0c;*s2"aB"&#xff1b; s1; s2; puts(s1)&#xff1b; puts(s2)&#xff1b; printf("%d\n",strcmp(s1,s2))&#xff1b; } 答案&#xff1…