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

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

Dec 19, 2016 pm 02:58 PM
ジェネリック

  1. 概要
    ジェネリックが導入される前は、Java 型はプリミティブ型と複合型に分割され、配列とクラスに分割されていました。ジェネリックスの導入後は、複合型をさらに多くの型に分割できるようになります。
    たとえば、元の型 List は List、List などの型に細分化されています。
    List と List は 2 つの異なる型であることに注意してください。
    String が Object を継承しても、それらの間には継承関係はありません。次のコードは不正です
    List ls = new ArrayList();
    List lo = ls;
    この設計の理由は、lo の宣言に従って、コンパイラが追加を許可しているためです。 to lo 任意のオブジェクト (Integer など)、ただしこのオブジェクトは
    List であるため、データ型の整合性が失われます。
    ジェネリックの導入前に、クラス内のメソッドが複数のデータ型をサポートしている場合、メソッドをオーバーロードする必要があります。ジェネリックの導入後、この問題は解決され、
    (ポリモーフィズム)、さらに複数のパラメーターを定義できるようになります。戻り値間の関係。
    例:
    public void write(Integer i, Integer[] ia);
    public void write(Double d, Double[] da);
    汎用バージョンは
    public [ ] ta);

    2. 定義と使用
    型パラメーターの命名スタイルは次のとおりです:
    仮型パラメーターの名前として簡潔な名前 (可能であれば 1 文字) を使用することをお勧めします。他の通常の
    仮パラメータと区別しやすくするため、小文字は避けることをお勧めします。
    区別するための具体的なタイプがない場合は、タイプに T を使用します。これはジェネリック メソッドでよく見られます。複数の型パラメータがある場合は、S など、アルファベットの T に近い文字を使用することがあります。
    ジェネリック関数がジェネリック クラスに出現する場合、混乱を避けるために、メソッドの型パラメータとクラスの型パラメータで同じ名前を使用しないことが最善です
    。内部クラスについても同様です。

    2.1 型パラメーターを使用してクラスを定義する
    型パラメーターを使用してクラスを定義する場合、クラス名の直後の <> に 1 つ以上の型パラメーターの名前を指定します。また、型パラメーターを指定することもできます。値の範囲は制限されており、複数の型パラメータは、記号で区切られます。
    型パラメーターを定義した後は、通常の型を使用するのと同じように、クラス内の定義位置以降のほぼどこでも (静的ブロック、静的プロパティ、静的メソッドを除く) 型パラメーターを使用できます。
    親クラスで定義された型パラメータはサブクラスに継承できないことに注意してください。
    public class TestClassDefine < ;>、1 つ以上の型パラメーターの名前を指定します。
    型パラメーターの値の範囲を制限したり、複数の型パラメーターを記号で区切ることもできます。
    型パラメータを定義した後は、通常の型を使用する場合と同様に、メソッド内の定義位置以降の任意の場所で型パラメータを使用できます。
    例:
    public T testGenericMethodDefine(T t, S s){
    ...
    }
    注: 型パラメーターを使用してメソッドを定義する主な目的は、複数のパラメーターを表現して戻り値を返すことです。価値観間の関係。たとえば、この例の T と S の間の継承関係では、戻り値の型は最初の型パラメーターの値と同じです。
    ポリモーフィズムを実現したいだけの場合は、最初にワイルドカードを使用してください。ワイルドカードの内容については、次のセクションを参照してください。
    public void testGenericMethodDefine2(List s){

    }

    public void testGenericMethodDefine2(List s){

    }

    3.クラスまたはメソッドの型パラメータに値を割り当てる場合は、すべての型パラメータを割り当てる必要があります。そうしないと、コンパイル エラーが発生します。

    3.1 型パラメータを持つクラスに型パラメータを割り当てる
    型パラメータを持つクラスに型パラメータを割り当てる方法は 2 つあります
    まず、クラス変数を宣言するかインスタンス化します。たとえば、
    List list;
    list = new ArrayList;
    2 番目の継承クラスまたはインターフェイスを実装する場合。たとえば、
    public class MyList extends ArrayListimplements List

    3.2 型パラメータを持つメソッドへの値の割り当て
    ジェネリック メソッドを呼び出すと、コンパイラは自動的に値を割り当てます。型パラメータへの代入が成功しない場合、コンパイル エラーが発生します。たとえば
    public T testGenericMethodDefine3(T t, List list){
    ...
    }
    public T testGenericMethodDefine4(List list list2){
    ...
    }

    Number n = null;
    Integer i = null;
    testGenericMethodDefine(n, i);//このとき、T は Number で、S は Integer です
    testGenericMethodDefine(o, i);/ / T はオブジェクト、S は整数です

    List list1 = null;
    testGenericMethodDefine3(i, list1)//T はこの時点では Number です

    List list2 = null;
    testGenericMethodDefine4(list1, list2) // コンパイルエラー
    3.3 ワイルドカード
    上記 2 つのセクションでは、型パラメータに特定の値が割り当てられていますが、さらに、未定義の値を型パラメータに割り当てることもできます。例:
    ListunknownList;
    List? super Integer>
    注: Java コレクション フレームワークでは、パラメーター値が不明なクラスの場合、読み取りのみ可能です 要素のうち、要素を追加することはできません
    その型が不明であるため、コンパイラは追加された要素の型がコンテナの型と互換性があるかどうかを識別できません

    唯一の例外です。 List listString;
    List<>unknownList2 = listString;
    unknownList2;
    listString =unknownList;// 配列パラダイム
    を宣言するために、クラスを使用できます。配列ですが、配列を作成することはできません
    List [] iListArray;
    new ArrayList[10];// 実装原理

    5.1.実行時には一般的な情報は含まれません。クラスのインスタンスのみが含まれます。型パラメーターの定義情報が含まれます。
    ジェネリックは、Java コンパイラーによる消去と呼ばれるフロントエンド プロセスを通じて実装されます。これは (基本的に) 汎用バージョンを非汎用バージョンに変換する、ソースからソースへの変換と考えることができます。
    基本的に、消去によりすべてのジェネリック型情報が削除されます。山かっこ内のすべての型情報は破棄されるため、たとえば、
    List 型は List に変換されます。型変数へのすべての参照は、型変数 (通常は Object) の上限に置き換えられます。また、
    結果のコードの型が正しくない場合は、適切な型への変換が挿入されます。 ️ 。これは、時間やスペースのオーバーヘッドが追加されないことを意味し、これは素晴らしいことです。残念ながら、これは型変換に依存できないことも意味します。

    5.2. ジェネリック クラスはそのすべての呼び出しで共有されます
    次のコードによって出力される結果は何ですか?
    List l1 = 新しい ArrayList();
    List l2 = new ArrayList();
    System.out.println(l1.getClass() == l2.getClass()) ;
    もしかしたら嘘だと言うかも知れませんが、それは間違っています。 true と出力されます。ジェネリック クラスのすべてのインスタンスは、実際の型パラメーターに関係なく、実行時に同じランタイム クラスを持つためです。
    実際、ジェネリックがジェネリックと呼ばれる理由は、考えられるすべての型パラメータに対して同じ動作をするためであり、同じクラスが多くの異なる
    型と見なすことができるからです。その結果、クラスの静的変数とメソッドもすべてのインスタンス間で共有されます。このため、静的メソッドまたは静的初期化コード内で、または静的変数を宣言および初期化するときに、型パラメーター (型パラメーターは特定のインスタンスに属します) を使用することは違法です。

    5.3. キャストとinstanceof
    ジェネリック クラスがそのすべてのインスタンスによって共有されるもう 1 つの意味は、インスタンスが特定のタイプのジェネリック クラスであるかどうかを確認するのは無意味であるということです。 I Collection CS = New ArrayList & LT; String & GT;
    If (CS Instanceof Collection & LT; String & GT;) // 同様に不正です
    String & gt; = (Collection & LT; String & GT; ) cs;
    ランタイム環境ではそのようなチェックが行われないため、未チェックの警告が表示されます。

    6. クラスのジェネリック処理
    Java 5以降、クラスはジェネリックになります。
    JDK1.5 の変更点の 1 つは、クラス java.lang.Class がジェネリックになったことです。これは、ジェネリックスをコンテナー クラスを超えて拡張する興味深い例です。
    さて、Class には型パラメータ T があります。T は何を表しているのかと疑問に思うかもしれません。 Class オブジェクトによって表される型を表します。たとえば、
    String.class 型は Class を表し、Serializable.class は Class を表します。
    これを使用して、リフレクション コードのタイプ セーフティを向上させることができます。
    特に、Class の newInstance() メソッドが T を返すようになったので、リフレクションを使用してオブジェクトを作成するときに、より正確な型を取得できるようになりました。
    たとえば、SQL ステートメントを指定してデータベース クエリを実行し、クエリ条件を満たすデータベース内のオブジェクトのコレクションを返すツール メソッドを作成するとします。 1 つの方法は、次のコードのように、ファクトリ オブジェクトを明示的に渡すことです。 Factory, String ステートメント) {
    Collection & LT; Result = New ArrayList & LT & ++) { /* jdbc の結果を反復処理します。 item = Factory.make(); T item =
    }
    次のように呼び出すことができます:
    select(new Factory(){
    public EmpInfo make() { return new EmpIn fo(); }俳優になる
    class EmpInfoFactoryimplements Factory { ...
    public EmpInfo make() { return new EmpInfo();}
    }
    次に呼び出します:
    select(getMyEmpInfoFactory(), "selection string");
    この解決策の欠点それは、呼び出しサイトで長い匿名ファクトリ クラスを使用するか、使用する型ごとにファクトリ クラスを宣言し、そのオブジェクトを呼び出しサイトに渡すことの 2 つのうちの 1 つが必要であるという点です。これは不自然です。
    クラス型パラメータ値の使用は非常に自然であり、リフレクションによって使用できます。ジェネリックのないコードは次のようになります:
    Collection emps = sqlUtility.select(EmpInfo.class, ”select * from emps”); ...
    public static Collection select(Class c, String sqlStatement) {
    Collection result = new ArrayList () ;
    /* jdbc を使用して SQL クエリを実行します */
    for ( /* jdbc の結果を反復処理します */ ) {
    Object item = c.newInstance();
    /* リフレクションを使用し、SQL の結果から項目のフィールドをすべて設定します */
    result.add(item);
    誰誰誰誰誰の result.add(item); Class がジェネリックになったので、次のように記述できます。
    Collection emps=sqlUtility.select(EmpInfo.class, ''select * from emps''); ;T>c, String sqlStatement) {
    Collection result = new ArrayList();
    /* jdbc を使用して SQL クエリを実行します */
    for ( /* jdbc の結果を反復処理します */ ) {
    T item = c.newInstance(); 必要なコレクション。
    このテクニックは非常に便利なトリックで、アノテーションを処理する新しい API で広く使用される慣用句になっています。

    7. 新旧コードの互換性

    7.1. コードの互換性を確保するために、次のコード コンパイラ (javac) が独自に型安全性を保証します
    List l = new ArrayList();
    List< ; String> l = new ArrayList();

    7.2. クラス ライブラリを汎用バージョンにアップグレードする場合は、共変の戻り値を使用するように注意してください。
    たとえば、コードを変更します
    public class Foo {
    public Foo create(){
    return new Foo();
    }
    }

    public class Bar extends Foo {
    public Foo create(){
    """"""" ;
    }
    }
    ライブラリのクライアントには注意してください。




    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衣類リムーバー

    AI Hentai Generator

    AI Hentai Generator

    AIヘンタイを無料で生成します。

    ホットツール

    メモ帳++7.3.1

    メモ帳++7.3.1

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

    SublimeText3 中国語版

    SublimeText3 中国語版

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

    ゼンドスタジオ 13.0.1

    ゼンドスタジオ 13.0.1

    強力な PHP 統合開発環境

    ドリームウィーバー CS6

    ドリームウィーバー CS6

    ビジュアル Web 開発ツール

    SublimeText3 Mac版

    SublimeText3 Mac版

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

    ジェネリック関数は Golang の可変長引数の型の問題を解決しますか? ジェネリック関数は Golang の可変長引数の型の問題を解決しますか? Apr 16, 2024 pm 06:12 PM

    Go のジェネリック関数は、可変個引数型の問題を解決します。ジェネリック関数を使用すると、実行時に型パラメータを指定できます。これにより、さまざまな型のパラメータを処理できる関数を作成できるようになります。たとえば、Max 関数は、2 つの同等のパラメーターを受け取り、大きい方の値を返す汎用関数です。ジェネリック関数を使用すると、さまざまな種類のパラメーターを処理できる、より柔軟で汎用的なコードを作成できます。

    golang でのジェネリックスの具体的なアプリケーション シナリオ golang でのジェネリックスの具体的なアプリケーション シナリオ May 04, 2024 am 11:45 AM

    Go でのジェネリックスのアプリケーション シナリオ: コレクション操作: フィルター処理など、あらゆるタイプに適したコレクション操作を作成します。データ構造: キュー、スタック、マップなどの汎用データ構造を作成して、さまざまな種類のデータを保存および操作します。アルゴリズム: さまざまな種類のデータを処理できる、並べ替え、検索、リダクションなどの汎用アルゴリズムを作成します。

    Java関数ジェネリックの上限と下限は何ですか?使い方? Java関数ジェネリックの上限と下限は何ですか?使い方? Apr 26, 2024 am 11:45 AM

    Java 関数ジェネリックでは、上限と下限を設定できます。 Extends は、関数によって受け入れられるか返されるデータ型が、指定された型のサブタイプである必要があることを指定します。下限 (スーパー) は、関数によって受け入れられるか返されるデータ型が、指定された型のスーパータイプである必要があることを指定します。ジェネリックを使用すると、コードの再利用性とセキュリティが向上します。

    Golang でのジェネリックの利点と使用法を調べる Golang でのジェネリックの利点と使用法を調べる Apr 03, 2024 pm 02:03 PM

    回答: Golang ジェネリックは、コードの再利用性、柔軟性、型安全性、およびスケーラビリティを向上させるための強力なツールです。詳細な説明: 利点: コードの再利用性: 共通のアルゴリズムとデータ構造 柔軟性: 特定の型のインスタンスのランタイム作成 型安全性: コンパイル時の型チェック 拡張性: 拡張およびカスタマイズが容易 目的: 共通の関数: 並べ替え、比較 リストなどの共通のデータ構造、マップ、スタックなど。型エイリアス: 型宣言を簡素化します。制約されたジェネリックス: 型安全性を確保します。

    Android開発におけるJavaジェネリックの適用 Android開発におけるJavaジェネリックの適用 Apr 12, 2024 pm 01:54 PM

    Android 開発におけるジェネリックの適用により、コードの再利用性、セキュリティ、柔軟性が強化されます。この構文は、型パラメーター化されたデータの操作に使用できる型変数 T の宣言で構成されます。動作中のジェネリックにはカスタム データ アダプターが含まれており、アダプターがあらゆる種類のカスタム データ オブジェクトに適応できるようになります。 Android は、さまざまな型のパラメーターを操作できる汎用リスト クラス (ArrayList など) と汎用メソッドも提供します。ジェネリックスを使用する利点には、コードの再利用性、セキュリティ、柔軟性が含まれますが、コードの可読性を確保するために正しい境界を指定し、適度に境界を使用するように注意する必要があります。

    Golang ジェネリックは関数のシグネチャとパラメーターにどのような影響を与えますか? Golang ジェネリックは関数のシグネチャとパラメーターにどのような影響を与えますか? Apr 17, 2024 am 08:39 AM

    Go 関数のシグネチャとパラメーターに対するジェネリックスの影響には、以下が含まれます。 型パラメーター: 関数シグネチャーには、関数が使用できる型を指定する型パラメーターを含めることができます。型制約: 型パラメーターには、満たさなければならない条件を指定する制約を設定できます。パラメーターの型の推論: コンパイラーは、指定されていない型パラメーターの型を推論できます。型の指定: パラメーターの型を明示的に指定して、ジェネリック関数を呼び出すことができます。これにより、コードの再利用性と柔軟性が向上し、複数の型で使用できる関数や型を作成できるようになります。

    Golang の汎用関数の制限は何ですか? Golang の汎用関数の制限は何ですか? Apr 16, 2024 pm 05:12 PM

    Go 汎用関数の制限: 型パラメーターのみがサポートされ、値パラメーターはサポートされません。関数の再帰はサポートされていません。型パラメータは明示的に指定できず、コンパイラによって推論されます。

    Java 列挙型はジェネリックとどのように連携するのでしょうか? Java 列挙型はジェネリックとどのように連携するのでしょうか? May 04, 2024 am 08:36 AM

    Java における列挙型とジェネリックの組み合わせ: ジェネリックを使用して列挙を宣言する場合は、山かっこを追加する必要があります。T は型パラメータです。ジェネリック クラスを作成するときは、山括弧を追加する必要もあります。T は、任意の型を格納できる型パラメーターです。この組み合わせにより、コードの柔軟性、型安全性が向上し、コードが簡素化されます。

    See all articles