Je me demandais s'il était possible d'écrire une fonction qui accepte plusieurs types génériques comme suit:
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);
Ça marchera? Le générique dans chaque paramètre signifie-t-il que chaque paramètre doit avoir le même type T qui est générique?
Merci!
Oui - c'est possible (mais pas avec votre signature de méthode) et oui, avec votre signature les types doivent être les mêmes.
Avec la signature que vous avez donnée, T
doit être associé à un seul type (par exemple String
ou Integer
) sur le site d'appel. Vous pouvez cependant déclarer des signatures de méthode qui prennent plusieurs paramètres de type
public <S, T> void func(Set<S> s, Set<T> t)
Notez dans la signature ci-dessus que j'ai déclaré les types S
et T
dans la signature elle-même. Ils sont donc différents et indépendants de tout type générique associé à la classe ou à l'interface qui contient la fonction.
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
}
Vous aimerez peut-être jeter un œil à certaines des signatures de méthode des classes de collection dans le Java.util
paquet. Les génériques sont vraiment un sujet plutôt compliqué, surtout lorsque les caractères génériques (? extends
et ? super
) sont considérés. Par exemple, il arrive souvent qu'une méthode qui prenne un Set<Number>
comme paramètre doit également accepter un Set<Integer>
. Dans ce cas, vous verriez une signature comme celle-ci:
public void baz(Set<? extends T> s);
Il y a déjà plein de questions sur SO pour que vous regardiez le sujet!
Vous ne savez pas à quoi sert de renvoyer un int
de la fonction, bien que vous puissiez le faire si vous le souhaitez!
Vous pouvez déclarer plusieurs variables de type sur un type ou une méthode. Par exemple, en utilisant des paramètres de type sur la méthode:
<P, Q> int f(Set<P>, Set<Q>) {
return 0;
}
Encore plus, vous pouvez hériter de génériques :)
@SuppressWarnings("unchecked")
public <T extends Something<E>, E extends Enum<E> & SomethingAware> T getSomething(Class<T> clazz) {
return (T) somethingHolderMap.get(clazz);
}
Vous pouvez suivre l'une des approches ci-dessous:
1) De base, type unique:
//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) Plusieurs types:
// multiple types as parameters
public static <T1, T2> String multipleTypeArgument(T1 val1, T2 val2) {
return val1+" "+val2;
}
3) Ci-dessous, une erreur de compilation apparaîtra car "T3 ne figure pas dans la liste des types génériques utilisés dans la partie déclaration de fonction.
//Raised compilation error
public static <T1, T2> T3 returnTypeGeneric(T1 val1, T2 val2) {
return 0;
}
Correct: Compile bien
public static <T1, T2, T3> T3 returnTypeGeneric(T1 val1, T2 val2) {
return 0;
}
Exemple de code de classe:
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"));
}
}
// fin de la définition de classe
Exemple de sortie:
[10, 20]
[100, 100]
[Chirag, Nayak]
[GOOD BOY, GOOD BOY]
Chirag 100
100 Nayak
a et b doivent tous deux être des ensembles du même type. Mais rien ne vous empêche d'écrire
myfunction(Set<X> a, Set<Y> b)
Dans votre définition de fonction, vous contraignez les ensembles a et b au même type. Vous pouvez également écrire
public <X,Y> void myFunction(Set<X> s1, Set<Y> s2){...}