Javaジェネリックス:説明とメソッド
Java言語の出現が完了して以来間違いなく、その機能性に肯定的な瞬間をもたらした多くの変更。そのような意味のある変更の1つは、Java Genericの導入または一般化です。この機能により、言語はより柔軟で多用途になるだけでなく、データ型の削減という面でもより安全になりました。
事実はジェネリックジェネリックの導入前Javaのコードは、オブジェクト型を参照することによってのみ作成できます。このようなリンクは、任意のオブジェクトに割り当てることができます。結局のところ、Javaのすべてのクラスは、Objectクラスの暗黙の子孫です。ただし、この方法は、オブジェクトをオブジェクトからターゲット型に明示的に変換するときに、多くの型安全エラーの原因となる可能性があります。一般化を使用すると、すべてのキャストが暗黙的かつ自動的に実行され、エラーの可能性さえも排除されます。
Javaジェネリックス:説明と例
下の図の一般的なクラスに一般化を適用する簡単な例を考えてみましょう。それでは、Java Genericの微妙な微妙な違いを詳しく調べてみましょう。
どのようにペアクラスの発表。クラス名の直後に、角カッコが開き、文字Tが表示されます。これは、このクラスのインスタンスを作成するときに特定の型に置き換えられる一種のプレースホルダーです。これは、Pair <Integer> obj = new Pair <Integer>()のようになります。 Tの代わりに任意の文字を指定できますが、原則としてT、VまたはEを使用することに注意してください。
注意: 8番目のバージョンのJavaからリンクが宣言されたときにターゲットタイプを指定すると、コンストラクタの山括弧は空のままにすることができます。したがって、上記の例は次のように書き直すことができます:Pair <Integer> obj = new Pair <>()。
このように宣言されたクラスは、メソッドによって返される特定のフィールド型、参照、およびメソッドの代わりに、この文字を使用できます。クラスオブジェクトの作成時にTが特定の型に置き換えられるため、この場合の第1フィールドと第2フィールドはInteger型になります。
ロジックに続いて、引数firstItemとsecondItem、適切なコンストラクタと呼ばも、Integer型またはサブクラスでなければなりません。あなたがオブジェクトを作成するときに指定されたものと異なるデータ型を送信しようとすると、コンパイラはこのミスをせません。ペア<整数> OBJ =新しいペア<>(新しい整数(1)、新しい整数(2))を次のようにオブジェクトがあろうこのように、引数のコンストラクタ。同じことは、引数とメソッドsetFirst setSecondに適用されます。そして、あなたはおそらく、メソッドgetFirstとgetSecond推測してきたとInteger型の値を返しますよう。
いくつかの型パラメータを持つ汎用クラス
ジェネリッククラスでは、角カッコで指定された複数の型パラメータをコンマで区切って宣言することもできます。この場合のPairクラスを下の図に示します。
ご覧のように、そのようなクラスのインスタンスを作成するとき山括弧では、パラメータと同じ数の型を指定する必要があります。 Mapのような種類のデータ構造に精通している場合は、同じ原則がそこで使用されていることがわかります。最初の引数はキーの型を決定し、2番目の引数は値の型を決定します。オブジェクトの作成に渡される引数の型は同じであってもよいことに注意してください。したがって、Pairクラスのインスタンスの次の宣言は、Pair <String、String> objです。
一般化のいくつかの特徴
先に進む前に、Javaコンパイラは、Pairクラスの異なるバージョンを作成しません。実際には、コンパイルプロセス中に、ジェネリックタイプに関するすべての情報が削除されます。代わりに、対応する型がキャストされ、Pairクラスの特別なバージョンが作成されます。しかし、プログラム自体には、このクラスの一般化されたバージョンが1つしかありません。このプロセスは、Java汎用タイプのクリーニングで呼び出されます。
重要な点に注目しましょう。 同じJava汎用クラスの異なるバージョンへの参照は、同じオブジェクトを指すことはできません。つまり、ペア<Integer> obj1とペア<double> obj2という2つのリンクがあるとします。したがって、行obj1 = obj2にエラーが発生します。両方の変数はPair <T>型ですが、それらが参照するオブジェクトは異なります。これはJava Genericの型のセキュリティの鮮明な例です。
一般化されたクラスに課される制限
一般化を適用できることを知ることは重要ですつまり、パラメータgenericクラスに渡される引数java型の引数はクラス型でなければなりません。そのような単純な型、例えば、double型またはlong型は、送信することができません。言い換えれば、Pairクラス宣言の次の行は無効です:Pair <int> obj。しかし、Javaにはそれぞれのプリミティブ型に対応するラッパークラスがあるため、この制限は深刻な問題ではありません。厳密に言えば、Pairクラスに整数値と論理値をカプセル化したい場合は、Pair <Integer、Boolean> obj = new Pair <>(25、true)のいずれかを実行します。
もう一つの重大な制限は、型パラメータのインスタンスを作成することは不可能です。したがって、次の行はコンパイルエラーを引き起こします:T first = new T()。これは、完全なクラスか抽象的なインターフェースが引数として渡されるかどうかを事前に知らないので、明らかです。配列の作成も同じです。
限定タイプ
非常に頻繁に、javaジェネリッククラスに引数として渡すことができる型のリストを制限する必要があります。私たちのPairクラスでは、さらに数学的演算のための数値を排他的にカプセル化したいとしましょう。これを行うには、型パラメータの上限を設定する必要があります。これは、山括弧で渡されたすべての引数によって継承されたスーパークラス宣言を使用して実装されます。これは、class Pair <T extends Number>のようになります。このようにして、コンパイラは、Tパラメータの代わりに、Numberクラスまたはそのサブクラスのいずれかを置き換えることができることを学習します。
これは一般的な手法です。 このような制限は、同じクラスの型パラメータの互換性を保証するためによく使用されます。 Pairクラスの例を考えてみましょう。クラスPair <T、V extends T>です。ここでは、型Tは任意であり、型Vは型Tまたはそのサブクラスのいずれかでなければならないことをコンパイラに伝えます。
「下から」という制限はまったく同じです単語の代わりにスーパーという単語が書かれています。つまり、Pair <T super ArrayList>クラスの宣言は、Tの代わりに、ArrayListまたは継承するクラスまたはインタフェースのいずれかを代用できることを示します。
一般的なJavaメソッドとコンストラクタ
Javaの一般化は、クラスだけでなくメソッドに関しても適用できます。したがって、一般化されたメソッドは通常のクラスで宣言することができます。
上記の図のように、一般化されたメソッドの宣言には何も複雑ではありません。戻り値の型メソッドの前に山カッコを入れ、型パラメータを指定するだけで十分です。
コンストラクタの場合は、すべて同じ方法で行われます。
この場合、角括弧は値を返さないため、コンストラクタの名前の前に置かれます。両方のプログラムの作業の結果は次のようになります。
整数
文字列