English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Java 基礎教程

Java 流程控制

Java 数组

Java 面向对象(I)

Java 面向对象(II)

Java 面向对象(III)

Java 例外処理

Java 列表(List)

Java Queue(キュー)

Java Map集合

Java Set集合

Java 输入输出(I/O)

Java Reader/Writer

Javaの他のトピック

Java ジェネリクス

このチュートリアルでは、Javaの汎用型、汎用クラスとメソッドの作成方法、その利点について例を通じて学びます。

Javaでは、泛型異なるタイプのオブジェクト(データ)と一緒に使用できるクラス、インターフェース、メソッドを作成するのに役立ちます。したがって、コードの再利用を可能にします。

意:泛型汎用型は基本データ型(int、float、charなど)には適用できません。

Javaの汎用型の使い方

Javaでどう使うかを理解するために泛型、ArrayListJava集合フレームワークのクラスを使用できます。

ArrayListクラスは汎用クラスの1つの例です。どんなデータ型のデータもArrayListで格納できます。例えば

import java.util.ArrayList;
class Main {
   public static void main(String[] args) {
      //Integerデータを格納するための配列リストを作成します
      ArrayList<Integer> list1 = new ArrayList<>();
      list1.add(4);
      list1.add(5);
      System.out.println("ArrayList of Integer: ") + list1);
      //Stringデータを格納するための配列リストを作成します
      ArrayList<String> list2 = new ArrayList<>();
      list2.add("Four");
      list2.add("Five");
      System.out.println("ArrayList of String: ") + list2);
      //Doubleデータを格納するための配列リストを作成します
      ArrayList<Double> list3 = new ArrayList<>();
      list3.add(4.5);
      list3.add(6.5);
      System.out.println("ArrayList of Double: " + list3);
   }
}

输出结果

ArrayList of Integer: [4, 5]
ArrayList of String: [Four, Five]
ArrayList of Double:  [4.5, 6.5]

上の例では、Integer、String、Doubleのデータ型の要素を格納するために同じArrayListクラスを使用しました。なぜなら、Javaの汎用、これは可能です。

ここに注意してください、

ArrayList<Integer> list1 = new ArrayList<>();

ここで、尖括号<>にはIntegerを使用しました。尖括号<>は汎用における型引数.

パラメータtypeは、汎用クラスやメソッドがどのオブジェクト(データ)の種類に適用されるかを指定します。

汎用クラスの作成

Javaで汎用の動作方法を知った今、自分自身の汎用クラスを作成する方法を見てみましょう。

例:汎用クラスの作成

class Main {
  public static void main(String[] args) {
    //整数データで汎用クラスを初期化します
    GenericsClass<Integer> intObj = new GenericsClass<>(5);
    System.out.println("汎用クラスは返します: " + intObj.getData());
    //文字データで汎用クラスを初期化します
    GenericsClass<String> stringObj = new GenericsClass<>("Java Programming");
    System.out.println("汎用クラスは返します: " + stringObj.getData());
  }
}
class GenericsClass<T> {
  //T型変数
  private T data;
  public GenericsClass(T data) {
    this.data = data;
  }
  //T型変数を返すメソッド
  public T getData() {
    return this.data;
  }
}

输出结果

汎用クラスは返します: 5
汎用クラスは返します: Java プログラミング

上の例では、GenericsClassという名前の汎用クラスを作成しました。このクラスはどんなデータの種類でも処理できます。

class GenericsClass<T> {...

ここでは、Tを表します型引数Mainクラス内部で、intObjとstringObjという名前のGenericsClassオブジェクトを作成しました。

  • 在创建intObj时,类型参数T被Integer替换。这意味着intObj使用GenericsClass处理整数数据。

  • 在创建stringObj时,类型参数T被String替换。 这意味着stringObj使用GenericsClass处理字符串数据。

创建泛型方法

与泛型类相似,我们还可以在Java中创建自己的泛型方法。

例:创建泛型方法

class Main {
  public static void main(String[] args) {
    //使用Integer数据初始化类
    DemoClass demo = new DemoClass();
    demo.<String>genericsMethod("Java Programming");
  }
}
class DemoClass {
  //泛型方法
  public <T> void genericsMethod(T data) {
    System.out.println("这是一个泛型方法。");
    System.out.println("传递给方法的数据是 " + data);
  }
}

输出结果

这是一个泛型方法。
传递给方法的数据是: Java Programming

在上面的示例中,我们创建了一个在普通类(DemoClass)内部命名的泛型方法genericsMethod。

public <T> void genericMethod(T data) {...}

在此,将类型参数<T>插入到修饰符(public)之后和返回类型(void)之前。

我们可以通过将实际类型<String>放在方法名前面的括号中来调用泛型方法。

demo.<String>genericMethod("Java Programming");

注意:在大多数情况下,我们可以在调用泛型方法时省略type参数。这是因为编译器可以使用传递给方法的值来匹配类型参数。例如,

demo.genericsMethod("Java Programming");

有界型

通常,typeパラメータ可以接受任何数据类型(原始类型除外)。但是,如果我们只想将泛型用于某些特定类型(例如接受数字类型的数据),则可以使用有界类型。

我们使用extends关键字。例如,

<T extends A>

这意味着T只能接受A的子类型的数据。

例:有界类型

class GenericsClass<T extends Number> {
  public void display() {}}
    System.out.println("This is a bounded type generics class.");
  }
}
class Main {
  public static void main(String[] args) {
    //GenericsClassオブジェクトを作成します
    GenericsClass<String> obj = new GenericsClass<>();
  }
}

上記の例では、以下を作成しました有界型の泛型クラス。ここでは、以下の式に注意してください

<T extends Number>

これはTがNumberのサブタイプデータタイプ(Integer、Doubleなど)のみを使用できることを意味します。

しかし、私たちはStringで泛型クラスのオブジェクトを作成していました。そのため、プログラムを実行すると、以下のようなエラーが発生します。

GenericsClass<String> obj = new GenericsClass<>();
                                                 ^
    reason: inference variable T has incompatible bounds
      equality constraints: String
      lower bounds: Number
  where Tは型-変数:
    class GenericsClassで宣言されたT extends Number

Javaの泛型の利点

1.コードの再利用性

泛型異なるデータタイプに適用できるコードを書くことができます。例えば、

public <T> void genericsMethod(T data) {...}

ここでは、泛型メソッドを作成しました。このメソッドは整数データ、文字列データなどに対して操作を実行するために使用できます。

2.コンパイル時の型チェック

泛型のtypeパラメータ泛型コードで使用されるデータタイプに関する情報を提供します。

そのため、コンパイル時にエラーを検出することができ、ランタイムエラーよりも簡単に修正できます。例えば、

//泛型を使用していません
NormalClass list = new NormalClass();
//NormalClassのメソッドを呼び出します
list.display("String");

上記のコードでは、普通のクラスがあります。このクラスのdisplay()メソッドに文字列データを渡して呼び出します。

ここでは、コンパイラはパラメータに渡された値が正しいかどうかを知りません。しかし、泛型クラスを使用してみるとどうなるかを見てみましょう。

//ジェネリクスの使用
GenericsClass<Integer> list = new GenericsClass<>();
//GenericsClassのメソッドを呼び出します
list2.display("String");
上記のコードでは、ジェネリクスクラスがあります。ここでは、タイプパラメータはこのクラスがIntegerデータを処理していることを示しています。
したがって、文字列データが引数として渡された場合、コンパイラはエラーを生成します。

3.ジェネリクスとコレクションを一緒に使用

コレクションフレームワークはJavaのジェネリクス概念を使用しています。例えば、

// 文字列型のArrayListを作成します
ArrayList<String> list1 = new ArrayList<>();
// 整数型のArrayListを作成します
ArrayList<Integer> list2 = new ArrayList<>();

上記の例では、異なるデータタイプを処理するために同じArrayListクラスを使用しました。

ArrayListと同様に、他のコレクション(LinkedList、Queue、Mapsなど)もJavaのジェネリクスです。