2009-11-18 139 views
44

我想知道是否有可能编写接受多个泛型类型如下功能: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?

谢谢!

回答

82

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

有了你给签名,T必须关联到一个单一的类型(例如StringInteger)在调用点。你可以,但是,声明其采取多种类型的参数

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

有很多的问题,已经在SO你看看关于这个问题!

不知道从函数返回一个int的一点是什么,但你能做到这一点,如果你想!

+0

我不明白为什么对这两个问题都是“是”(具体而言,为什么“是”,“这会工作吗?”)。上面的函数(我知道,用int返回)不会接受这两种不同的类型,因为它对于两个参数都需要相同的泛型类型T,对吧? – ash 2009-11-18 22:29:47

+1

对不起 - 我的意思是“是有可能的”和“是的,在您定义的签名中,类型需要相同” – 2009-11-18 22:32:46

+0

我已经澄清了它 – 2009-11-18 22:34:08

2

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

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

感谢您的快速回复! – ash 2009-11-18 22:21:59

+0

除了您需要在签名中声明类型参数,如我的答案 – 2009-11-18 22:23:09

+0

您不应该接受错误的答案。 @oxbow_lakes是第一个正确的选择。 – 2009-11-18 22:30:09

6

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

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

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

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

甚至,你可以继承泛型:)

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

您可以按照下面的方法一个:

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