Java 泛型使用教程

簡介

Java 泛型是 JDK 5 引入的一項特性,它提供了編譯時類型安全檢測機制,允許在編譯時檢測出非法的類型。泛型的本質是參數化類型,也就是說所操作的數據類型被指定為一個參數。

泛型的好處:

  • 編譯期檢查類型安全

  • 避免強制類型轉換(cast

  • 代碼更通用,更易重用

泛型的基本使用

泛型類
public class Box<T> {private T content;public void set(T content) {this.content = content;}public T get() {return content;}
}

使用:

Box<String> stringBox = new Box<>();
stringBox.set("Hello");
String value = stringBox.get(); // 無需強轉
泛型方法
public class Util {public static <T> void printArray(T[] array) {for (T element : array) {System.out.println(element);}}
}

使用:

String[] arr = {"A", "B", "C"};
Util.printArray(arr);
泛型接口
public interface Converter<F, T> {T convert(F from);
}public class StringToIntegerConverter implements Converter<String, Integer> {public Integer convert(String from) {return Integer.parseInt(from);}
}

泛型中的通配符:?

? 通配符

表示任意類型:

public void printList(List<?> list) {for (Object item : list) {System.out.println(item);}
}
? extends T(上界通配符)

表示 TT 的子類(只讀,不能寫):

public void printNumbers(List<? extends Number> list) {for (Number num : list) {System.out.println(num);}
}

不能添加元素:

list.add(10); // ? 報錯
? super T(下界通配符)

表示 TT 的父類(可以寫入,但取出只能當作 Object):

public void addNumbers(List<? super Integer> list) {list.add(10); // ? OK
}

類型擦除(Type Erasure)

泛型在編譯后會被擦除,JVM 不知道泛型類型,全部變成 Object

List<String> list = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
System.out.println(list.getClass() == list2.getClass()); // true

正因如此:

  • 不能使用 new T()

  • 不能使用 T.class

  • 不能判斷 instanceof T

常見的泛型類庫例子

  • List<T>:存儲 T 類型的集合

  • Map<K, V>:泛型鍵值對

  • Optional<T>:包裝返回值

  • Comparable<T>:排序比較接口

  • Function<T, R>:函數式接口

  • Callable<T>:異步任務的返回類型

  • Future<T>:異步計算的結果

進階技巧

泛型數組不允許:
List<String>[] lists = new List<String>[10]; // ? 編譯錯誤
泛型靜態方法必須聲明 <T>
public static <T> void print(T value) {System.out.println(value);
}

實際項目中 Java 泛型的用法大全

通用返回封裝類(統一 API 響應格式)
public class Result<T> {private int code;private String message;private T data;public Result(int code, String message, T data) {this.code = code;this.message = message;this.data = data;}public static <T> Result<T> success(T data) {return new Result<>(200, "Success", data);}public static <T> Result<T> fail(String message) {return new Result<>(500, message, null);}// getter/setter omitted
}
通用分頁結果類
public class PageResult<T> {private List<T> records;private long total;public PageResult(List<T> records, long total) {this.records = records;this.total = total;}
}

結合 Spring 使用泛型的示例

通用 Service 接口
public interface BaseService<T, ID> {T findById(ID id);List<T> findAll();T save(T entity);void deleteById(ID id);
}
抽象 Service 實現類
public abstract class AbstractBaseService<T, ID> implements BaseService<T, ID> {@Autowiredprotected JpaRepository<T, ID> repository;@Overridepublic T findById(ID id) {return repository.findById(id).orElse(null);}@Overridepublic List<T> findAll() {return repository.findAll();}@Overridepublic T save(T entity) {return repository.save(entity);}@Overridepublic void deleteById(ID id) {repository.deleteById(id);}
}
具體 Service
@Service
public class UserService extends AbstractBaseService<User, Long> {// 可以擴展額外業務邏輯
}

Java 泛型 與 C#.net 泛型比較

Java 泛型 與 C# (.NET) 泛型有很多相似之處,C# 泛型的設計部分參考了 Java。但它們在類型擦除、協變/逆變、約束、運行時行為等方面有顯著的不同。

特性Java 泛型C# (.NET) 泛型
類型擦除是(編譯期擦除)否(保留類型信息)
運行時可反射獲取泛型類型
基本類型支持不直接支持(需使用包裝類如 Integer支持,例如 List<int>
泛型約束限制(只能 extends,不支持多個約束)強大(支持 where T : class, new(), 多個接口)
協變/逆變支持通過通配符 ? extends/super直接使用 out/in 關鍵字
泛型數組不支持(如 new T[] 編譯錯誤)支持
泛型方法支持支持
類型擦除 vs 保留類型
  • Java
List<String> list = new ArrayList<>();
List<Integer> intList = new ArrayList<>();
System.out.println(list.getClass() == intList.getClass()); // true

Java 在編譯時擦除了泛型信息,List<String>List<Integer> 其實是同一個字節碼類。

  • C#
List<string> list = new List<string>();
List<int> intList = new List<int>();
Console.WriteLine(list.GetType() == intList.GetType()); // false

C# 會為不同泛型參數生成不同的類實例,因此保留類型信息。

泛型約束
  • Java
public class Repository<T extends BaseEntity> {public void save(T entity) { }
}
  • C#
public class Repository<T> where T : BaseEntity, new() {public void Save(T entity) { }
}

C# 支持更豐富的泛型約束,例如要求是引用類型 class、值類型 struct、必須有無參構造函數 new() 等。

協變與逆變(Covariance & Contravariance)
  • Java 使用通配符
List<? extends Number> numbers;  // 只能讀取,不能添加
List<? super Integer> integers;  // 只能添加 Integer
  • C# 使用 in / out
interface ICovariant<out T> { }
interface IContravariant<in T> { }

C# 在接口中用 in/out 明確支持協變逆變,且更強大、更類型安全。

泛型數組
  • Java
T[] array = new T[10]; // 編譯錯誤
  • C#
T[] array = new T[10]; // 合法
基本類型泛型
  • Java
List<int> list = new ArrayList<>(); // 編譯錯誤
List<Integer> list = new ArrayList<>(); // 正確
  • C#
List<int> list = new List<int>(); // 正確,泛型支持值類型
總結
特性JavaC#
類型安全????
靈活性?(類型擦除限制)??(運行時保留泛型)
泛型數組???
基本類型支持?(需包裝)??
泛型約束一般強大
協變逆變復雜、通配符語法簡潔、原生支持
性能需裝箱無裝箱(對值類型更快)

協變逆變詳解

協變(Covariance)和逆變(Contravariance)是泛型類型系統中用于處理子類和父類之間的泛型關系的重要機制。

Java 的協變(Covariant)與逆變(Contravariant)

Java 使用 通配符(wildcards) 來支持:

協變(? extends T) — 只讀

  • 意思是:某個未知類型是 T 的子類

  • 常用于“只能讀”的場景

public void readAnimals(List<? extends Animal> animals) {for (Animal animal : animals) {System.out.println(animal);}
}

可以傳入 List<Cat>、List<Dog> 或 List<Animal>,但不能添加新元素。

animals.add(new Cat()); // ? 編譯錯誤

逆變(? super T) — 只寫

  • 意思是:某個未知類型是 T 的父類

  • 常用于“只能寫”的場景

public void addCats(List<? super Cat> cats) {cats.add(new Cat());     // ? 合法// cats.add(new Animal()); // ? 不安全
}

可以傳入 List<Cat>、List<Animal>、List<Object>,但不能安全地讀取具體類型:

Object obj = cats.get(0); // 只能作為 Object 使用
C# 中的協變與逆變
  • C# 協變(out)
interface IReadOnlyList<out T> {T Get(int index);
}IReadOnlyList<Animal> animals = new List<Cat>(); // ? 協變成功
  • C# 逆變(in)
interface IWriter<in T> {void Write(T value);
}IWriter<Cat> writer = new AnimalWriter(); // ? 逆變成功
完整示例:協變 & 逆變
import java.util.*;class Animal { }
class Cat extends Animal { }
class Dog extends Animal { }public class VarianceDemo {public static void main(String[] args) {List<Cat> cats = new ArrayList<>();cats.add(new Cat());readAnimals(cats); // ? 協變addCats(cats);     // ? 逆變}// 協變:讀取public static void readAnimals(List<? extends Animal> animals) {for (Animal a : animals) {System.out.println("Animal: " + a);}// animals.add(new Dog()); // ? 編譯錯誤}// 逆變:寫入public static void addCats(List<? super Cat> animals) {animals.add(new Cat()); // ?}
}
總結
特性協變逆變
Java 關鍵字? extends T? super T
C# 關鍵字out Tin T
適合場景讀取數據寫入數據
是否可寫??
是否可讀??(只能當 Object)

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

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

相關文章

Leetcode - 周賽446

目錄 一、3522. 執行指令后的得分二、3523. 非遞減數組的最大長度三、3524. 求出數組的 X 值 I四、3525. 求出數組的 X 值 II 一、3522. 執行指令后的得分 題目鏈接 本題就是一道模擬題&#xff0c;代碼如下&#xff1a; class Solution {public long calculateScore(String…

【更新完畢】2025泰迪杯數據挖掘競賽A題數學建模思路代碼文章教學:競賽論文初步篩選系統

完整內容請看文末最后的推廣群 基于自然語言處理的競賽論文初步篩選系統 基于多模態分析的競賽論文自動篩選與重復檢測模型 摘要 隨著大學生競賽規模的不斷擴大&#xff0c;參賽論文的數量激增&#xff0c;傳統的人工篩選方法面臨著工作量大、效率低且容易出錯的問題。因此&…

計算機視覺與深度學習 | RNN原理,公式,代碼,應用

RNN(循環神經網絡)詳解 一、原理 RNN(Recurrent Neural Network)是一種處理序列數據的神經網絡,其核心思想是通過循環連接(隱藏狀態)捕捉序列中的時序信息。每個時間步的隱藏狀態 ( h_t ) 不僅依賴當前輸入 ( x_t ),還依賴前一時間步的隱藏狀態 ( h_{t-1} ),從而實現…

AI速讀:解鎖LLM下Game Agent的奇妙世界

在 AI 浪潮中&#xff0c;大語言模型&#xff08;LLMs&#xff09;正重塑游戲智能體格局。想知道基于 LLMs 的游戲智能體如何運作&#xff0c;在各類游戲中有何驚艷表現&#xff0c;未來又將走向何方&#xff1f; 大型語言模型&#xff08;LLMs&#xff09;的興起為游戲智能體的…

【每日八股】復習計算機網絡 Day3:TCP 協議的其他相關問題

文章目錄 昨日內容復習TCP 的四次揮手&#xff1f;TCP 為什么要四次揮手&#xff1f;在客戶端處于 FIN_WAIT_2 狀態時&#xff0c;如果此時收到了亂序的來自服務端的 FIN 報文&#xff0c;客戶端會如何處理&#xff1f;何時進入 TIME_WAIT 狀態&#xff1f;TCP 四次揮手丟了怎么…

學習筆記十五——rust柯里化,看不懂 `fn add(x) -> impl Fn(y)` 的同學點進來!

&#x1f9e0; Rust 柯里化從零講透&#xff1a;看不懂 fn add(x) -> impl Fn(y) 的同學點進來&#xff01; &#x1f354; 一、什么是柯里化&#xff1f;先用一個超好懂的生活比喻 假設你在點一個漢堡&#xff1a; 你說&#xff1a;我要點一個雞腿漢堡&#xff01; 店員…

深入理解 TCP 協議 | 流量、擁塞及錯誤控制機制

注&#xff1a;本文為 “TCP 協議” 相關文章合輯。 原文為繁體&#xff0c;注意術語描述差異。 作者在不同的文章中互相引用其不同文章&#xff0c;一并匯總于此。 略作重排&#xff0c;如有內容異常&#xff0c;請看原文。 TCP 三向交握 (Three-way Handshake) 2016-12-21 …

PCL庫編譯指南

PCL(Point Cloud Library)的編譯過程會根據不同操作系統有所差異。以下是詳細的編譯步驟&#xff1a; Linux/Ubuntu系統編譯 1. 安裝依賴項 bash sudo apt-get update sudo apt-get install git build-essential linux-libc-dev sudo apt-get install cmake cmake-gui sud…

【Linux】條件變量、基于阻塞隊列的生產者消費者模型

&#x1f4da; 博主的專欄 &#x1f427; Linux | &#x1f5a5;? C | &#x1f4ca; 數據結構 | &#x1f4a1;C 算法 | &#x1f310; C 語言 進程是資源分配的基本單位&#xff0c;線程是調度的基本單位&#xff0c;線程是在進程內部運行的&#xff08;是進程內部…

32-工藝品商城小程序

技術&#xff1a; 基于 B/S 架構 SpringBootMySQLvueelementuiuniapp 環境&#xff1a; Idea mysql maven jdk1.8 node 可修改為其他類型商城 用戶端功能 1.系統首頁展示輪播圖及工藝品列表 2.分類模塊:展示產品的分類類型 3.購物車:進行商品多選結算 或者批量管理操作 4.…

SLAM | 激光SLAM中的退化問題

在激光SLAM中,判斷退化環境的核心是通過數學建模分析環境特征對位姿估計的約束能力。除了LOAM中提出的退化因子D外,還存在多種基于表達式和閾值設定的方法。以下是幾種典型方法及其實現原理: 1. 協方差矩陣特征值分析 原理:通過分析點云協方差矩陣的特征值分布,判斷環境中…

【2025最新版】火鳥門戶v8.5系統源碼+PC、H5、小程序 +數據化大屏插件

一.介紹 火鳥地方門戶系統V8.5源碼 系統包含4端&#xff1a; PCH5小程序APP 二.搭建環境 系統環境&#xff1a;CentOS、 運行環境&#xff1a;寶塔 Linux 網站環境&#xff1a;Nginx 1.2.22 MySQL 5.6 PHP-7.4 常見插件&#xff1a;fileinfo &#xff1b; redis 三.測…

PHP騰訊云人臉核身獲取NONCE ticket

參考騰訊云官方文檔&#xff1a; 人臉核身 獲取 NONCE ticket_騰訊云 前提條件&#xff0c;已經成功獲取了access token。 獲取參考文檔&#xff1a; PHP騰訊云人臉核身獲取Access Token-CSDN博客 public function getTxFaceNonceTicket($uid) {$access_token file_get_c…

多人3D游戲完整實現方案

以下是一份完整的代碼實現方案,涵蓋架構設計、核心模塊實現和部署流程。我們以 多人3D游戲 為例,結合之前討論的Nano服務端框架和Unity客戶端: 技術棧 模塊技術選型服務端Golang + Nano框架 + MongoDB客戶端Unity 2022 + C# + Mirror Networking通信協議Protobuf + WebSock…

【Linux我做主】GDB調試工具完全指南

Linux下GDB調試工具完全指南&#xff1a;25個核心命令詳解與實戰示例 github地址 有夢想的電信狗 前言 GDB&#xff08;GNU Debugger&#xff09;是Linux開發中不可或缺的調試工具&#xff0c;尤其在定位代碼邏輯錯誤和內存問題時表現卓越。本文基于實際開發經驗&#xff0…

QT中柵格模式探索

1、Qt中選擇了柵格模式&#xff0c;如下圖所示&#xff1a; 2、在進行整個大的UI界面布局時&#xff0c;需了解每個控件所需要選擇的屬性sizePolicy。 sizePolicy包含如下幾種選擇&#xff1a; 3、舉個例子&#xff1a;此時整個UI界面&#xff0c;我采用了柵格模式&#xf…

【計算機網絡】3數據鏈路層①

這篇筆記專門講數據鏈路層的功能。 2.功能 數據鏈路層的主要任務是讓幀在一段鏈路上或一個網絡中傳輸。 2.1.封裝成幀(組幀) 解決的問題:①幀定界②幀同步③透明傳輸 實現組幀的方法通常有以下種。 2.1.1.字符計數法 原理:在每個幀開頭,用一個定長計數字段來記錄該…

[區塊鏈lab2] 構建具備加密功能的Web服務端

實驗目標&#xff1a; 掌握區塊鏈中密碼技術的工作原理。在基于Flask框架的服務端中實現哈希算法的加密功能。 實驗內容&#xff1a; 構建Flash Web服務器&#xff0c;實現哈希算法、非對稱加密算法的加密功能。 實驗步驟&#xff1a; 哈希算法的應用&#xff1a;創建hash…

藍橋杯之前綴和

一維前綴 解題思路 看到“區間之和”問題&#xff0c;直接想到“前綴和” 前綴和的核心公式&#xff1a; sum[i]sum[i?1]a[i] 利用前綴和求區間和 [l,r] 的公式&#xff1a; 區間和sum[r]?sum[l?1] 解題步驟模板 輸入數組&#xff1a; 讀取數組長度 n 和查詢次數 m。 讀…

【學習筆記】計算機網絡(八)—— 音頻/視頻服務

第8章 互聯網上的音頻/視頻服務 文章目錄 第8章 互聯網上的音頻/視頻服務8.1概述8.2 流式存儲音頻/視頻8.2.1 具有元文件的萬維網服務器8.2.2 媒體服務器8.2.3 實時流式協議 RTSP 8.3 交互式音頻/視頻8.3.1 IP 電話概述8.3.2 IP電話所需要的幾種應用協議8.3.3 實時運輸協議 RTP…