java generics(泛型)

在定義類、接口和方法時,泛型使類型(類和接口)成為參數。與方法聲明中使用的形參非常相似,類型參數為您提供了一種方法,可以用不同的輸入重用相同的代碼。不同之處在于形式參數的輸入是值,而類型參數的輸入是類型。

使用泛型有許多好處:

1、在編譯時加強類型檢測

通過使用泛型,可以在編譯時捕獲和修復類型錯誤,從而避免在運行時出現 ClassCastException 等類型轉換異常。這提高了代碼的可靠性和穩定性。

2、消除類型轉換

使用泛型可以避免一些操作的強制類型轉換

3、提高代碼重用性

泛型可以使代碼更加通用,可以編寫一次代碼來處理多種類型的數據。

4、提高性能

泛型是在編譯時進行類型檢查的,因此可以避免在運行時進行類型轉換,從而提高了程序的性能。

泛型定義

泛型可以定義在類,接口和方法上。泛型使用 < >來指定泛型類型。

public class Aminal<T> {private T flag;public T getFlag() {return flag;}public Aminal(T x){this.flag = x;}public static void main(String[] args) {Aminal<String> a1 = new Aminal<>("a");Aminal<Integer> a2 = new Aminal<>(2);System.out.println(a1.getFlag());System.out.println(a2.getFlag());}
}

如上,類變量flag在class定義時候指定為泛型,在對應使用泛型變量flag的地方都需要使用泛型進行接收和傳遞。

常見的泛型類型標識:

E - Element(表示元素,常見于JDK的集合框架中)

K - Key(鍵)

V - Value(值)

N - Number(數字)

T - Type (類型)

S, U, V等 - 第2個、第3個、第4個類型

上面這些泛型類型標識只是一種約定,不會強制進行校驗,你也完全可以自定義,如下

public class Fruit<XXX> {private XXX price;XXX getPrice(){return price;}void setPrice(XXX price){this.price = price;}public static void main(String[] args) {Fruit<Double> f1 = new Fruit<>();f1.setPrice(2.1d);Fruit<Integer> f2 = new Fruit<>();f2.setPrice(5);}
}

上面使用XXX來表示類型,一樣可以正常編譯使用。

多個泛型

定義泛型時,可以指定多個泛型類型,多個之間使用,隔開

public class Pair<K,V> {K key;V value;public Pair(K k,V v){this.key = k;this.value = v;}public static void main(String[] args) {Pair<Integer,String> pair = new Pair<>(666,"泛型");System.out.println(pair.value);}
}
泛型方法

泛型方法相比于普通方法的聲明,還會在返回值前使用 < >來聲明使用的泛型參數列表

public static <T> List<T> fromArrayToList(T[] a) {return Arrays.stream(a).collect(Collectors.toList());
}

這里需要主要一點類上的泛型在類方法上都可以直接使用(注意是非靜態方法),不用在方法上聲明。

泛型類型限定

可以限定泛型為某個類的子類或實現了某個接口,使用extends來指定父類。

public static <T extends Number> float plus(T a ,T b){
return a.floatValue() + a.floatValue();
}

如果要限定多個條件可以使用 &來連接。

<T extends Number & Comparable>
通配符限定

在泛型代碼中,問號(?)被稱為通配符,用來表示未知類型。通配符可以在多種情況下使用:作為參數、字段或局部變量的類型;有時作為返回類型(盡管最好的編程實踐是更加具體)。通配符永遠不會被用作泛型方法調用的類型參數,泛型類的實例創建,或者超類型。

通配符限定只能使用在引用類型上,是是對泛型的限定。可以限定泛型的上界和下界。

<? extends Foo>
<? super Foo> 

上界:? extends Foo表示泛型最高類型是Foo,只能是Foo及其子類。

下界:? super Foo表示泛型最低類型是Foo,只能是Foo及其父類。

無界:? 表示沒有類型限制

例如:

public void printFruits(List<? extends Fruit> fruits) {for (Fruit fruit : fruits) {System.out.println(fruit);}
}

這里入參約束成Fruit的上界,也就是入參只能是實現了Fruit接口的類,這樣在方法體中就可以調用Fruit接口統一的方法來完成邏輯操作。這里一定要理解 ?extends和 T extends的區別。?extends是針對引用類型,也就是實際參數,而T extends是方法或類的定義上

類型擦除(Type Erasure)

Java 中的泛型在編譯時會進行類型擦除(Type Erasure)。類型擦除是 Java 泛型實現的一種機制,它允許你在編譯時使用泛型類型(也就是在編碼是進行檢測),但在運行時使用的是原始類型。在編譯時,泛型類型參數被擦除并替換為其邊界或 Object 類型。

驗證泛型擦除可以使用反射來操作class。

如下定義類

public class ErasureTest<T,X extends Number> {T t;X x;public void setT(T t){this.t = t;}    
}

通過反射打印類信息:

Class c = ErasureTest.class;
for (Field field : c.getDeclaredFields()) {System.out.println(field.getName()+":"+field.getType());
}
for (Method method : c.getDeclaredMethods()) {System.out.println(method.getName()+":");Class[] params = method.getParameterTypes();for (int i = 0; i < params.length; i++) {System.out.println("參數"+params[i].getName()+",類型:"+params[i].getTypeName());
}
/**
輸出內容:
t:class java.lang.Object
x:class java.lang.Number
setT:
參數java.lang.Object,類型:java.lang.Object
*/

這里可以看到X extends Number轉換成了其上界Number,T轉換成了其原始類型Object。

擦除帶來的問題

由于擦除,通過反射在對方法進行調用時可以跳過類型約束:

List<String> list = new ArrayList<>();
list.add("haha");
Method addMethod = list.getClass().getDeclaredMethod("add", Object.class);
addMethod.invoke(list,Integer.valueOf(1));
System.out.println(list);

如上代碼,定義了一個String型的list,但是我們通過反射成功的往list添加了一個Integer類型的,上面的代碼可以正常執行。這就可以繞過泛型限定。

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

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

相關文章

Elasticsearch7.17.7操作geo_point類型數據

目前使用的elasticsearch版本是7.17.7 有一個index&#xff0c;其中mapping的內容如下&#xff1a; {"city" : {"aliases" : { },"mappings" : {"properties" : {"city" : {"type" : "keyword"},"…

嵌入式學習 Day 29

函數: 1.函數的定義 2.函數的調用 3.函數的聲明 1.函數傳參: 1.賦值傳遞&#xff08;復制傳遞&#xff09; 函數體內部想要使用函數體外部變量值的時候使用復制傳遞 2.全局變量傳遞 3.地址傳遞 函數體內部想要修改函數體外部變量值的時候使用地址傳遞 函數…

代碼隨想錄算法訓練營第48天| Leetcode 121. 買賣股票的最佳時機、Leetcode 122.買賣股票的最佳時機II

文章目錄 Leetcode 121. 買賣股票的最佳時機Leetcode 122.買賣股票的最佳時機II Leetcode 121. 買賣股票的最佳時機 題目鏈接&#xff1a; Leetcode 121. 買賣股票的最佳時機 題目描述&#xff1a; 給定一個數組 prices &#xff0c;它的第 i 個元素 prices[i] 表示一支給定股…

W5300驅動說明

W5300是一款帶有硬件協議棧的網絡芯片&#xff0c;內部擁有128K的緩存&#xff0c;最大支持8路socket通信&#xff0c;與MCU之間通過16位數據總線通信&#xff0c;通信速度遠超W5500之類以SPI作為通信接口的網絡芯片&#xff0c;特別適合對高速網絡傳輸有需求的應用。 本次使用…

使用 helm repo add istio添加了一個helm chart repo,如何查看istio的版本呢

1. 添加chart repo helm repo add istio https://istio-release.storage.googleapis.com/charts helm repo update2. 查看版本 helm search repo istio 3. 查看版本詳細信息 helm show chart istio/cni 4. 查看某個chart的歷史版本 helm search repo <chart-name> --…

【Linux】信號的保存

&#x1f34e;個人博客&#xff1a;個人主頁 &#x1f3c6;個人專欄&#xff1a;Linux ?? 功不唐捐&#xff0c;玉汝于成 目錄 前言 正文 信號在Linux中的保存主要涉及方面 信號的類型&#xff1a; 信號處理程序&#xff1a; 信號的傳遞和處理&#xff1a; 信號的阻…

面試官:你用過Collections工具類嗎?

Collections工具類 1. 常用的 Collections 方法2. 代碼示例 Java中的 Collections 工具類提供了一系列靜態方法&#xff0c;用于對集合進行各種操作&#xff0c;如排序、查找、替換等。下面我們來看一些 Collections 工具類中常用的API和使用示例。 1. 常用的 Collections 方…

回溯算法套路③排列型回溯+N皇后【基礎算法精講 16】

46 . 全排列 鏈接 : . - 力扣&#xff08;LeetCode&#xff09; 思路 : 那么怎么確定選了那個數呢? 這里設置一個used表示i選沒選過 ; class Solution { public:vector<vector<int>> ans;vector<int> path;void backtrack(vector<int>nums,vect…

2024年【天津市安全員B證】考試內容及天津市安全員B證實操考試視頻

題庫來源&#xff1a;安全生產模擬考試一點通公眾號小程序 天津市安全員B證考試內容根據新天津市安全員B證考試大綱要求&#xff0c;安全生產模擬考試一點通將天津市安全員B證模擬考試試題進行匯編&#xff0c;組成一套天津市安全員B證全真模擬考試試題&#xff0c;學員可通過…

《Improving Calibration for Long-Tailed Recognition》閱讀筆記

論文標題 《Improving Calibration for Long-Tailed Recognition》 改進長尾識別的校準工作 作者 Zhisheng Zhong、 Jiequan Cui、Shu Liu 和 Jiaya Jia 香港中文大學和 SmartMore 初讀 摘要 深度神經網絡在訓練數據集類別極度不平衡時可能會表現不佳。最近&#xff0c…

pydub、playsound播放聲音;gradio、streamlit頁面播放聲音;gradio 頁面圖像、視頻及調用攝像頭

1、pydub from pydub import AudioSegment from pydub.playback import playsong AudioSegment.from_wav(r"C:\Users\loong\Downloads\zh.wav") play(song)2、playsound from playsound import playsoundplaysound(r"voice.wav")3、streamlit import s…

Linux學習:初識Linux

目錄 1. 引子&#xff1a;1.1 簡述&#xff1a;操作系統1.2 學習工具 2. Linux操作系統中的一些基礎概念與指令2.1 簡單指令2.2 ls指令與文件2.3 cd指令與目錄2.4 文件目錄的新建與刪除指令2.5 補充指令1&#xff1a;2.6 文件編輯與拷貝剪切2.7 文件的查看2.8 時間相關指令2.9 …

22.基于springboot + vue實現的前后端分離-汽車票網上預定系統(項目 + 論文PPT)

項目介紹 系統是一個B/S模式系統&#xff0c;采用Spring Boot框架&#xff0c;MySQL 數據庫設計開發&#xff0c;充分保證系統的穩定性。系統具有界面清晰、操作簡單&#xff0c;功能齊全的特點&#xff0c;使得汽車票網上預訂系統管理工作系統化、規范化。本系統的使用使管理人…

JavaScript作用域及預解析

文章目錄 1. 作用域介紹2. 變量的作用域*3. JS中沒有塊級作用域4. 作用域鏈5. 預解析預解析案例 1. 作用域介紹 全局作用域局部作用域相同的變量名稱在不同的作用域中是不會相互影響的&#xff01; 2. 變量的作用域 全局變量&#xff1a;在全局下都可以使用&#xff1b;局部變…

藍橋杯——外賣店優先級

外賣店優先級 題目分析 這一題一看N&#xff0c;M&#xff0c;T的范圍就知道不能暴力&#xff0c;要討巧&#xff0c;怎么討巧是重點。正常的思路是第一層for循環遍歷訂單&#xff08;或者外賣店&#xff09;&#xff0c;第二層for循環遍歷外賣店&#xff08;或者訂單&#x…

Vue中 computed 和 watch

在Vue框架中&#xff0c;computed和watch都用于響應數據的變化&#xff0c;但它們在使用上有著不同的側重點和機制。具體分析如下&#xff1a; 1. 功能差異 computed是計算屬性&#xff0c;它是基于它們的響應式依賴進行緩存的。只有當依賴的數據發生變化時&#xff0c;compu…

2827. 范圍中美麗整數的數目

文章目錄 題意思路代碼 題意 題目鏈接 思路 按位dp暴力 代碼 // 暴力 class Solution { public:int numberOfBeautifulIntegers(int low, int high, int k) {int l low / k;int r high / k;if (low % k)l;int ans 0;while (l < r){int tmp l * k;if (10 < tmp &…

華為數通方向HCIP-DataCom H12-821題庫(多選題:61-80)

第61題 ACL 可分為如下哪些類別? A.用戶自定義 ACL B.基本 ACL C.二層ACL D.高級ACL 【參考答案】ABCD 【答案解析】 A. 用戶自定義 ACL (User-defined ACL): 這是用戶根據自身需求自定義的 ACL,用于實現特定的訪問控制策略。B.基本 ACL (Standard ACL): 基本 ACL 是基于源 …

OCP Secure boot必要特性

三點必需要求&#xff1a; The platform components must: 1. Provide a mechanism for securely anchoring a root of trust public key. // 提供一種用于安全地錨定信任根公鑰的機制。 2. Verify the device firmware digital signature using the anchored public key /…

北京大學發布,將試錯引入大模型代理學習!

引言&#xff1a;探索語言智能的新邊界 在人工智能的發展歷程中&#xff0c;語言智能始終是一個核心的研究領域。隨著大語言模型&#xff08;LLM&#xff09;的興起&#xff0c;我們對語言智能的理解和應用已經邁入了一個新的階段。這些模型不僅能夠理解和生成自然語言&#x…