Java-generics-quick-guide
Javaジェネリック-概要
整数配列、文字列配列、または順序付けをサポートする任意のタイプの配列内の要素を並べ替えることができる単一の並べ替えメソッドを作成できれば便利です。
Javaジェネリックメソッドとジェネリッククラスを使用すると、プログラマは、単一のメソッド宣言で関連メソッドのセットを、単一のクラス宣言で関連タイプのセットをそれぞれ指定できます。
ジェネリックはまた、プログラマがコンパイル時に無効な型をキャッチできるコンパイル時の型安全性も提供します。
Javaジェネリックコンセプトを使用して、オブジェクトの配列を並べ替えるためのジェネリックメソッドを記述し、整数配列、ダブル配列、ストリング配列などでジェネリックメソッドを呼び出して、配列要素を並べ替えます。
Java Generics-環境設定
ローカル環境のセットアップ
JUnitはJavaのフレームワークなので、最初の要件はJDKをマシンにインストールすることです。
システム要件
JDK | 1.5 or above. |
Memory | No minimum requirement. |
Disk Space | No minimum requirement. |
Operating System | No minimum requirement. |
ステップ1:マシンでのJavaインストールの検証
まず、コンソールを開き、作業しているオペレーティングシステムに基づいてjavaコマンドを実行します。
OS | Task | Command |
---|---|---|
Windows | Open Command Console | c:\> java -version |
Linux | Open Command Terminal | $ java -version |
Mac | Open Terminal | machine:< joseph$ java -version |
すべてのオペレーティングシステムの出力を確認しましょう-
OS | Output |
---|---|
Windows |
java version "1.6.0_21" Java(TM)SEランタイム環境(ビルド1.6.0_21-b07) Java HotSpot(TM)Client VM(ビルド17.0-b17、混合モード、共有) |
Linux |
java version "1.6.0_21" Java(TM)SEランタイム環境(ビルド1.6.0_21-b07) Java HotSpot(TM)Client VM(ビルド17.0-b17、混合モード、共有) |
Mac |
java version "1.6.0_21" Java(TM)SEランタイム環境(ビルド1.6.0_21-b07) Java HotSpot(TM)64ビットサーバーVM(ビルド17.0-b17、混合モード、共有) |
システムにJavaがインストールされていない場合は、次のリンクからJavaソフトウェア開発キット(SDK)をダウンロードしてください。https://www.oracle.com/technetwork/java/javase/downloads/indexl [https://www .oracle.com]。 このチュートリアルのインストールバージョンとしてJava 1.6.0_21を想定しています。
ステップ2:JAVA環境を設定する
OS | Output |
---|---|
Windows | Set the environment variable JAVA_HOME to C:\Program Files\Java\jdk1.6.0_21 |
Linux | export JAVA_HOME =/usr/local/java-current |
Mac | export JAVA_HOME =/Library/Java/Home |
Javaコンパイラの場所をシステムパスに追加します。
OS | Output |
---|---|
Windows | Append the string C:\Program Files\Java\jdk1.6.0_21\bin *at the end of the system variable, Path*. |
Linux | export PATH = $PATH:$JAVA_HOME/bin/ |
Mac | not required |
上記の説明に従って、コマンド java -version を使用してJavaのインストールを確認します。
Javaジェネリック-クラス
ジェネリッククラス宣言は、クラス名の後に型パラメーターセクションが続くことを除いて、非ジェネリッククラス宣言のように見えます。
ジェネリッククラスの型パラメーターセクションには、コンマで区切られた1つ以上の型パラメーターを含めることができます。 これらのクラスは、1つ以上のパラメーターを受け入れるため、パラメーター化クラスまたはパラメーター化タイプと呼ばれます。
構文
どこで
- Box -Boxはジェネリッククラスです。
- T -ジェネリッククラスに渡されるジェネリック型パラメーター。 任意のオブジェクトを取ることができます。
- t -ジェネリック型Tのインスタンス。
説明
Tは、ジェネリッククラスBoxに渡される型パラメーターであり、Boxオブジェクトの作成時に渡す必要があります。
例
任意のエディターを使用して、次のJavaプログラムを作成します。
GenericsTester.java
これにより、次の結果が生成されます。
出力
型パラメーターの命名規則
慣例により、型パラメーターは通常のクラス名またはインターフェイス名で簡単に区別できるように、単一の大文字として名前が付けられます。 以下は、一般的に使用される型パラメータ名のリストです-
- E -要素。主にJavaコレクションフレームワークで使用されます。
- K -キー。主にマップのキーのパラメータータイプを表すために使用されます。
- V -値。主にマップの値のパラメータータイプを表すために使用されます。
- N -数値。主に数値を表すために使用されます。
- T -タイプ。主に最初のジェネリックタイプパラメータを表すために使用されます。
- S -タイプ。主に2番目の汎用タイプパラメータを表すために使用されます。
- U -タイプ。主に3番目の汎用タイプパラメータを表すために使用されます。
- V -タイプ。主に4番目のジェネリックタイプパラメーターを表すために使用されます。
次の例では、上記の概念を紹介します。
例
任意のエディターを使用して、次のJavaプログラムを作成します。
GenericsTester.java
これにより、次の結果が生成されます。
出力
Javaジェネリック-型推論
型の推論は、メソッド呼び出しとその対応する宣言を調べて型引数をチェックおよび決定するJavaコンパイラの機能を表します。 推論アルゴリズムは引数の型をチェックし、可能な場合は、割り当てられた型が返されます。 推論アルゴリズムは、すべての型パラメーターをフルフィルできる特定の型を見つけようとします。
コンパイラは、未確認の変換警告を生成します。この場合、型推論は使用されません。
構文
どこで
- Box -Boxはジェネリッククラスです。
- <> -ダイアモンド演算子は型推論を示します。
説明
コンパイラーは、ダイヤモンド演算子を使用して、パラメーターのタイプを決定します。 この演算子は、Java SE 7バージョン以降で利用可能です。
例
任意のエディターを使用して、次のJavaプログラムを作成します。
GenericsTester.java
これにより、次の結果が生成されます。
出力
Javaジェネリック-メソッド
異なる型の引数で呼び出すことができる単一のジェネリックメソッド宣言を作成できます。 ジェネリックメソッドに渡される引数のタイプに基づいて、コンパイラは各メソッド呼び出しを適切に処理します。 以下は、ジェネリックメソッドを定義するルールです-
- すべてのジェネリックメソッド宣言には、メソッドの戻り型(次の例では<E>)の前に山括弧(<および>)で区切られた型パラメーターセクションがあります。
- 各型パラメーターセクションには、カンマで区切られた1つ以上の型パラメーターが含まれています。 型パラメーターとも呼ばれる型変数は、一般的な型名を指定する識別子です。
- 型パラメーターを使用して戻り型を宣言し、ジェネリックメソッドに渡される引数の型のプレースホルダーとして機能することができます。これは実際の型引数として知られています。
- ジェネリックメソッドの本体は、他のメソッドの本体と同様に宣言されます。 型パラメーターは参照型のみを表すことができ、プリミティブ型(int、double、charなど)は表すことができないことに注意してください。
例
次の例は、単一のGenericメソッドを使用して異なるタイプの配列を印刷する方法を示しています-
これは、次の結果を生成します-
出力
Javaジェネリック-複数の型パラメーター
Genericクラスには、複数のタイプのパラメーターを含めることができます。 次の例では、上記の概念を紹介します。
例
任意のエディターを使用して、次のJavaプログラムを作成します。
GenericsTester.java
これにより、次の結果が生成されます。
出力
Javaジェネリック-パラメーター化された型
ジェネリッククラスは、型パラメーターをパラメーター化された型に置き換えることができるパラメーター化された型を持つことができます。 次の例では、上記の概念を紹介します。
例
任意のエディターを使用して、次のJavaプログラムを作成します。
GenericsTester.java
これにより、次の結果が生成されます。
出力
Javaジェネリック-生の型
生の型は、その型引数が作成中に渡されない場合、ジェネリッククラスまたはインターフェイスのオブジェクトです。 次の例では、上記の概念を紹介します。
例
任意のエディターを使用して、次のJavaプログラムを作成します。
GenericsTester.java
これにより、次の結果が生成されます。
出力
Java Generics-制限された型パラメーター
型パラメータに渡すことができる型の種類を制限したい場合があるかもしれません。 たとえば、数値を操作するメソッドは、Numberまたはそのサブクラスのインスタンスのみを受け入れたい場合があります。 これが境界型パラメータの目的です。
制限された型パラメーターを宣言するには、型パラメーターの名前をリストし、その後にextendsキーワードとその上限をリストします。
例
次の例は、extends(クラスなど)または「implements」(インターフェイスなど)を意味する一般的な意味でのextendの使用方法を示しています。 この例は、3つのComparableオブジェクトのうち最大のものを返す汎用メソッドです-
これは、次の結果を生成します-
出力
Javaジェネリック-複数の境界
型パラメーターには複数の境界を設定できます。
構文
どこで
- maximum -最大値は一般的な方法です。
- T -ジェネリックメソッドに渡されるジェネリック型パラメーター。 任意のオブジェクトを取ることができます。
説明
Tは、ジェネリッククラスBoxに渡される型パラメーターであり、Numberクラスのサブタイプである必要があり、Comparableインターフェイスを実装する必要があります。 クラスがバインドされて渡される場合、インターフェイスの前に最初に渡される必要があります。そうでないと、コンパイル時エラーが発生します。
例
任意のエディターを使用して、次のJavaプログラムを作成します。
これは、次の結果を生成します-
出力
Javaジェネリック-リスト
Javaは、Listインターフェイスで一般的なサポートを提供しています。
構文
どこで
- list -リストインターフェイスのオブジェクト。
- T -リスト宣言中に渡されるジェネリック型パラメーター。
説明
Tは、ジェネリックインターフェイスListおよびその実装クラスArrayListに渡される型パラメーターです。
例
任意のエディターを使用して、次のJavaプログラムを作成します。
これは、次の結果を生成します-
出力
Javaジェネリック-セット
JavaはSetインターフェースで一般的なサポートを提供しています。
構文
どこで
- set -Set Interfaceのオブジェクト。
- T -セット宣言中に渡されるジェネリック型パラメーター。
説明
Tは、ジェネリックインターフェイスSetおよびその実装クラスHashSetに渡される型パラメーターです。
例
任意のエディターを使用して、次のJavaプログラムを作成します。
これは、次の結果を生成します-
出力
Java Generics-マップ
Javaは、Mapインターフェイスで一般的なサポートを提供しています。
構文
どこで
- set -Set Interfaceのオブジェクト。
- T -セット宣言中に渡されるジェネリック型パラメーター。
説明
Tは、ジェネリックインターフェイスSetおよびその実装クラスHashSetに渡される型パラメーターです。
例
任意のエディターを使用して、次のJavaプログラムを作成します。
これは、次の結果を生成します-
出力
Javaジェネリック-上限のあるワイルドカード
疑問符(?)はワイルドカードを表し、ジェネリックの不明なタイプを表します。 型パラメータに渡すことができる型の種類を制限したい場合があるかもしれません。 たとえば、数値を操作するメソッドは、Numberまたはそのサブクラスのインスタンスのみを受け入れたい場合があります。
上限のあるワイルドカードパラメーターを宣言するには、?をリストし、extendsキーワードを続けて、その上限を続けます。
例
次の例は、extendsを使用して上限のワイルドカードを指定する方法を示しています。
これは、次の結果を生成します-
出力
Java Generics-無制限のワイルドカード
疑問符(?)はワイルドカードを表し、ジェネリックの不明なタイプを表します。 Objectクラスで提供される機能を使用してメソッドを実装できる場合、またはコードがtypeパラメーターから独立している場合、オブジェクトを使用できる場合があります。
Unbounded Wildcardパラメーターを宣言するには、? のみ。
例
次の例は、extendedを使用して無制限のワイルドカードを指定する方法を示しています。
これは、次の結果を生成します-
出力
Javaジェネリック-下限のワイルドカード
疑問符(?)はワイルドカードを表し、ジェネリックの不明なタイプを表します。 型パラメータに渡すことができる型の種類を制限したい場合があるかもしれません。 たとえば、数値を操作するメソッドは、IntegerまたはNumberのようなスーパークラスのインスタンスのみを受け入れたい場合があります。
下限のワイルドカードパラメータを宣言するには、?をリストし、その後にsuperキーワード、その下限を続けます。
例
次の例は、superを使用して下限のワイルドカードを指定する方法を示しています。
これは、次の結果を生成します-
Java Generics-ワイルドカード使用のガイドライン
ワイルドカードは3つの方法で使用できます-
- 上限ワイルドカード-? Typeを拡張します。
- 下限ワイルドカード-? スーパータイプ。
- 無制限のワイルドカード-?
条件に最適なワイルドカードのタイプを決定するために、最初にメソッドに渡されるパラメーターのタイプを in および out パラメーターとして分類しましょう。
- in variable -in変数はコードにデータを提供します。 たとえば、copy(src、dest)。 ここで、srcはコピーされるデータである変数のように機能します。
- * out変数*-out変数は、コードによって更新されたデータを保持します。 たとえば、copy(src、dest)。 ここで、destはコピーされたデータを持つ変数のように機能します。
ワイルドカードのガイドライン。
- 上限ワイルドカード-変数が in カテゴリの場合、ワイルドカードを使用してextendsキーワードを使用します。
- 下限ワイルドカード-変数が out カテゴリの場合、ワイルドカード付きのスーパーキーワードを使用します。
- 非バインドワイルドカード-オブジェクトクラスメソッドを使用して変数にアクセスできる場合は、非バインドワイルドカードを使用します。
- ワイルドカードなし-コードが in および out カテゴリの両方の変数にアクセスしている場合、ワイルドカードを使用しないでください。
例
次の例は、上記の概念を示しています。
これは、次の結果を生成します-
Javaジェネリック-型消去
ジェネリックは、コンパイル時の厳密な型チェックに使用され、ジェネリックプログラミングを提供します。 一般的な動作を実装するために、Javaコンパイラは型消去を適用します。 型消去は、コンパイラがジェネリックパラメータを実際のクラスまたはブリッジメソッドに置き換えるプロセスです。 型消去では、コンパイラは余分なクラスが作成されず、実行時のオーバーヘッドがないことを保証します。
タイプ消去ルール
- バインドされた型パラメーターが使用されている場合、ジェネリック型の型パラメーターをバインドされた型に置き換えます。
- 制限のない型パラメーターが使用されている場合、ジェネリック型の型パラメーターをオブジェクトに置き換えます。
- 型キャストを挿入して、型の安全性を維持します。
- ブリッジメソッドを生成して、拡張ジェネリック型のポリモーフィズムを維持します。
Javaジェネリック-バインドされた型の消去
Javaコンパイラは、バウンド型パラメーターが使用されている場合、ジェネリック型の型パラメーターをバウンドに置き換えます。
例
この場合、JavaコンパイラはTをNumberクラスに置き換え、型を消去した後、コンパイラは次のコードのバイトコードを生成します。
どちらの場合でも、結果は同じです-
出力
Javaジェネリック-制限のない型の消去
Javaコンパイラは、無制限の型パラメーターが使用されている場合、ジェネリック型の型パラメーターをObjectに置き換えます。
例
この場合、JavaコンパイラはTをObjectクラスに置き換え、型を消去した後、コンパイラは次のコードのバイトコードを生成します。
どちらの場合でも、結果は同じです-
出力
Javaジェネリック-ジェネリックメソッドの消去
Javaコンパイラは、無制限の型パラメーターが使用されている場合はジェネリック型の型パラメーターをObjectに、メソッドパラメーターとして使用されている場合は型に置き換えます。
例
この場合、JavaコンパイラはTをObjectクラスに置き換え、型を消去した後、コンパイラは次のコードのバイトコードを生成します。
どちらの場合でも、結果は同じです-
出力
Javaジェネリック-プリミティブ型なし
ジェネリックを使用すると、プリミティブ型を型パラメーターとして渡すことはできません。 以下の例では、ボックスクラスにintプリミティブ型を渡すと、コンパイラーは文句を言います。 同じことを緩和するには、intプリミティブ型の代わりにIntegerオブジェクトを渡す必要があります。
例
これは、次の結果を生成します-
出力
Java Generics-インスタンスなし
型パラメーターを使用して、メソッド内でオブジェクトをインスタンス化することはできません。
このような機能を実現するには、リフレクションを使用します。
例
これは、次の結果を生成します-
Java Generics-静的フィールドなし
ジェネリックを使用すると、型パラメーターを静的にすることはできません。 静的変数はオブジェクト間で共有されるため、コンパイラは使用する型を決定できません。 静的型パラメーターが許可されている場合は、次の例を検討してください。
例
stringBoxとintegerBoxの両方にスター型の静的型変数があるため、その型を判別できません。 したがって、静的型パラメーターは許可されません。
Javaジェネリック-キャストなし
パラメータ化された型へのキャストは、無制限のワイルドカードによってパラメータ化されない限り許可されません。
同じことを実現するには、無制限のワイルドカードを使用できます。
Javaジェネリック-instanceOfなし
コンパイラは型消去を使用するため、ランタイムは型パラメーターを追跡しないため、実行時にBox <Integer>とBox <String>の違いはinstanceOf演算子を使用して検証できません。
Javaジェネリック-配列なし
パラメーター化された型の配列は許可されていません。
コンパイラは型消去を使用するため、型パラメーターはObjectに置き換えられ、ユーザーは配列に任意の型のオブジェクトを追加できます。 また、実行時に、コードはArrayStoreExceptionをスローできません。
Java Generics-例外なし
ジェネリッククラスは、Throwableクラスを直接または間接的に拡張することはできません。
メソッドは、型パラメーターのインスタンスをキャッチできません。
型パラメーターはthrows句で許可されます。
Java Generics-オーバーロードなし
クラスは、型消去後に同じシグネチャを持つことができる2つのオーバーロードされたメソッドを持つことはできません。