【Java】ジェネリクス(総称型)の使い方をサンプルコード付きで紹介
  • facebookページ
  • twitterページ
  • 2019.12.27

    【Java】ジェネリクス(総称型)の使い方をサンプルコード付きで紹介

    Javaのジェネリクス(Generics/総称型)とは?

    ジェネリクスとは、クラスやメソッドにデータ型名を「<>」記号でくくることで、String型やInteger型などの指定した型に対応する多用途型なクラスやメソッドを作る機能のことをいいます。

    以下のような、リストに入れる型の限定などがよく見られるジェネリクスです。

    通常、Listにはさまざまなものを入れられますが、 「<String>」を付けると入れられる型がStringに限定されます。

    ジェネリクスを使うメリットは?

    たとえば、上記のリストにIntegerを入れると、Stringではないのでコンパイルエラーになります。

    そのため、ジェネリクスを使うとコンパイルエラーが出るのでコードの記述ミスが見つかりやすいです。

    また、型を限定しているためコード上で何の型を扱っているかわかりやすくなっています。

    ポテパンダの一言メモ

    ジェネリクスを使うと、

    1. コードの記述ミスが見つかりやすい

    2.コード上で何の型を扱っているかわかりやすい

    といったメリットがあります。

    ジェネリクスのネーミング慣例

    特に決められてはいないのですが、ジェネリクスの変数名は基本的に1字で定義します。

    また、以下のような慣例があるので覚えておくとよいでしょう。

    ジェネリクスのネーミング慣例
    • E:Element(要素)
    • K:Key(キー)
    • T:Type(タイプ)
    • V:Value(値)
    • N:Number(数値)
    • S,U:2,3番目

    クラスでのジェネリクスの書き方

    クラスでジェネリクスを使う方法を見ていきましょう。

    上記のサンプルコードは、GenericSampleクラスに「<T>」を記述しました。

    「<T>」を記述すると、「Object型」から「T型(型変数)」にデータ型の指定が変わります。

    mainメソッド内でGenericSampleクラスをインスタンス化する場合には、データ型を「<>」記号で指定します。

    このサンプルコードでは<String>と<Integer>で指定していますね。

    getValueメソッドは、ジェネリクスを使っているため型変換(キャスト)することなく、指定した型に値を代入できています。

    そのため、データ型が一致しないエラーが出ずに複数の型で使用可能になっているのです。

    このサンプルコードを実行すると、以下の実行結果が得られます。

    実行結果↓

    ジェネリクスのワイルドカード型とは?

    ジェネリクスのワイルドカード型とは、型に「?」記号が付いているジェネリクス型です。

    ワイルドカードを利用すると、プログラムが実行されるまで型が不明なものとして表せます。

    ワイルドカード型には、「非境界ワイルドカード型」「境界ワイルドカード型」の2種類あり、それぞれ以下のように分けられます。

    • 非境界ワイルドカード型 (unbounded wildcard type)
    • 境界ワイルドカード型 (bounded wildcard type)

    ひとつずつ解説しますね。

    1.非境界ワイルドカード型

    非境界ワイルドカード型は、型が「?」のみのジェネリクス型を言います。

    実型のパラメータが決まっていない場合などに利用されます。

    具体的なコードを見てみましょう。

    checkAnyKindOfListメソッドは、引数にどんな制約が付いたListでも渡せます。

    しかし、何が渡されるかは不明です。

    checkAnyKindOfListメソッドでは、要素の取り出しなど「要素の制約がわからなくても行える操作」であれば実行可能です。

    反対に、要素の追加など「要素の制約がわかっていないと行えない操作」はできません。

    このサンプルコードを実行すると、java.lang.IndexOutOfBoundsExceptionエラーが発生します。(サイズが設定されていないためです)

    2.境界ワイルドカード型

    境界ワイルドカード型は、型にある程度の幅(上下限)をもたせて宣言できるジェネリクス型を言います。

    境界ワイルドカード型には「上限付き境界ワイルドカード」と「下限付き境界ワイルドカード」の2種類あります。

    それぞれの使い方を見ていきましょう。

    1.上限付き境界ワイルドカード(extends)

    上限付き境界ワイルドカードでは、「?」と「extends」を用います。

    サンプルコードで動きを確認しましょう。

    GenericSampleクラスの型変数Tは不明な型です。

    そこで「<? extends Number>」を記述すれば、NumberクラスまたはNumberクラスのサブクラスのみOKという境界が設定されます。

    実行結果↓

    2.下限付き境界ワイルドカード(super)

    下限付き境界ワイルドカードでは、「?」と「super」を用います。

    「<? uper String>」を記述して、StringクラスまたはStringクラスの親クラスのみOKという境界が設定されます。

    実行結果↓

    メソッドでのジェネリクスの書き方

    ジェネリクスは、クラスだけではなくメソッドでも使用可能です。

    メソッドで利用する場合は、戻り値の型名Tの前に「<T>」を記述します。

    サンプルコードで動きを確認してみましょう。

    getValueメソッドの引数と戻り値にT型を指定します。

    また、クラスと同様にgetValueメソッドをキャストの必要はありません。

    実行結果↓

    ジェネリクス複数の型パラメータ

    ジェネリクスは、カンマ区切りで複数の型パラメータの使用も可能です。

    サンプルコードを記述します。

    実行結果↓

    まとめ

    Javaのジェネリクスについて意味や使い方を紹介しました。

    ジェネリクスを利用すれば、さまざまなデータ型で似たような処理を動かしたい場合にそれぞれ処理を記述しなくて済みます。

    また、 コードの記述ミスが見つかりやすくなったり、何の型を扱っているかわかりやすいといったメリットもあります。

    ジェネリクスを活用する際は、ぜひこの記事を参考にしてください!



    優良フリーランス案件多数掲載中!
    フリーランスエンジニアの案件をお探しなら
    ポテパンフリーランス

    この記事をシェア

    • Facebookシェア
    • Twitterシェア
    • Hatenaシェア
    • Lineシェア
    pickup









    ABOUT US

    ポテパンはエンジニアと企業の最適なマッチングを追求する企業です。

    READ MORE