java加強 -泛型

概念

定義類、接口、方法時,同時聲明了一個或多個類型變量(如<E>),稱為泛型類、泛型接口、泛型方法、它們統稱為泛型。

語法

public class ArrayList<E>{}

E可以接收不同類型的數據,可以是字符串,也可以是學生類等東西。

作用:泛型提供了在編譯階段約束所能操作的數據類型,并自動進行檢查的能力,這樣可以避免強制類型轉換,及其可能出現的異常。

接下來用常見API,ArrayList集合舉例

package GenericityDemo;import java.util.ArrayList;public class GenericDemo1 {public static void main(String[] args) {
//        //認識泛型
//        ArrayList list = new ArrayList();           //沒有使用泛型,存儲任意類型數據
//        list.add("hello");
//        list.add(100);
//        list.add(true);
//        //獲取數據
//        for (int i = 0; i < list.size(); i++)
//        {
//            Object obj = list.get(i);       //必須用Object接收,因為存儲的任意類型數據
//            //數據轉型處理
//            String s = (String) list.get(i);//運行到整型時程序會崩,因此最好要統一數據類型
//            System.out.println(s);
//        }ArrayList<String> list = new ArrayList<String>();       //泛型約束,只能存儲String類型數據list.add("hello");list.add("world");//list.add(90);     //類型不是泛型約束的類型,報錯for (int i = 0; i < list.size(); i++){String s = list.get(i);     //類型確定,不用轉型System.out.println(s);      //不會出現異常}}
}

一、泛型類

泛型類(Generic Class)?是通過類型參數化定義的類,其核心作用是通過類型抽象實現代碼的通用性、類型安全性和靈活性。

語法

修飾符 class 類名<類型變量,類型變量....>{}
public class ArrayList<E>{
......
}

示例

創建一個ArrayList集合類(其實就是在自己的類里用之前的API,但接收的數據類型由我們限制)

package GenericityDemo;import java.util.ArrayList;public class MyArrayList <E>{private ArrayList list = new ArrayList();public boolean add(E e){list.add(e);return true;}public boolean remove(E e){return  list.remove(e);}@Overridepublic String toString() {return list.toString();}
}
package GenericityDemo;public class GenericDemo2 {public static void main(String[] args) {//目標:學會自定義泛型類//需求:模擬ArrayList集合,自定義一個集合MyArrayListMyArrayList<String> list = new MyArrayList<>();//jdk7支持后面不寫泛型類型list.add("java");list.add("后端");System.out.println(list);}
}

類型變量建議使用大寫的英文字母,常用的有:E、T、K、V等

E:常用于集合類(如?ListSet),強調泛型參數是容器內的元素。

T:當泛型類或方法不限制具體類型時,常用?T?作為默認類型占位符。

K/V:用于鍵值對數據結構(如?Map)中,明確區分鍵和值的類型。

二、泛型接口

泛型接口(Generic Interface)?是通過類型參數化定義的接口,其核心作用是通過類型抽象提高代碼的復用性、類型安全性和靈活性。

修飾符 interface 接口名<類型變量,類型變量...>{
}
public interface A<E>{
...
}

示例

對學生數據/老師數據都要進行增刪查改操作。

定義一個泛型接口可以接學生或老師對象進行操作,可以實現一個方法操作兩個角色。

package GenericityDemo3;public interface Data<T> {
//    void add(Student s);
//    void add(Teacher t);//類型約定死了,,只能存Student或Teacher//利用泛型接口void add(T t);      //此時泛型可以為Teacher也能為Studentvoid delete(T t);void update(T t);T query(int id);
}

(此示例并沒有真正實現增刪查改操作,只為示范)

package GenericityDemo3;public class Student {
}
package GenericityDemo3;public class Teacher {
}

創造兩個類用于實現Data,一個實現老師操作,一個實現學生操作

package GenericityDemo3;public class TeacherData implements Data<Teacher>{//操作老師數據@Overridepublic void add(Teacher teacher) {}@Overridepublic void delete(Teacher teacher) {}@Overridepublic void update(Teacher teacher) {}@Overridepublic Teacher query(int id) {return null;}
}
package GenericityDemo3;public class StudentData implements Data<Student>{//專門操作學生對象@Overridepublic void add(Student student) {}@Overridepublic void delete(Student student) {}@Overridepublic void update(Student student) {}@Overridepublic Student query(int id) {return null;}
}
package GenericityDemo3;public class GenericDemo3 {public static void main(String[] args) {//目標:搞清楚泛型接口的基本應用//需求:項目需要對學生數據/老師數據都要進行增刪查改操作StudentData studentData = new StudentData();studentData.add(new Student());      //添加學生數據.對學生操作Student s = studentData.query(1001);}
}

通過泛型接口,可以為不同類型的數據定義統一的處理邏輯,同時避免強制類型轉換和運行時類型錯誤。

三、泛型方法

泛型方法(Generic Method)?是通過在方法簽名中聲明類型參數來實現的方法級別泛型化。它與泛型類的主要區別在于作用范圍:泛型方法的類型參數僅作用于該方法內部,而非整個類。

語法

修飾符<類型變量,類型變量,...>返回值類型 方法名(形參列表){}

示例

現在我需要一個方法將數組的內容打印出來

package GenericDemo4;public class GenericDemo4 {//目標:理解泛型方法public static void main(String[] args) {//需求:打印任意數組的內容String[] arr1 = {"hello","world","java"};printArray(arr1);Student[] arr2 = new Student[3];//printArray(arr2);//只能接收String類型數組Student s1 = getMax(arr2); printArray2(arr1);getMax(arr2);       //泛型方法,可以接收任意類型的數組,避免強轉}public static  void printArray(String[] arr){for (int i = 0; i < arr.length; i++) {System.out.println(arr[i] + " ");}}public static <T> void printArray2(T[] arr){for (int i = 0; i < arr.length; i++) {System.out.println(arr[i] + " ");}}public static <T> T getMax(T[] name){return null;}
}

上述代碼有兩個方法,一個是printArray一個是printArray2,但printArray有一個缺點就是只能打印字符串數組的內容,若是其他數組則無法接收。因此,我們可以做一個泛型方法即printArray2,它可以接收String數組也可以接收Student數組,實現了一個方法解決多個問題。

四、通配符與上下限

當我們要傳的參數為多個集合,每個集合都是繼承于某個父類的子類的集合時,我們就可以通過使用通配符來接收不同的子類集合。(注:例如兩個集合為ArrayList<Cat>和ArrayList<Dog>,不能用ArrayList<Animal>接收,因為他們本質上是不同的集合,雖然他們的子類繼承了同一個父類)

示例

package GenericDemo4;public class Car {
}
package GenericDemo4;public class BYD extends Car{}
package GenericDemo4;public class BMW extends Car{
}
package GenericDemo4;import java.util.ArrayList;public class GenericDemo5 {public static void main(String[] args) {//目標:理解通配符和上下限ArrayList<BYD> byds = new ArrayList<>();byds.add(new BYD());byds.add(new BYD());byds.add(new BYD());//go(byds);           //報錯不具備通用性ArrayList<BMW> bmws = new ArrayList<>();bmws.add(new BMW());bmws.add(new BMW());bmws.add(new BMW());go(bmws);}//模擬極品飛車游戲//雖然比亞迪和寶馬是Car的子類,但ArrayList<BYD>和ArrayList<BMW>和ArrayList<Car>是不同的,因此不能用多態
//    public static void go(ArrayList<BMW> cars)
//    {
//
//    }//通配符,在使用泛型時代表一切類型public static void go(ArrayList<?> cars){}
}

然而,若是這么寫這個方法能接收的集合范圍又太大了,連貓和狗都可以進這個開汽車的方法,因此需要使用上下限來加以限制。

? extends Car ?能接收Car或者Car的子類(泛型上限)
? super Car ?能接收Car或者Car的父類(泛型下限)

package GenericDemo4;import java.util.ArrayList;public class GenericDemo5 {public static void main(String[] args) {//目標:理解通配符和上下限ArrayList<BYD> byds = new ArrayList<>();byds.add(new BYD());byds.add(new BYD());byds.add(new BYD());//go(byds);           //報錯不具備通用性ArrayList<BMW> bmws = new ArrayList<>();bmws.add(new BMW());bmws.add(new BMW());bmws.add(new BMW());go(bmws);}//模擬極品飛車游戲//雖然比亞迪和寶馬是Car的子類,但ArrayList<BYD>和ArrayList<BMW>和ArrayList<Car>是不同的,因此不能用多態
//    public static void go(ArrayList<BMW> cars)
//    {
//
//    }//通配符,在使用泛型時代表一切類型//為了防止將狗,貓等不屬于車的類型傳入方法,使用泛型的上下限限制//? extends Car ?能接收Car或者Car的子類(泛型上限)//? super Car ?能接收Car或者Car的父類(泛型下限)public static void go(ArrayList<? extends Car> cars){}
}

這樣,就能將這個方法限制在接收汽車類的子類了。

五、泛型支持的數據類型

泛型不支持基本的數據類型,即int,double等數據類型,原因是泛型工作在編譯階段,編譯結束后系統會進行泛型擦除,所有類型都會轉變為Object類型。而Object是對象類型,接收的是對象,數字等類型不是對象,因此不接收基本的數據類型。為了能夠兼容基本的數據類型,java的庫里添加了包裝類,用于將基本數據類型變為對象。

包裝類有8種。

int -> Integer char -> Character ,其它的都是首字母大小寫。

package GenericDemo5;import java.util.ArrayList;
import java.util.Objects;public class GenericDemo5 {public static void main(String[] args) {//目標:搞清楚泛型和集合不支持基本數據類型,只能支持對象類型(引用類型)//ArrayList<double> list = new ArrayList<>();   //報錯,不支持//泛型擦除:泛型工作在編譯階段,等編譯后泛型就沒用了,所以泛型在編譯后都會被擦除。所有類型會恢復為Object類型。//Object是對象類型,不能直接指向某個數,只能指向某個對象。//因此要使用包裝類,比如Integer、Double、Character、Boolean等。//包裝類的作用:把基本數據類型包裝成對象類型。//ArrayList<int> list = new ArrayList<>();//list.add(12);     //12不是對象,報錯ArrayList<Integer> list = new ArrayList<>();list.add(12);           //自動裝箱,把基本數據類型12包裝成Integer對象。int rs= list.get(0);        //自動拆箱,把Integer對象12拆箱成基本數據類型。//把基本數據類型變成包裝類對象//手工包裝//Integer i = new Integer(12);//從jdk9開始,這個方法被淘汰了(過時)//推薦用valueOf的原因:valueOf方法中緩存了-128~127的數值,重復創建這個范圍內的數字時不會創建新對象,而是直接返回緩存中的對象。//緩存對象范圍是-128~127,如果超過這個范圍,就會創建新的對象。//更優雅,節約內存。Integer i = Integer.valueOf(12);    //此時i為對象,里面存儲的是12Integer i2 = Integer.valueOf(12);System.out.println(i == i2);        //ture, 因為i和i2是同一個對象//自動裝箱Integer i3 = 12;        //與Integer i = Integer.valueOf(12)一個意思Integer i4 = 12;System.out.println(i3 == i4);//自動拆箱:把包裝類型的對象直接給基本類型的數據int i5 = i3;System.out.println(i5);System.out.println("========================================================");//包裝類新增的功能//1、把基本類型的數據變成字符串int j=23;String rs1 = Integer.toString(j);System.out.println(rs1+1);      //不是24,說明已經是字符串Integer i6=j;String rs2 = i6.toString();System.out.println(rs2+1);String  rs3 = i6+"";        //直接加""轉換為字符串System.out.println(rs3+1);System.out.println("========================================================");//把字符串數值轉換成對應的基本數據類型String str = "123";int i1 = Integer.parseInt(str);int i9 = Integer.valueOf(str);System.out.println(i1+1);System.out.println(i9+1);}
}

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

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

相關文章

C++ 項目 -- 高并發內存池

目錄 項目介紹 內存池概念 池化技術 內存池 內存池主要解決的問題 malloc 定長內存池 申請內存 釋放內存 整體框架設計 thread cache 申請內存 釋放內存 central cache 申請內存 釋放內存 page cache 申請內存 釋放內存 大塊內存申請實現 定長內存…

高效C/C++之九:Coverity修復問題:關于數組操作 和 內存操作

【關注我&#xff0c;后續持續新增專題博文&#xff0c;謝謝&#xff01;&#xff01;&#xff01;】 上一篇我們講了&#xff1a; 這一篇我們開始講&#xff1a; 高效C/C之九&#xff1a;Coverity修復問題&#xff1a;關于數組操作 和 內存操作 目錄 【關注我&#xff0c;后…

vfrom表單設計器使用事件機制控制字段顯示隱藏

1. 使用表單設計器進行debug調試 依據 vform3.0開發者文檔 https://www.ganweicloud.com/docs/6.1.0/pages/d3e6d9/ 對switch組件設置事件邏輯 調試中

iPhone 和 Android 在日期格式方面的區別

整篇文章由iPhone 和 Android 在日期格式方面有所不同引起,大致介紹了,兩種時間標準,以及在 JavaScript 下的格式轉換方法。 Unix 時間戳是從1970年1月1日(UTC/GMT的午夜)開始所經過的秒數,不考慮閏秒。 iPhone 和 Android 在日期格式方面有所不同。其中,iPhone(iOS)使…

985高校查重率“隱性閾值”:低于5%可能被重點審查!

你是不是也以為&#xff1a; “查重率越低越好&#xff0c;最好壓到1%、0%&#xff0c;導師看了都感動哭&#x1f979;” 但是你不知道的是——在985/211等重點高校&#xff0c;查重率太低反而可能引起導師和學術辦公室的“特別關注”&#xff01; 今天就來扒一扒這個查重圈“…

【NLP】33. Pinecone + OpenAI :構建自定義語義搜索系統

Pinecone OpenAI 中文教學教程&#xff1a;構建自定義語義搜索系統 一、背景介紹 當下 AI 問答系統、矩陣檢索、短文本分類等場景中&#xff0c;都需要很好地實現 “根據輸入進行相似給點搜索”。這種算法基礎稱為 “向量搜索”&#xff0c;它的核心是將文本轉換為向量后&am…

【Mybatis-plus常用語法】

MyBatis-Plus 是 MyBatis 的增強工具&#xff0c;提供了很多便捷的功能來簡化開發。以下是一些 MyBatis-Plus 的常見語法&#xff1a; 實體類注解&#xff1a;使用 TableName 注解來指定實體類和數據庫表的映射關系。 TableName("user") public class User {privat…

Logback官方文檔翻譯章節目錄

Logback官方文檔翻譯章節目錄 第一章 Logback簡介 第二章 Logback的架構&#xff08;一&#xff09; Logback的架構&#xff08;二&#xff09; Logback的架構&#xff08;三&#xff09; 持續更新中…

Python變量作用域

變量作用域是Python編程中非常重要的基礎概念&#xff0c;理解它可以幫助你避免很多常見的錯誤。本文將用簡單易懂的方式&#xff0c;帶你全面掌握Python變量作用域的所有細節。 一、什么是變量作用域&#xff1f; 變量作用域&#xff08;Scope&#xff09;指的是變量在程序中…

初學者的AI智能體課程:構建AI智能體的十堂課

初學者的AI智能體課程:構建AI智能體的十堂課 在人工智能(AI)領域,AI智能體正在逐漸發揮其不容忽視的作用。自動化的智能體不僅僅在理論上廣泛討論,更加在實際應用中開辟了一片新的天地。那么如何動手開發屬于自己的AI智能體呢?Microsoft提供的AI智能體入門課正是為此而設…

【并發編程】MySQL鎖及單機鎖實現

目錄 一、MySQL鎖機制 1.1 按鎖粒度劃分 1.2 按鎖功能劃分 1.3 InnoDB鎖實現機制 (1)記錄鎖(Record Lock) (2) 間隙鎖(Gap Lock) (3) 臨鍵鎖(Next-Key Lock) (4) 插入意向鎖(Insert Intention Lock) 二、基于 JVM 本地鎖實現,保證線程安全 2.1 線程不安全的分析 2.1…

能耗優化新引擎:EIOT平臺助力企業降本增效

安科瑞顧強 數字化轉型的背景下&#xff0c;能源管理正加速向智能化、遠程化方向演進。安科瑞電氣推出的EIOT托管平臺及ADW300系列4G無線計量儀表&#xff0c;通過云端技術與無線通信的深度融合&#xff0c;為用戶打造了高效、便捷的遠程能源監測與管理體系&#xff0c;助力企…

(14)Element Plus項目綜合案例

本系列教程目錄&#xff1a;Vue3Element Plus全套學習筆記-目錄大綱 文章目錄 第3章 綜合案例3.1 搭建項目3.1.1 創建Vite工程3.1.2 配置路由 3.2 登錄模塊頁面3.2.1 注冊頁面3.2.2 登錄頁面3.2.3 忘記密碼頁面 3.3 導航設置3.3.1 頭部3.3.2 側邊欄與底部1&#xff09;頭像部分…

Webug4.0靶場通關筆記22- 第27關文件包含

目錄 一、文件包含 1、原理分析 2、文件包含函數 &#xff08;1&#xff09;include( ) &#xff08;2&#xff09;include_once( ) &#xff08;3&#xff09;require( ) &#xff08;4&#xff09;require_once( ) 二、第27關滲透實戰 1、打開靶場 2、源碼分析 3、…

〖 Linux 〗解決 VS Code 遠程連接服務器的常見問題

文章目錄 解決 VS Code 遠程連接服務器的斷開問題VS Code Remote-SSH一直彈出輸入密碼的問題VsCode C 語法檢測失效不標紅色波浪線 解決辦法卸載擴展方式&#xff1a; 解決vscode C智能提示緩慢 解決 VS Code 遠程連接服務器的斷開問題 解決 vscode 卡頓&#xff0c;卡死&…

ERC-20與ERC-721:區塊鏈代幣標準的雙星解析

一、代幣標準的誕生背景 在以太坊生態中&#xff0c;代幣標準是構建去中心化應用&#xff08;DApps&#xff09;的基石。ERC-20與ERC-721分別代表同質化與非同質化代幣的兩大核心標準&#xff0c;前者支撐著90%以上的加密資產流通&#xff0c;后者則開啟了數字資產唯一性的新時…

C++入門小館 :多態

嘿&#xff0c;各位技術潮人&#xff01;好久不見甚是想念。生活就像一場奇妙冒險&#xff0c;而編程就是那把超酷的萬能鑰匙。此刻&#xff0c;陽光灑在鍵盤上&#xff0c;靈感在指尖跳躍&#xff0c;讓我們拋開一切束縛&#xff0c;給平淡日子加點料&#xff0c;注入滿滿的pa…

【NextPilot日志移植】整體功能概要

整體日志系統的實現功能 該日志系統主要實現了飛行日志的記錄功能&#xff0c;支持多種日志記錄模式&#xff0c;可將日志存儲到文件或通過 MAVLink 協議傳輸&#xff0c;同時具備日志加密、空間管理、事件記錄等功能。具體如下&#xff1a; 日志記錄模式&#xff1a;支持按武…

數字化轉型:概念性名詞淺談(第二十五講)

大家好&#xff0c;今天接著介紹數字化轉型的概念性名詞系列。 &#xff08;1&#xff09;SOP(標準作業程序) 標準作業程序&#xff08;Standard Operating Procedure, SOPs&#xff09;是在有限時間與資源內&#xff0c;為了執行復雜的日常事務所設計的內部程序。從管理學的…

交叉編譯 opencv-4.10

編譯說明 opencv 下包含很多模塊&#xff0c;各個模塊的作用可以參考Opencv—模塊概覽. 嵌入式考慮有限存儲等因素會對模塊進行裁剪&#xff0c;我這里主要保留圖像拼接&#xff08;stitching&#xff09;圖片編解碼&#xff08;imgcodecs&#xff09;與特征點匹配&#xff08…