web-dev-qa-db-ja.com

Javaジェネリック:複数のジェネリックパラメータ?

次のように複数のジェネリック型を受け入れる関数を書くことができるかどうか疑問に思っていました:

public int void myfunction(Set<T> a, Set<T> b) {
    return 5;
}

Set<Integer> setA = new HashSet<Integer>();
Set<String> setB = new HashSet<String>();
int result = myfunction(setA, setB);

それは機能しますか?各パラメーターのジェネリックは、各パラメーターがジェネリックである同じタイプTを持たなければならないことを意味しますか?

ありがとう!

60
atp

はい-可能です(ただし、メソッドシグネチャを使用することはできません)。また、シグネチャを使用する場合、タイプは同じでなければなりません。

指定した署名では、Tを単一の型に関連付ける必要があります(例:StringorInteger)呼び出しサイトで。ただし、複数の型パラメーターをとるメソッドシグネチャを宣言できます

public <S, T> void func(Set<S> s, Set<T> t)

上記の署名では、署名自体でSおよびT型を宣言していることに注意してください。したがって、これらは、関数を含むクラスまたはインターフェイスに関連付けられたジェネリック型とは異なり、独立しています。

public class MyClass<S, T> {
   public        void foo(Set<S> s, Set<T> t); //same type params as on class
   public <U, V> void bar(Set<U> s, Set<V> t); //type params independent of class
}

Java.utilパッケージ内のコレクションクラスのメソッドシグネチャのいくつかをご覧ください。ジェネリックは、特にワイルドカード(? extendsおよび? super)が考慮される場合、実際にはかなり複雑な主題です。たとえば、パラメータとしてSet<Number>を受け取るメソッドがSet<Integer>も受け入れる必要がある場合がよくあります。その場合、次のような署名が表示されます。

public void baz(Set<? extends T> s);

SOについては、多くの質問が既にあります。

関数からintを返すポイントが何であるかはわかりませんが、必要に応じてできます。

109
oxbow_lakes

型またはメソッドで複数の型変数を宣言できます。たとえば、メソッドで型パラメーターを使用する場合:

<P, Q> int f(Set<P>, Set<Q>) {
  return 0;
}
9
erickson

さらに、ジェネリックを継承できます:)

@SuppressWarnings("unchecked")
public <T extends Something<E>, E extends Enum<E> & SomethingAware> T getSomething(Class<T> clazz) {
        return (T) somethingHolderMap.get(clazz);
    }
9
kingoleg

以下のいずれかの方法を使用できます。

1)基本的な単一タイプ:

//One type
public static <T> void fill(List <T> list, T val) {

    for(int i=0; i<list.size(); i++){
        list.set(i, val);
    }

}

2)複数のタイプ:

// multiple types as parameters
public static <T1, T2> String multipleTypeArgument(T1 val1, T2 val2) {

    return val1+" "+val2;

}

3)以下は、T3が関数宣言部で使用されるジェネリック型のリストにないため、コンパイラエラーが発生します。

//Raised compilation error
public static <T1, T2> T3 returnTypeGeneric(T1 val1, T2 val2) {
    return 0;
}

正しい:正常にコンパイルします

public static <T1, T2, T3> T3 returnTypeGeneric(T1 val1, T2 val2) {
    return 0;
}

サンプルクラスコード:

package generics.basics;

import Java.util.ArrayList;
import Java.util.List;

public class GenericMethods {

/*
 Declare the generic type parameter T in this method. 

 After the qualifiers public and static, you put <T> and 
 then followed it by return type, method name, and its parameters.

 Observe : type of val is 'T' and not '<T>'

 * */
//One type
public static <T> void fill(List <T> list, T val) {

    for(int i=0; i<list.size(); i++){
        list.set(i, val);
    }

}

// multiple types as parameters
public static <T1, T2> String multipleTypeArgument(T1 val1, T2 val2) {

    return val1+" "+val2;

}

/*// Q: To audience -> will this compile ? 
 * 
 * public static <T1, T2> T3 returnTypeGeneric(T1 val1, T2 val2) {

    return 0;

}*/

 public static <T1, T2, T3> T3 returnTypeGeneric(T1 val1, T2 val2) {

    return null;

}

public static void main(String[] args) {
    List<Integer> list = new ArrayList<>();
    list.add(10);
    list.add(20);
    System.out.println(list.toString());
    fill(list, 100);
    System.out.println(list.toString());

    List<String> Strlist = new ArrayList<>();
    Strlist.add("Chirag");
    Strlist.add("Nayak");
    System.out.println(Strlist.toString());
    fill(Strlist, "GOOD BOY");
    System.out.println(Strlist.toString());


    System.out.println(multipleTypeArgument("Chirag", 100));
    System.out.println(multipleTypeArgument(100,"Nayak"));

}

}

//クラス定義は終了します

サンプル出力:

[10, 20]
[100, 100]
[Chirag, Nayak]
[GOOD BOY, GOOD BOY]
Chirag 100
100 Nayak
4
chirag nayak

aとbは両方とも同じタイプのセットでなければなりません。しかし、あなたが書くことを妨げるものは何もありません

myfunction(Set<X> a, Set<Y> b)
2
Dmitry

関数定義では、セットaとbを同じ型に制約しています。また書くことができます

public <X,Y> void myFunction(Set<X> s1, Set<Y> s2){...}
2
Steve B.