Java泛型中的通配符和類型擦除可通過PECS原則和類型令牌有效掌握,使用? extends T讀取數(shù)據(jù)、? super T寫入數(shù)據(jù),遵循Producer-Extends Consumer-Super原則;1. 無界通配符<?>用于僅操作Object方法的場景,不可添加元素;2. 上界通配符<? extends T>允許從多種子類型集合中讀取,但禁止寫入;3. 下界通配符<? super T>支持向集合寫入T類型元素,但讀取時僅能作為Object處理;類型擦除導致運行時泛型信息丟失,List<String>與List<Integer>均變?yōu)長ist,因此無法實例化泛型類型、不能基于泛型重載方法、靜態(tài)字段不能使用泛型;可通過傳遞Class<T>類型令牌實現(xiàn)運行時類型檢查,如TypeSafeList或Gson的TypeToken機制;為確保類型安全,應避免原始類型和強制轉換,設計時依賴編譯期類型檢查,運行時借助反射或類令牌彌補擦除限制,最終將泛型從復雜特性轉化為可靠工具。
Java generics are powerful, but when you dive deeper—especially into wildcards and type erasure—they can feel more like a puzzle than a productivity tool. While basic generics help catch type errors at compile time, advanced use cases involving ?
, extends
, super
, and the limitations imposed by type erasure require a clearer mental model. Let’s break down how to actually use wildcards effectively and work around the quirks of type erasure.

Understanding Wildcards: ?
, extends
, and super
Wildcards (?
) represent unknown types in generics. They’re not just syntactic noise—they’re essential for writing flexible and safe generic code.
1. Unbounded Wildcard (<?>
) – “I don’t care what type it is”
Use when you only need methods from Object
(like toString()
, equals()
), or you're doing operations that don’t depend on the generic type.

public void printList(List<?> list) { for (Object item : list) { System.out.println(item); } }
You can’t add any element (except null
) to a List<?>
—because the compiler doesn’t know what type is allowed.
2. Upper-Bounded Wildcard (<? extends T>
) – “It’s T or a subclass”
Use when you need to read elements and treat them as a common type.

public double sum(List<? extends Number> numbers) { return numbers.stream() .mapToDouble(Number::doubleValue) .sum(); }
This works with List<Integer>
, List<Double>
, etc., because they’re subtypes of Number
.
?? But again: you cannot add anything (except null
) to a List<? extends T>
. The compiler doesn’t know the exact type—maybe it’s List<Integer>
, maybe List<Double>
.
3. Lower-Bounded Wildcard (<? super T>
) – “It’s T or a superclass”
Use when you need to write or add elements of type T
.
public void addNumbers(List<? super Integer> list) { list.add(42); list.add(100); }
This accepts List<Integer>
, List<Number>
, or List<Object>
.
But when reading, you only know the elements are at least Object
, so you get back Object
, not Integer
.
The PECS Rule: A Mental Shortcut
From Joshua Bloch’s Effective Java: PECS stands for Producer-Extends, Consumer-Super.
- If a parameterized collection produces items (you read from it), use
<? extends T>
. - If it consumes items (you write to it), use
<? super T>
.
Example: Collections.copy()
public static <T> void copy(List<? super T> dest, List<? extends T> src)
src
is a producer →? extends T
dest
is a consumer →? super T
Remember PECS, and you’ll rarely guess wrong.
Type Erasure: What Happens at Runtime?
Java generics use type erasure—all generic type information is removed by the compiler. At runtime, List<String>
and List<Integer>
are both just List
.
What’s Erased?
- Generics:
List<T>
→List
- Type parameters: replaced with their bound (or
Object
if unbounded) - Bridge methods are generated to maintain polymorphism
List<String> strings = new ArrayList<>(); List<Integer> ints = new ArrayList<>(); // This compiles to true at runtime System.out.println(strings.getClass() == ints.getClass()); // true
Consequences of Type Erasure
No runtime type checks on generics
List<String> list = new ArrayList<>(); ((List) list).add(123); // Compiles and runs, but breaks type safety
→ Throws
ClassCastException
only when you later read theString
.Cannot instantiate generic types
public class Box<T> { private T item; public T create() { // return new T(); // ? Not allowed } }
Workaround: Pass a
Class<T>
:public T create(Class<T> clazz) throws Exception { return clazz.newInstance(); }
No method overloading based on generics
void method(List<String> list) { } void method(List<Integer> list) { } // ? Compile error
Cannot have static fields with generic type parameters
public class Box<T> { static T item; // ? Not allowed — static shared across all T }
Working Around Type Erasure: Reification and Tokens
Sometimes you need to preserve type information at runtime. One common solution is using type tokens with Class<T>
.
public class TypeSafeList<T> { private Class<T> type; public TypeSafeList(Class<T> type) { this.type = type; } public void add(List<Object> rawList, Object item) { if (type.isInstance(item)) { rawList.add(item); } else { throw new IllegalArgumentException("Wrong type"); } } }
Used like:
TypeSafeList<String> stringList = new TypeSafeList<>(String.class);
Gson uses this pattern with TypeToken
for deserializing generic types.
Summary: Taming the Beast
- Use wildcards to make APIs flexible:
extends
for reading,super
for writing. - Remember PECS—it’s your best friend.
- Accept that type erasure limits what you can do at runtime.
- Use class tokens or reflection when you need type info back.
- Avoid casting and raw types—they defeat the purpose of generics.
Generics in Java aren’t perfect, but once you understand the rules behind wildcards and erasure, they become a reliable tool—not a mystery.
Basically: design with types at compile time, work around erasure at runtime, and let PECS guide your wildcard use.
以上が高度なJavaジェネリック:ワイルドカードとタイプの消去を飼いならしますの詳細內容です。詳細については、PHP 中國語 Web サイトの他の関連記事を參照してください。

ホットAIツール

Undress AI Tool
脫衣畫像を無料で

Undresser.AI Undress
リアルなヌード寫真を作成する AI 搭載アプリ

AI Clothes Remover
寫真から衣服を削除するオンライン AI ツール。

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中國語版
中國語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統(tǒng)合開発環(huán)境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック

Java の汎用境界では型パラメーターの制約を指定し、これらの制約を満たす型のみを使用できるようにします。一般的な境界には、上限 (拡張) と下限 (スーパー) の 2 種類があります。上限では、型パラメーターが指定された型のサブクラスであることが必要ですが、下限では、型パラメーターが指定された型のスーパークラスであることが必要です。汎用境界は型の安全性を強化し、パフォーマンスとコードの可読性を向上させます。

Java ジェネリックは、コンパイル時の型チェックを可能にする Java 言語の機能であり、これによりコードの型安全性が強化されます。ジェネリックは、クラス、インターフェイス、およびメソッドの定義で使用でき、これらの定義の範囲が広がります。再利用性を高めるため、ジェネリックスを使用すると、型変換エラーのリスクを最小限に抑え、コードをより簡潔で読みやすくすることができます。ジェネリックはコードの冗長性を減らし、不必要なキャストを回避することもできます。

ジェネリック メソッドは、メソッド シグネチャに型情報を埋め込むことで型の消去を排除し、特定の型の狀況に適した多態(tài)性メソッドの作成を可能にします。ジェネリック メソッドは型パラメーターを使用して定義されます。実際の型と同様に、メソッド內で型パラメーターを使用します。たとえば、max() メソッドは、比較可能なオブジェクトのリスト內の最大のオブジェクトを返します。 getHighestPaidEmployee() メソッドは、従業(yè)員リストから最高給與の従業(yè)員を返します。

Java 言語ジェネリックスの使用方法 Java 言語はタイプセーフなプログラミング言語です。つまり、コンパイル時に型エラーがチェックされ、実行時に発生するエラーが減少します。 Java 5 でのジェネリックスの導入により、Java プログラマはデータ型をより柔軟に操作できるようになり、型安全性とコードの可読性が大幅に向上しました。この記事では、Java 言語ジェネリックスの基本概念と使用法を紹介します。 1. ジェネリックスの概念 ジェネリックスは、Java の型パラメータ化メカニズムであり、

ネストされたジェネリックにより、ジェネリック メソッド內で他のジェネリック型を使用できるようになり、再利用性の高いコードが作成されます。実際には、ネストされたジェネリックを使用して、配列內の 2 つのピーク要素を見つけることができます。サンプル コードでは、ジェネリック ペアを使用して結果を保存し、要素を繰り返しチェックして隣接する要素と比較することでピーク値を見つけます。

ジェネリック関數(shù)を使用して Java でタイプセーフなデータ操作を実裝する方法の概要: ジェネリックは Java の非常に強力で重要な概念であり、コードを記述するときにデータ型パラメータを指定できるようになります。ジェネリック関數(shù)を使用すると、型安全なデータ操作を実裝し、コンパイル時または実行時の型エラーを回避できます。この記事では、Java でジェネリック関數(shù)を使用してタイプ セーフなデータ操作を実裝する方法と、具體的なコード例を紹介します。ジェネリック関數(shù)とは: ジェネリック関數(shù)とは、操作できる関數(shù)です。

Java ジェネリックには主に 6 つの用途があります。「ジェネリック クラスの定義」、「ジェネリック インターフェイスの定義」、「ジェネリック メソッドの定義」、「ジェネリック クラスまたはインターフェイスのインスタンス化」、「ワイルドカードの使用」、および「ジェネリック修飾子の使用」です。ジェネリック クラスを定義し、型パラメータを表すために <T> を使用します。 2. ジェネリック インターフェイスを定義し、型パラメータを表すために <T> を使用します。 3. ジェネリック メソッドを定義し、型パラメータを表すために <T> を使用します。 4. インスタンス化するときジェネリック クラスまたはインターフェイスの場合は、特定の型パラメータを指定します。 5. ワイルドカードを使用して、ジェネリック型のサブタイプまたはスーパータイプを表します。

Java でのジェネリック プログラミングにジェネリック関數(shù)を使用する方法 Java のジェネリックは、コンパイル時の型チェックのメカニズムであり、コードのセキュリティと可読性を向上させることができます。ジェネリック プログラミングは、ジェネリックを使用してジェネリック コードを実裝する方法です。 Java では、ジェネリック関數(shù)を使用してジェネリック プログラミングを実裝できます。これにより、関數(shù)內でジェネリック型を使用し、関數(shù)を呼び出すときに必要に応じて特定の型を指定できます。ジェネリック関數(shù)の定義は非常に簡単で、関數(shù)の戻り値の型の前に山かっこ <>gt を使用するだけです。
