Java Genericsサンプルチュートリアル-Genericメソッド、クラス、インターフェイス
Java Genricsは、Java5で導入された最も重要な機能の1つです。
Javaコレクションで作業していて、バージョン5以降を使用している場合は、それを使用したと確信しています。
コレクションクラスを使用したJavaのジェネリックは非常に簡単ですが、作成するだけでなく、はるかに多くの機能を提供します。コレクションのタイプ。
この記事では、ジェネリックの機能について学習します。ジェネリックスを理解することは、専門用語を使用すると混乱することがあるので、シンプルで理解しやすいものにしようと思います。
Javaのジェネリック
Java 5でジェネリックが追加され、コンパイル時の型チェックを提供し、作業中に一般的だったClassCastException
のリスクを排除しました。コレクションクラスを使用します。コレクションフレームワーク全体が、型安全性のためにジェネリックを使用するように書き直されました。ジェネリックスがコレクションクラスを安全に使用するのにどのように役立つかを見てみましょう。
上記のコードは正常にコンパイルされますが、リスト内のオブジェクトを文字列にキャストしようとしているのに対し、要素の1つは整数型であるため、実行時にClassCastExceptionがスローされます。 Java 5以降では、以下のようなコレクションクラスを使用します。
リストの作成時に、リスト内の要素のタイプが文字列になるように指定していることに注意してください。したがって、リストに他のタイプのオブジェクトを追加しようとすると、プログラムはコンパイル時エラーをスローします。また、forループでは、リスト内の要素を型キャストする必要がないため、実行時にClassCastExceptionが削除されることに注意してください。
Javaジェネリッククラス
独自のクラスを定義できますジェネリック型。ジェネリック型は、型に対してパラメーター化されるクラスまたはインターフェースです。角かっこ(< >)を使用して型パラメーターを指定します。
利点を理解するために、たとえば次のような単純なクラスがあります。
このクラスを使用している間は型キャストを使用する必要があり、実行時にClassCastExceptionが生成される可能性があることに注意してください。次に、Java汎用クラスを使用して、以下に示すように同じクラスを書き換えます。
mainメソッドでGenericsTypeクラスが使用されていることに注意してください。型キャストを行う必要はなく、実行時にClassCastExceptionを削除できます。作成時に型を指定しない場合、コンパイラは「GenericsTypeはraw型です。
ジェネリック型への参照GenericsType < T >はパラメータ化する必要があります」。タイプを指定しない場合、タイプはObject
になるため、両方の文字列が許可されます。と整数オブジェクト。ただし、ランタイムエラーを生成する可能性のあるraw型で作業している間は型キャストを使用する必要があるため、常にこれを回避する必要があります。
また、javaオートボクシングをサポートしていることに注意してください。
Java汎用インターフェース
比較可能なインターフェースは、インターフェースのジェネリックスの優れた例であり、次のように記述されています。
同様に、javaでジェネリックスインターフェースを作成することもできます。マップインターフェイスのように複数の型パラメータがあります。Aゲインパラメータ化された値をパラメータ化された型に提供することもできます。たとえば、new HashMap<String, List<String>>();
は有効です。
Java汎用型
Java汎用型の命名規則はコードを簡単に理解するのに役立ち、命名規則を持つことはJavaプログラミング言語のベストプラクティスの1つです。そのため、ジェネリックには独自の命名規則もあります。通常、タイプパラメータ名は、Java変数と簡単に区別できるように、単一の大文字です。最も一般的に使用される型パラメーター名は次のとおりです。
- E –要素(Javaコレクションフレームワークで広く使用されています。たとえば、ArrayList、Setなど)
- K –キー(マップで使用)
- N –番号
- T –タイプ
- V –値(マップで使用)
- S、U、 Vなど– 2番目、3番目、4番目のタイプ
Javaジェネリックメソッド
クラス全体をパラメーター化したくない場合があります。その場合は、次のことができます。 Javaジェネリックメソッドを作成します。コンストラクターは特殊な種類のメソッドであるため、コンストラクターでもジェネリック型を使用できます。
これは、javaジェネリックメソッドの例を示すクラスです。
isEqualメソッドに注意してください。メソッドでジェネリック型を使用するための構文を示す署名。また、Javaプログラムでこれらのメソッドを使用する方法にも注意してください。これらのメソッドを呼び出すときに型を指定することも、通常のメソッドのように呼び出すこともできます。 Javaコンパイラは、使用する変数の型を決定するのに十分賢いです。この機能は型推論と呼ばれます。
JavaGenericsの有界型パラメーター
たとえば、2つのオブジェクトを比較するメソッドで、パラメーター化された型で使用できるオブジェクトの型を制限したいとします。受け入れられたオブジェクトがComparablesであることを確認してください。制限付き型パラメーターを宣言するには、以下のメソッドのように、型パラメーターの名前、extendsキーワード、上限をリストします。
これらのメソッドの呼び出しは、Comparableでないクラスを使用しようとすると、コンパイル時エラーがスローされることを除いて、無制限のメソッドに似ています。
制限付き型パラメーターは、メソッドだけでなくメソッドでも使用できます。クラスとインターフェース。
Java Genericsは複数の境界もサポートします。つまり、< T extends A & B & C >。この場合、Aはインターフェイスまたはクラスにすることができます。 Aがクラスの場合、BとCはインターフェイスである必要があります。複数の境界に複数のクラスを含めることはできません。
Javaのジェネリックスと継承
Java継承により、AがBのサブクラスである場合、変数Aを別の変数Bに割り当てることができます。したがって、任意のジェネリック型のAをジェネリック型のBに割り当てることができると考えるかもしれませんが、そうではありません。簡単なプログラムでこれを見てみましょう。
MyClass < String >変数をMyClassに割り当てることは許可されていません。 <オブジェクト>変数は関連していないため、実際にはMyClass < T >親はオブジェクトです。
Java汎用クラスとサブタイプ
汎用クラスまたはインターフェースを拡張または実装することで、サブタイプ化できます。あるクラスまたはインターフェイスの型パラメータと別の型パラメータの関係は、extendsおよびimplements句によって決定されます。
type引数を変更しない限り、サブタイプの関係は保持されます。以下に、複数の型パラメーターの例を示します。
List < String はMyList < String、Object >、MyList < String、Integer >など。
JavaGenericsワイルドカード
質問マーク(?)は、ジェネリックのワイルドカードであり、不明なタイプ。ワイルドカードは、パラメーター、フィールド、またはローカル変数の型として使用でき、場合によっては戻り値の型として使用できます。ジェネリックメソッドを呼び出したり、ジェネリッククラスをインスタンス化したりするときに、ワイルドカードを使用することはできません。次のセクションでは、上限のあるワイルドカード、下限のあるワイルドカード、およびワイルドカードのキャプチャについて学習します。
9.1)JavaGenericsの上限のあるワイルドカード
上限のあるワイルドカードは、メソッド内の変数のタイプに関する制限。リスト内の数値の合計を返すメソッドを作成するとします。そのため、実装は次のようになります。
ここで、上記の実装では、List < Integer >とList
Double >は関連していません。これは、上限のワイルドカードが役立つ場合です。 extendsキーワードと、上限またはそのサブクラスタイプの引数を渡すことができる上限クラスまたはインターフェイスを備えたジェネリックワイルドカードを使用します。
上記の実装は、以下のプログラムのように変更できます。
インターフェースの観点からコードを書くのと似ています。上記のメソッドでは、上限クラスNumberのすべてのメソッドを使用できます。上限付きリストでは、null以外のオブジェクトをリストに追加できないことに注意してください。 sumメソッド内のリストに要素を追加しようとすると、プログラムはコンパイルされません。
9.2)Java Generics Unbounded Wildcard
状況が発生することがあります。ジェネリックメソッドがすべてのタイプで機能するようにしたい場合、この場合、無制限のワイルドカードを使用できます。 <を使用するのと同じですか?オブジェクトを拡張します>。
リストを提供できます< String >またはList < Integer >またはその他のタイプのオブジェクトリスト引数printDataメソッド。上限リストと同様に、リストに何も追加することはできません。
9。3)JavaGenericsの下限ワイルドカード
メソッド内の整数のリストに整数を追加する場合、引数の型をList <整数のままにしておくことができます。 >ただし、整数で拘束されますが、List < Number >とList <オブジェクト>も整数を保持できるため、下限のワイルドカードを使用してこれを実現できます。これを実現するために、スーパーキーワードと下限クラスを含むジェネリックワイルドカード(?)を使用します。
引数として下限または下限のスーパータイプを渡すことができます。この場合、javaコンパイラで下限を追加できます。リストにバインドされたオブジェクトタイプ。
Genericsワイルドカードを使用したサブタイピング
Java Generics Type Erasure
Generics in Javaは、コンパイル時に型チェックを提供するために追加され、実行時には使用されないため、Javaコンパイラは型消去機能を使用して、バイトコード内のすべてのジェネリック型チェックコードを削除し、必要に応じて型キャストを挿入します。型消去により、パラメーター化された型に対して新しいクラスが作成されないことが保証されます。その結果、ジェネリックスには実行時のオーバーヘッドは発生しません。
たとえば、以下のようなジェネリックスクラスがある場合。
Javaコンパイラは、制限付き型パラメータTを最初の制限付きインターフェイスComparableに置き換えます。 、以下のコードのように:
ジェネリックに関するFAQ
12.1)なぜJavaでジェネリックを使用するのですか?
ジェネリックは強力なコンパイル時の型チェックを提供し、 ClassCastExceptionとオブジェクトの明示的なキャスト。
12.2)ジェネリックスのTとは何ですか?
< T を使用して、ジェネリッククラス、インターフェイス、およびメソッドを作成します。 Tは、使用時に実際の型に置き換えられます。
12.3)ジェネリックはJavaでどのように機能しますか?
ジェネリックコードは、型の安全性を保証します。コンパイラは、型消去を使用してコンパイル時にすべての型パラメータを削除し、実行時の過負荷を軽減します。
Javaのジェネリック–参考資料
これで、java、javaのジェネリックはすべてです。ジェネリックは非常に広大なトピックであり、それを効果的に理解して使用するには多くの時間が必要です。この投稿は、ジェネリックスの基本的な詳細と、それを使用してプログラムを型安全性で拡張する方法を提供する試みです。