Webサイト制作コースのお申し込みはこちら Webサイト制作コースのお申し込みはこちら

Generics(ジェネリクス・総称型)とは

Genericsとは、クラスやメソッドなどの型を、パラメータとして定義できるようにした機能のことです。

「<>」の中に具体的な型名を付けて利用できます。

Genericsクラスを定義する方法

Genericsクラスを定義するには、「パラメータ化された型」と「型変数」の2つを使います。

パラメータ化された型とは、型パラメータリストをもったクラスのことです。

クラスの宣言時に、クラス名の後ろに「< 型変数 >」という形で、型パラメータを記述します。

記述方法は次の通りです。

  1. class クラス名< 型変数 > { //処理 }

パラメータ化されたクラスを使う場合は、インスタンス化する時に型の指定が必要です。

例えば、String型にする場合は、以下のように記述できます。

  1. GenericsClass gc = new GenericsClass();

Genericsメソッドを定義する方法

ジェネリクスメソッドを定義するには、Genericsクラスで定義した型変数を、引数や戻り値に利用しましょう。

先ほどの、GenericsClassで言えば次のように記述可能です。

  1. public class GenericsClass<String> {
  2. private String type;
  3. public GenericsClass(String type) {
  4. this.type = type;
  5. }
  6. public String getType() {
  7. return type;
  8. }
  9. }

Genericsの使い方

ここまで、Genericsの定義について紹介しました。

言葉で説明されても難しいと思うので、実際に使い方を見ていきましょう。

例えば、次のように記述できます。

  1. ■記述例
  2. public class Main {
  3. public static void main(String[] args) {
  4. GenericsClass<String> gcStr = new GenericsClass<String>("PotepanStyle");
  5. String str = gcStr.getT();
  6. System.out.println(str);
  7.  
  8. GenericsClass<Integer> gcInt = new GenericsClass<Integer>(123456);
  9. Integer i = gcInt.getT();
  10. System.out.println(i);
  11. }
  12. }
  13.  
  14. class GenericsClass<T>{
  15. private T t;
  16.  
  17. public GenericsClass(T t){
  18. this.t = t;
  19. }
  20.  
  21. public T getT(){
  22. return t;
  23. }
  24. }

GenericsClassクラスのクラス名の後に「<T>」と記述しました。

<T>を指定すると、データ型の指定が「Object型」から「T型(型変数)」へ変更できます。

そして、Mainクラスのmainメソッドで、GenericsClassクラスをインスタンス化するときに、データ型をString型とInteger型で指定しています。

Genericsを使うので、GenericsClassクラスのオブジェクトを呼び出す「getTメソッド」をキャストすることなく、指定した方で値の代入が可能です。

上記のプログラムを実行すると、次の結果を取得できます。

  1. ■実行結果
  2. mbp:Desktop potepan$ java Main
  3. PotepanStyle
  4. 123456

それぞれ、String型とInteger型で使えているのがわかります。

Genericsの「T」とは?

前章のプログラムで「<T>」という表現がありました。

この T とは、Generics型の変数名に使われるネーミングです。

T は Type の略称です。

T以外にも、次のようなネーミングがよく使われます。

Generics型の変数名に使われるネーミング
  • E:Element
  • K:Key
  • V:Value
  • T:Type
  • N:Number
  • S,U:2、3番目

慣習的に使われるものなので、覚えておくと良いでしょう。

実際の現場やプロジェクトでも、共通のネーミングを使うことで混乱を避けられるはずです!

Genericsのワイルドカード型について

ここでは、Genericsのワイルドカード型について見ていきましょう。

例として、以下のプログラムを用意しました。

  1. ■記述例
  2. import java.util.ArrayList;
  3. import java.util.Collection;
  4. import java.util.List;
  5.  
  6. public class Main {
  7. public static void main(String[] args) {
  8. List list = new ArrayList<>();
  9. list.add("Potepan");
  10. list.add("Style");
  11. printStr(list);
  12. }
  13.  
  14. public static void printStr(Collection<String> col) {
  15. for (String s : col) {
  16. System.out.print(s);
  17. }
  18. System.out.println();
  19. }
  20. }
  21. ■実行結果
  22. mbp:Desktop potepan$ java Main
  23. PotepanStyle

printStrメソッドで、Collection型のコレクションを受け取った上で、その要素を出力しているプログラムです。

Collectionは、Genericsを使って型の指定を行っています。

しかし、使う際にはGenericsの型であるTごとに使う必要があり、少し不便です。

仮に、Integer型で扱いたい場合は、それぞれ別個で扱わないといけません。

そこで、便利なのがワイルドカード型を使った方法です。

ワイルドカードを「?」で表現し、「Collection<?>」します。

そうすることで、任意の型のコレクションとして扱えるのです。

先ほどのプログラムを書き換えて実行してみます。

  1. ■記述例
  2. import java.util.ArrayList;
  3. import java.util.Collection;
  4. import java.util.List;
  5.  
  6. public class Main {
  7. public static void main(String[] args) {
  8. List listStr = new ArrayList<>();
  9. listStr.add("Potepan");
  10. listStr.add("Style");
  11. printStr(listStr);
  12.  
  13. List listInt = new ArrayList<>();
  14. listInt.add(12345);
  15. listInt.add(67890);
  16. printStr(listInt);
  17. }
  18.  
  19. public static void printStr(Collection<?> col) {
  20. for (Object o : col) {
  21. System.out.print(o);
  22. }
  23. System.out.println();
  24. }
  25. }
  26. ■実行結果
  27. mbp:Desktop potepan$ java Main
  28. PotepanStyle
  29. 1234567890

このように、String型でもInteger型でも使えるようになります!

Genericsでextendsを使う方法

Genericsでは、型パラメータを宣言するときに、「extends」が使えます。

extendsを使うと、データ型として指定できるものを制限可能です。

例えば、<T extends P>と宣言した場合、データ型として指定できる型は、クラスPを継承したデータ型となります。

extendsで指定できるクラスは1つだけです。

複数指定する際は「&」でつなげることでインタフェースを指定できます。

  1. class クラス名<型パラメーター extends クラスorインタフェース & インタフェース & ・・・> { クラス本体 }

では、実際にプログラムを実行してみましょう!

次のように記述できます。

  1. ■記述例
  2. public class Main {
  3. public static void main(String[] args) {
  4. GenericsClass<Integer> gc = new GenericsClass<Integer>();
  5. gc.setValue(123456);
  6. Integer i = gc.getValue();
  7. System.out.println(i);
  8. }
  9. }
  10. class GenericsClass<T extends Number> {
  11. private T t;
  12.  
  13. public void setValue (T t) {
  14. this.t = t;
  15. }
  16.  
  17. public T getValue() {
  18. return t;
  19. }
  20. }

上記の例では、TはNumber型を継承したデータ型だけを扱えるようになります。

そのため、Integer型は使えますが、String型は使えません。

String型を指定した場合、コンパイルエラーになります。

上記のプログラムを実行した結果は次の通りです。

  1. ■実行結果
  2. mbp:Desktop potepan$ java Main
  3. 123456

Integer型として出力されているのがわかります。

このように、扱えるデータ型を制限したい場合に、extendsは便利な機能です!

Genericsでsuperを使う方法

Genericsでsuperを使うことで、extendsとは逆の動作を実現することも可能です。

例えば、次のように記述できます。

  1. ■記述例
  2. public class Main {
  3. public static void main(String[] args) {
  4. GenericsClass<Number> gc1 = new GenericsClass<Number>(123456);
  5. GenericsClass<? super Integer> gc2;
  6.  
  7. gc2 = gc1;
  8.  
  9. Object obj = gc2.getValue();
  10. System.out.println(obj);
  11. }
  12. }
  13.  
  14. class GenericsClass<T> {
  15. private T t;
  16.  
  17. public GenericsClass(T t) {
  18. this.t = t;
  19. }
  20.  
  21. public T getValue() {
  22. return t;
  23. }
  24. }

gs1というNumber型で指定したインスタンスと、<? super Integer>で指定したgs2インスタンスを用意します。

そして、gs1をgs2に代入する際に、Object型の変数「obj」を使いました。

上記のプログラムを実行すると、次のように表示されます。

  1. ■実行結果
  2. mbp:Desktop potepan$ java Main
  3. 123456

Genericsでメソッドで使う方法

Genericsメソッドを定義する方法」を紹介したように、メソッドでもGenericsは使用可能です。

使う際は、次のように記述しましょう。

  1. ■記述例
  2. public class Main {
  3. public static void main(String[] args) {
  4. String str = getT("PotepanStyle");
  5. System.out.println(str);
  6.  
  7. Integer i = getT(123456);
  8. System.out.println(i);
  9. }
  10.  
  11. private static <T> T getT(T t){
  12. return t;
  13. }
  14. }
  15. ■実行結果
  16. mbp:Desktop potepan$ java Main
  17. PotepanStyle
  18. 123456

Genericsクラスと同じように、String型とInteger型で取得できているのがわかります!

まとめ

JavaのGenericsについて、クラス・メソッドの定義方法や使い方を解説しました。

Genericsは、Integer型やString型といったさまざまなデータ型で、同じ処理を実行したい場合に便利です。

プログラム実行時のエラーが発生する危険がなくなるのも、メリットと言えます。

ぜひこの記事を参考に、Genericsの使い方を覚えてください!

エンジニアになりたい人に選ばれるプログラミングスクール「ポテパンキャンプ 」

ポテパンキャンプは卒業生の多くがWebエンジニアとして活躍している実践型プログラミングスクールです。 1000名以上が受講しており、その多くが上場企業、ベンチャー企業のWebエンジニアとして活躍しています。

基礎的な学習だけで満足せず、実際にプログラミングを覚えて実践で使えるレベルまで学習したいという方に人気です。 プログラミングを学習し実践で使うには様々な要素が必要です。

それがマルっと詰まっているポテパンキャンプでプログラミングを学習してみませんか?

卒業生の多くがWebエンジニアとして活躍

卒業生の多くがWeb企業で活躍しております。
実践的なカリキュラムをこなしているからこそ現場でも戦力となっております。
活躍する卒業生のインタビューもございますので是非御覧ください。

経験豊富なエンジニア陣が直接指導

実践的なカリキュラムと経験豊富なエンジニアが直接指導にあたります。
有名企業のエンジニアも多数在籍し品質高いWebアプリケーションを作れるようサポートします。

満足度高くコスパの高いプログラミングスクール「ポテパンキャンプ」

運営する株式会社ポテパンは10,000人以上のエンジニアのキャリアサポートを行ってきております。
そのノウハウを活かして実践的なカリキュラムを随時アップデートしております。

代表の宮崎もプログラミングを覚えサイトを作りポテパンを創業しました。
本気でプログラミングを身につけたいという方にコスパ良く受講していただきたいと思っておりますので、気になる方はぜひスクール詳細をのぞいてくださいませ。