Java泛型:多个泛型参数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1759549/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 22:22:31  来源:igfitidea点击:

Java generics: multiple generic parameters?

javagenericsparameters

提问by atp

I was wondering if it's possible to write a function that accepts multiple generic types as follows:

我想知道是否可以编写一个接受多种泛型类型的函数,如下所示:

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);

Will that work? Does the generic in each parameter mean that each parameter must have the same type T that's generic?

那行得通吗?每个参数中的泛型是否意味着每个参数必须具有相同的泛型类型 T?

采纳答案by oxbow_lakes

Yes - it's possible (though not with your method signature) and yes, with your signature the types must be the same.

是的 - 这是可能的(虽然不是你的方法签名),是的,你的签名类型必须相同。

With the signature you have given, Tmust be associated to a single type (e.g. StringorInteger) at the call-site. You can, however, declare method signatures which take multiple type parameters

使用您提供的签名,T必须与调用站点的单个类型(例如StringInteger)相关联。但是,您可以声明采用多个类型参数的方法签名

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

Note in the above signature that I have declared the types Sand Tin the signature itself. These are therefore different to and independent of any generic types associated with the class or interface which contains the function.

请注意,在上面的签名中,我已经声明了类型ST签名本身。因此,它们不同于并独立于与包含该函数的类或接口相关联的任何泛型类型。

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
}

You might like to take a look at some of the method signatures of the collection classes in the java.utilpackage. Generics is really rather a complicated subject, especially when wildcards (? extendsand ? super) are considered. For example, it's often the case that a method which might take a Set<Number>as a parameter should also accept a Set<Integer>. In which case you'd see a signature like this:

您可能想查看java.util包中集合类的一些方法签名。泛型确实是一个相当复杂的主题,尤其是在考虑通配符(? extends? super)时。例如,通常情况下,可能将 aSet<Number>作为参数的方法也应该接受 a Set<Integer>。在这种情况下,您会看到这样的签名:

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

There are plenty of questions already on SO for you to look at on the subject!

已经有很多关于 SO 的问题供您查看!

Not sure what the point of returning an intfrom the function is, although you could do that if you want!

不确定int从函数返回 an的意义是什么,尽管您可以根据需要这样做!

回答by Dmitry

a and b must both be sets of the same type. But nothing prevents you from writing

a 和 b 必须都是相同类型的集合。但没有什么能阻止你写作

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

回答by erickson

You can declare multiple type variables on a type or method. For example, using type parameters on the method:

您可以在一个类型或方法上声明多个类型变量。例如,在方法上使用类型参数:

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

回答by Steve B.

In your function definition you're constraining sets a and b to the same type. You can also write

在您的函数定义中,您将 a 和 b 设置为相同的类型。你也可以写

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

回答by kingoleg

Even more, you can inherit generics :)

更重要的是,您可以继承泛型:)

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

回答by chirag nayak

You can follow one of the below approaches:

您可以遵循以下方法之一:

1) Basic, single type :

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 :

2)多种类型:

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

    return val1+" "+val2;

}

3) Below will raise compiler error as 'T3 is not in the listing of generic types that are used in function declaration part.

3) 下面将引发编译器错误,因为 'T3 不在函数声明部分使用的泛型类型列表中。

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

Correct : Compiles fine

正确:编译正常

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

Sample Class Code :

示例类代码:

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"));

}

}

// class definition ends

// 类定义结束

Sample Output:

示例输出:

[10, 20]
[100, 100]
[Chirag, Nayak]
[GOOD BOY, GOOD BOY]
Chirag 100
100 Nayak