2009-11-18 27 views
44

Me preguntaba si es posible escribir una función que acepta múltiples tipos genéricos de la siguiente manera:genéricos de Java: ¿parámetros genéricos múltiples?

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

¿Funcionará? ¿El genérico en cada parámetro significa que cada parámetro debe tener el mismo tipo T que es genérico?

Gracias!

Respuesta

82

Sí - es posible (aunque no con la firma del método) y sí, con su firma los tipos deben ser los mismos.

Con la firma que has dado, T debe estar asociado a un único tipo (por ejemplo StringoInteger) en la llamada in situ. Puede, sin embargo, declarar firmas de los métodos que toman múltiples parámetros de tipo

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

Nota de la firma anterior que he declarado los tipos S y T en la propia firma. Por lo tanto, estos son diferentes e independientes de cualquier tipo genérico asociado con la clase o interfaz que contiene la función.

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 
} 

Es posible que desee echar un vistazo a algunas de las firmas de los métodos de las clases de colección en el paquete java.util. Los genéricos son realmente un tema bastante complicado, especialmente cuando se consideran comodines (? extends y ? super). Por ejemplo, a menudo ocurre que un método que podría tomar un Set<Number> como parámetro también debería aceptar un Set<Integer>. En cuyo caso se vería una firma así:

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

Hay un montón de preguntas que ya están en SO para que mire sobre el tema!

No está seguro de cuál es el punto de retornar un int de la función es, aunque se podría hacer eso si quieres!

+0

No entiendo por qué es "Sí" a ambas preguntas (específicamente, por qué "Sí" a "¿Esto funcionará?"). La función anterior (ideada, lo sé, con el int-return) no aceptará los dos tipos diferentes ya que espera el mismo tipo genérico T para ambos parámetros, ¿verdad? – ash

+1

Lo siento, quise decir "sí, es posible" y "sí, en la firma que definió, los tipos deben ser los mismos" –

+0

Lo he aclarado ahora –

2

ayb deben ser ambos conjuntos del mismo tipo. Pero nada le impide escribir

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

¡Gracias por la respuesta rápida! – ash

+0

Excepto que necesita declarar los parámetros de tipo en la firma como en mi respuesta –

+0

No debe aceptar una respuesta incorrecta. @oxbow_lakes fue el primero en hacerlo bien. –

6

Puede declarar múltiples variables de tipo en un tipo o método. Por ejemplo, utilizando parámetros de tipo en el método:

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

En su definición de la función que está limitando conjuntos A y B al mismo tipo.También puede escribir

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

Aún más, se puede heredar los genéricos :)

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

Puede seguir uno de los siguientes enfoques:

1) básico, solo tipo:

//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) Varios tipos:

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

    return val1+" "+val2; 

} 

3) A continuación se generará un error de compilación ya que 'T3 no está en la lista de tipos genéricos que se utilizan en la parte de declaración de función.

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

correcta: compila bien

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

Código de clase de ejemplo:

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

} 

} 

// definición de la clase termina

Ejemplo de salida:

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