ジェネリックメソッド
CoddyのJavaジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 55/87。
ジェネリッククラスはクラス全体を異なる型で動作させますが、時には単一のメソッドだけをジェネリックにする必要がある場合があります。ジェネリックメソッドは、クラスレベルのジェネリクスとは独立して、独自の型パラメータを宣言します。
型パラメータは、メソッドシグネチャの戻り値の型の前に記述します:
public class Utility {
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.println(element);
}
}
}
String[] names = {"Alice", "Bob"};
Integer[] numbers = {1, 2, 3};
Utility.printArray(names); // String[] で動作します
Utility.printArray(numbers); // Integer[] で動作します修飾子と戻り値の型の間に <T> が置かれていることに注目してください。これにより、T がこの特定のメソッドの型パラメータとして宣言されます。コンパイラは、渡された引数から実際の型を推論します。
ジェネリックメソッドは、ジェネリック型を返すこともできます。
public static <T> T getFirst(T[] array) {
if (array.length > 0) {
return array[0];
}
return null;
}
String first = getFirst(new String[]{"a", "b"}); // "a" を返します必要に応じて、複数の型パラメータを使用できます。
public static <K, V> void printPair(K key, V value) {
System.out.println(key + ": " + value);
}
printPair("Age", 25); // String と Integer
printPair(1, "First"); // Integer と Stringジェネリックメソッドは、ジェネリッククラスを作成することなく、柔軟で再利用可能な操作が必要なユーティリティクラスにおいて特に有用です。
チャレンジ
簡単ジェネリックメソッドの柔軟性を示すユーティリティツールキットを作成しましょう。任意の型で動作する再利用可能なメソッドを持つクラスを作成し、ジェネリックメソッドがジェネリッククラスから独立して存在できることを実証します。
コードは2つのファイルに分けて構成します:
ArrayUtils.java: 配列を操作するためのジェネリックメソッドを含むユーティリティクラスを作成します。クラスには3つの静的ジェネリックメソッドを含める必要があります:getLast- 型Tの配列を受け取り、最後の要素を返すジェネリックメソッドです。配列が空の場合はnullを返します。swap- 型Tの配列と2つの整数のインデックスを受け取り、それらの位置にある要素を入れ替えるジェネリックメソッドです。このメソッドは何も返しません。printWithLabel- 2つの型パラメータKとVを持つジェネリックメソッドです。型Kのラベルと型Vの値を受け取り、次の形式で出力します:[label]: [value]Main.java: 作成したジェネリックメソッドを実際に動かしてみましょう!4つの入力(2つの単語(String)と2つの数字(Integer))を受け取ります。まず、両方の単語を含む
String[]配列を作成します。getLastを使用して最後の要素を取得し、次のように出力します:Last word: [result]次に、両方の数字を含む
Integer[]配列を作成します。swapを呼び出してインデックス0と1の要素を入れ替え、次のように出力します:After swap: [first], [second]最後に、
printWithLabelを2回呼び出して、2つのパラメータを持つジェネリックメソッドを実演します:- 1回目は、最初の単語をラベル、最初の数字を値として呼び出します
- 2回目は、最初の数字をラベル、2番目の単語を値として呼び出します
入力は、最初の単語、2番目の単語、最初の数字、2番目の数字の順に4つ受け取ります。
各メソッドが戻り値の型の前に <T> または <K, V> を使用して独自の型パラメータを宣言していることに注目してください。コンパイラは渡された引数から実際の型を推論するため、メソッドを呼び出すときに明示的に型を指定する必要はありません。
チートシート
ジェネリックメソッドは、クラスレベルのジェネリクスとは独立して、独自の型パラメータを宣言します。型パラメータは、メソッドシグネチャの戻り値の型の前に記述されます。
基本的なジェネリックメソッドの構文:
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.println(element);
}
}<T> は修飾子と戻り値の型の間に配置されます。コンパイラは、渡された引数から実際の型を推論します。
ジェネリックメソッドはジェネリック型を返すことができます:
public static <T> T getFirst(T[] array) {
if (array.length > 0) {
return array[0];
}
return null;
}複数の型パラメータを使用することもできます:
public static <K, V> void printPair(K key, V value) {
System.out.println(key + ": " + value);
}
printPair("Age", 25); // String と Integer
printPair(1, "First"); // Integer と Stringジェネリックメソッドは、ジェネリッククラスを作成することなく、柔軟で再利用可能な操作を行うためのユーティリティクラスで役立ちます。
自分で試してみよう
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 入力を読み込む
String firstWord = scanner.nextLine();
String secondWord = scanner.nextLine();
int firstNumber = scanner.nextInt();
int secondNumber = scanner.nextInt();
// TODO: 両方の単語を含む String[] 配列を作成する
// TODO: ArrayUtils.getLast を使用して最後の要素を取得する
// 出力: "Last word: [result]"
// TODO: 両方の数値を含む Integer[] 配列を作成する
// TODO: ArrayUtils.swap を呼び出してインデックス 0 と 1 の要素を入れ替える
// 出力: "After swap: [first], [second]"
// TODO: firstWord をラベル、firstNumber を値として ArrayUtils.printWithLabel を呼び出す
// TODO: firstNumber をラベル、secondWord を値として ArrayUtils.printWithLabel を呼び出す
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
4継承
継承の基本 (extends)super キーワードメソッドのオーバーライド (@Override)コンストラクタチェーンObject クラス単一継承と多段階継承なぜ多重継承ができないのかまとめ:従業員の階層構造