ジェネリックメソッド
CoddyのJavaジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 55/87。
generic classes はクラス全体を異なる型で動作させますが、場合によっては単一の method だけを generic にする必要があります。generic method は、クラスレベルのジェネリクスとは独立した、独自の型パラメータを宣言します。
型パラメータは、メソッドシグネチャの戻り値の型の前に記述します。
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ジェネリックメソッドは、ジェネリッククラスを作成せずに柔軟で再利用可能な操作が必要なユーティリティクラスで特に役立ちます。
チャレンジ
簡単generic method の柔軟性を示す utility toolkit を構築しましょう。任意の型で動作する再利用可能な method を持つ class を作成し、generic class とは独立して generic method が存在できることを示します。
コードを2つのファイルに分けて整理します。
ArrayUtils.java: array を操作するための generic method を含む utility class を Create します。class には、次の3つの static generic method を定義します。getLast- 型Tの array を受け取り、last element を Returns する generic method です。array が empty の場合は、nullを return します。swap- 型Tの array と2つの integer indices を受け取り、その positions にある elements を入れ替える generic method です。この method は何も Returns しません。printWithLabel- 2つの type parametersKとVを持つ generic method です。型Kの label と型Vの value を受け取り、次の format でそれらを Print します:[label]: [value]Main.java: generic method を実際に使ってみましょう!4つの inputs、つまり2つの単語(Strings)と2つの数値(integers)を受け取ります。まず、両方の単語を containing する
String[]array を Create します。getLastを使って last element を取得し、Last word: [result]を Print します。次に、両方の数値を containing する
Integer[]array を Create します。swapを Call して indices 0 と 1 の elements を入れ替え、その後After swap: [first], [second]を Print します。最後に、
printWithLabelを2回 Call して、2つの parameters を持つ generic method を示します。- 1回は、first word を label とし、first number を value とします
- もう1回は、first number を label とし、second word を value とします
入力は次の順序で4つ受け取ります: first word、second word、first number、second number。
各 method が、return type の前に <T> または <K, V> を使って独自の type parameter(s) を宣言していることに注目してください。compiler は渡した arguments から実際の型を推論するため、method を Call するときに明示的に指定する必要はありません。
自分で試してみよう
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 クラス単一継承と多段階継承なぜ多重継承ができないのかまとめ:従業員の階層構造自分で練習してみよう: Javaオンラインコンパイラ