ホームページ Java &#&チュートリアル Javaのジェネリックスの詳細な説明

Javaのジェネリックスの詳細な説明

Jan 18, 2017 am 10:54 AM

いわゆるジェネリック: クラスとインターフェイスを定義するときに型パラメーターを指定できます。この型パラメーターは、変数を宣言し、オブジェクトを作成するときに決定されます (つまり、型引数とも呼ばれる実際の型パラメーターを渡します)。ジェネリック クラスまたはインターフェイス

"ダイヤモンド" 構文

//定义
 
public interface List<E> extends Collection<E>  
 
public class HashMap<K,V> extends AbstractMap<K,V>  implements Map<K,V>, Cloneable, Serializable 
//使用
 
List<String> list = new ArrayList();
 
//Java7以后可以省略后面尖括号的类型参数
 
List<String> list = new ArrayList<>();
ログイン後にコピー

ジェネリック クラスからサブクラスを派生する

//方式1
 
public class App extends GenericType<String>
 
//方式2
 
public class App<T> extends GenericType<T>
 
//方式3
 
public class App extends GenericType
ログイン後にコピー

疑似ジェネリック

真のジェネリック クラスは存在せず、ジェネリック クラスは Java 仮想マシンに対して透過的です。JVM は認識しません。ジェネリック クラスの存在。つまり、JVM はジェネリック クラスを通常のクラスと何ら区別せずに扱います。そのため、静的メソッド、静的初期化ブロック、および静的変数では型パラメータを使用できません。

- 以下のメソッドはすべて間違っています

private static T data;
 
static{
 
    T f;
 
}
 
public static void func(){
 
    T name = 1;
 
}
ログイン後にコピー

次の例は、ジェネリック クラスが存在しないことを側から検証できます

public static void main(String[] args){
 
        List<String> a1 = new ArrayList<>();
        List<Integer> a2 = new ArrayList<>();  
    System.out.println(a1.getClass() == a2.getClass());
 
    System.out.println(a1.getClass());
 
    System.out.println(a2.getClass());
 
}
ログイン後にコピー

Output

true
 
class java.util.ArrayList
 
class java.util.ArrayList
ログイン後にコピー

Type wildcard

まず第一に、Foo が親であるかどうかを明確にする必要がありますBar のクラスですが、List は List の親クラスではありません。Java では、汎用のワイルドカードを表すために「?」を使用します。この種のワイルドカードを使用した .List ジェネリックは、要素を設定 (set) することはできませんが、要素を取得 (get) することしかできません。プログラムはリスト内のタイプを判断できないため、オブジェクトを追加できません。ただし、取得されるオブジェクトは Object 型である必要があります。

次のメソッドはコンパイル エラーになります:

List<?> list = new ArrayList<>();
 
list.add(new Object());
ログイン後にコピー

いくつかのアイデア:

1. List オブジェクトは List オブジェクトとして使用できません。 ;オブジェクト>クラスのサブカテゴリ。

2. 配列とジェネリックは異なります。Foo が Bar のサブタイプ (サブクラスまたはサブインターフェイス) であると仮定すると、Foo[] は依然として Bar[] のサブタイプですが、 G は G ではありません。

3. さまざまなジェネリック リストの親クラスを表すには、型ワイルドカードを使用する必要があります。List コレクションに型引数として疑問符を渡します。 ;?>( 不明なタイプの要素のリストを意味します)。この疑問符 (?) はワイルドカード文字と呼ばれ、その要素の型は任意の型に一致します。

ワイルドカードの上限

List は、すべての SuperType ジェネリック リストの親クラスまたはそれ自体を表します。ワイルドカードの上限を持つジェネリックスは set メソッドを持つことができず、get メソッドのみを持つことができます。

ワイルドカードの上限を設定すると、次の問題を解決できます: Dog は Animal サブクラスであり、受信リストの数を取得する getSize メソッドがあります。コードは次のとおりです

abstract class Animal {
    public abstract void run();
}
class Dog extends Animal {
    public void run() {
        System.out.println("Dog run");
    }
}
public class App {
    public static void getSize(List<Animal> list) {
        System.out.println(list.size());
    }
    public static void main(String[] args) {
        List<Dog> list = new ArrayList<>();
        getSize(list); // 这里编译报错
    }
}
ログイン後にコピー

ここでのプログラミング エラーの理由は次のとおりです。 List は List の親クラスではありません。 1つ目の解決策は、getSizeメソッドの仮パラメータListをListに変更することですが、この場合はオブジェクトを取得するたびに強制的な型変換が必要となり面倒です。ワイルドカードの上限を使用すると、List を List に変更することができ、コンパイルが間違ってしまうことはなく、型変換は必要ありません。


ワイルドカード

Listの下限は、SubTypeジェネリックリストの下限を表します。ワイルドカードの上限を持つジェネリックには get メソッドを含めることはできず、set メソッドのみを含めます。

ジェネリックメソッド

型パラメータを使用せずにクラスまたはインターフェイスを定義するが、メソッドを定義するときに型パラメータを自分で定義したい場合、JDK1.5 ではジェネリックメソッドもサポートされています。ジェネリック メソッドのメソッド シグネチャには、通常のメソッドのメソッド シグネチャよりも多くの型パラメータ宣言が含まれます。複数の型パラメータ宣言は、すべてのメソッドの間にカンマ (,) で区切られます。修飾子とメソッドの戻り値の型の構文形式は次のとおりです:

修饰符 返回值类型 方法名(类形列表){
 
//方法体
 
}
ログイン後にコピー

ジェネリック メソッドでは、メソッドの 1 つ以上のパラメーター間の型の依存関係、またはメソッドの戻り値とパラメーター間の型の依存関係を表現するために型パラメーターを使用できます。このような型の依存関係がない場合は、ジェネリック メソッドを使用しないでください。 Collections の copy メソッドは、ジェネリック メソッドを使用します:

 public static <T> void copy(List<? super T> dest, List<? extends T> src){ ...}
ログイン後にコピー

このメソッドでは、src 型が dest 型またはそれ自体のサブクラスである必要があります。

消去と変換

厳密なジェネリック コードでは、ジェネリック宣言を持つクラスは常に型パラメーターを持つ必要があります。ただし、古い Java コードとの一貫性を保つために、型パラメータを指定せずにジェネリック宣言を持つクラスを使用することもできます。このジェネリック クラスに型パラメーターが指定されていない場合、型パラメーターは raw 型と呼ばれ、パラメーターの宣言時に指定された最初の上限型がデフォルトになります。

ジェネリック情報を持つオブジェクトをジェネリック情報のない別の変数に代入する場合、山かっこ内のすべての型情報は破棄されます。たとえば、List 型を List に変換すると、List のコレクション要素の型チェックが型変数 (つまり、Object) の上限になります。この状況を消去と呼びます。

class Apple<T extends Number>
 
{
 
 T size;
 
 public Apple()
 
 {
 
 }
 
 public Apple(T size)
 
 {
 
  this.size = size;
 
 }
 
 public void setSize(T size)
 
 {
 
  this.size = size;
 
 }
 
 public T getSize()
 
 {
 
  return this.size;
 
 }
 
}
 
public class ErasureTest
 
{
 
 public static void main(String[] args)
 
 {
 
  Apple<Integer> a = new Apple<>(6);    // ①
 
  // a的getSize方法返回Integer对象
 
  Integer as = a.getSize();
 
  // 把a对象赋给Apple变量,丢失尖括号里的类型信息
 
  Apple b = a;      // ②
 
  // b只知道size的类型是Number
 
  Number size1 = b.getSize();
 
  // 下面代码引起编译错误
 
  Integer size2 = b.getSize();  // ③
 
 }
 
}
ログイン後にコピー

Java のジェネリックスの詳細な説明に関連するその他の記事については、PHP 中国語 Web サイトに注目してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

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

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

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

会社のセキュリティソフトウェアはアプリケーションの実行に失敗していますか?それをトラブルシューティングと解決する方法は? 会社のセキュリティソフトウェアはアプリケーションの実行に失敗していますか?それをトラブルシューティングと解決する方法は? Apr 19, 2025 pm 04:51 PM

一部のアプリケーションが適切に機能しないようにする会社のセキュリティソフトウェアのトラブルシューティングとソリューション。多くの企業は、内部ネットワークセキュリティを確保するためにセキュリティソフトウェアを展開します。 ...

MapsTructを使用したシステムドッキングのフィールドマッピングの問題を簡素化する方法は? MapsTructを使用したシステムドッキングのフィールドマッピングの問題を簡素化する方法は? Apr 19, 2025 pm 06:21 PM

システムドッキングでのフィールドマッピング処理は、システムドッキングを実行する際に難しい問題に遭遇することがよくあります。システムのインターフェイスフィールドを効果的にマッピングする方法A ...

エンティティクラス変数名をエレガントに取得して、データベースクエリ条件を構築する方法は? エンティティクラス変数名をエレガントに取得して、データベースクエリ条件を構築する方法は? Apr 19, 2025 pm 11:42 PM

データベース操作にMyBatis-Plusまたはその他のORMフレームワークを使用する場合、エンティティクラスの属性名に基づいてクエリ条件を構築する必要があることがよくあります。あなたが毎回手動で...

Intellijのアイデアは、ログを出力せずにSpring Bootプロジェクトのポート番号をどのように識別しますか? Intellijのアイデアは、ログを出力せずにSpring Bootプロジェクトのポート番号をどのように識別しますか? Apr 19, 2025 pm 11:45 PM

intellijideaultimatiateバージョンを使用してスプリングを開始します...

名前を数値に変換してソートを実装し、グループの一貫性を維持するにはどうすればよいですか? 名前を数値に変換してソートを実装し、グループの一貫性を維持するにはどうすればよいですか? Apr 19, 2025 pm 11:30 PM

多くのアプリケーションシナリオでソートを実装するために名前を数値に変換するソリューションでは、ユーザーはグループ、特に1つでソートする必要がある場合があります...

Javaオブジェクトを配列に安全に変換する方法は? Javaオブジェクトを配列に安全に変換する方法は? Apr 19, 2025 pm 11:33 PM

Javaオブジェクトと配列の変換:リスクの詳細な議論と鋳造タイプ変換の正しい方法多くのJava初心者は、オブジェクトのアレイへの変換に遭遇します...

eコマースプラットフォームSKUおよびSPUデータベースデザイン:ユーザー定義の属性と原因のない製品の両方を考慮する方法は? eコマースプラットフォームSKUおよびSPUデータベースデザイン:ユーザー定義の属性と原因のない製品の両方を考慮する方法は? Apr 19, 2025 pm 11:27 PM

eコマースプラットフォーム上のSKUおよびSPUテーブルの設計の詳細な説明この記事では、eコマースプラットフォームでのSKUとSPUのデータベース設計の問題、特にユーザー定義の販売を扱う方法について説明します。

データベースクエリにTKMYBATISを使用するときに、エンティティクラスの変数名の構築クエリ条件をエレガントに取得する方法は? データベースクエリにTKMYBATISを使用するときに、エンティティクラスの変数名の構築クエリ条件をエレガントに取得する方法は? Apr 19, 2025 pm 09:51 PM

データベースクエリにTKMYBATISを使用する場合、クエリ条件を構築するためにエンティティクラスの変数名を優雅に取得する方法は一般的な問題です。この記事はピン留めします...

See all articles