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 类型?

171550 次浏览

A 和 b 必须是同一类型的集合。但是没有什么可以阻止你写

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

是的——这是可能的(虽然不是通过您的方法签名) ,而且是的,通过您的签名,类型必须是相同的。

使用您所给出的签名,T必须与呼叫站点上的单个类型(例如 String 或者 Integer)相关联。但是,可以声明采用多个类型参数的方法签名

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

请注意,在上面的签名中,我已经在签名本身中声明了类型 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
}

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

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

已经有很多关于这个主题的问题等着你去看!

不确定从函数返回 int的意义是什么,尽管如果需要的话可以这样做!

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

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

在你的函数定义中,你把 a 和 b 约束成相同的类型

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

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

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

你可采用以下其中一种方法:

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