29 votes

Méthodes génériques statiques

Pouvez-vous expliquer pourquoi les éléments suivants fonctionnent?

 public class GenericsTest<T> {

    public void doSomething(T v1, T v2) {

    }

    public static <T> void doSomethingStatic(T v1, T v2) {

    }

    public static <T> void doSomethingStaticList(List<T> v1, List<T> v2)
    {

    }

    public static void main(String[] args) {
        GenericsTest<String> gt = new GenericsTest<>();

        // OK
        gt.doSomething("abc", "abc");

        // Not OK
        gt.doSomething(1, "abc");

        // OK
        doSomethingStatic(1, 2);

        // Still OK
        doSomethingStatic(1, "abc");

        // So why is this not OK?
        List<String> list1=new LinkedList<>();
        List<Integer> list2=new LinkedList<>();
        doSomethingStaticList(list1,list2);
    }
}
 

T v1, T v2 devrait être du même type dans doSomethingStatic , mais je peux toujours passer différents types (entier et chaîne).

Si doSomethingStatic() prend une super classe commune par défaut, pourquoi doSomethingStaticList() fonctionne pas avec différents types?

23voto

Jaroslaw Pawlak Points 2512

En non-statique dans le cas où vous définissez T comme String lorsque vous créer une instance de l' GenericsTest. Donc en passant un int donnera erreur de compilation. Si vous n'avez gt.doSomething(1, 2) il ne pourrait pas ainsi.

Dans le cas statique, vous ne définissez pas d' T manuellement, elle est dérivée à partir de paramètres. Ce sera la première commune de la super-classe de deux classes - ce qui dans ce cas est - Object. Vous pouvez utiliser délimitée génériques, par exemple, <T extends Number> ou <T extends CharSequence>.

Notez que vous disposez de deux différents Ts ici:

  • GenericsTest<T>
  • public static <T> void doSomethingStatic(T v1, T v2)

La déclaration de paramètre générique est chaque fois que vous écrivez <T>. Vous pouvez utiliser des lettres différentes dans ce cas, pour éviter toute confusion.

14voto

Philip Voronov Points 2998

Cela fonctionne parce qu' T dans votre méthode statique est son propre paramètre de type, pas le T paramètre pour exemple celui utilisé dans votre méthode de membre. Renommer pour clarifier:

public static class GenericsTest<T> {

    public void doSomething(T v1, T v2) {

    }

    public static <V> void doSomethingStatic(V v1, V v2) {

    }
//...

Ainsi, en cas d' doSomething(...) votre exemple de paramètre de type de valeur est String donc c'est une erreur. Dans le cas de la statique doSomethingStatic(...) de la valeur de paramètre de type est différent:

GenericsTest.doSomethingStatic(1, "abc"); //ok
GenericsTest.<Object>doSomethingStatic(1, "abc"); //ok
GenericsTest.<String>doSomethingStatic(1, "abc"); //not ok
new GenericsTest<String>().doSomething(1, "abc"); //not ok

2voto

Aris2World Points 874

D'abord un peu de théorie:

  • Méthodes génériques sont des méthodes qui introduisent leurs propres paramètres de type Java Tutoriels - Méthodes Génériques
  • L'inférence de Type est un compilateur Java la capacité de regarder à chaque invocation de méthode et de déclaration correspondante pour déterminer le type de l'argument (ou arguments) qui font de l'invocation applicable Tutoriels Java - l'inférence de Type

Donc ce qu'il se passe:

  • quand une expression générique qui précèdent la valeur de retour alors un nouveau générique de type de variable est "déclarée". Donc le T de la déclaration de la classe est différente (pour le compilateur) à partir de la T de la déclaration de la méthode.
  • le compilateur appliquer l'inférence de type et dans votre exemple, il est établi que le type approprié d'appliquer la méthode d'invocation est l'Objet

Vous pouvez également essayer cet exemple sans méthode statique:

public class GenericsTest<T> {

  public void doSomething(T v1, T v2) {

  }

  public <T> void doSomething2(T v1, T v2) {

  }

  public static void main(String[] args) {
    GenericsTest<String> gt = new GenericsTest<>();

    // ok
    gt.doSomething("abc", "abc");

    // Not ok
    gt.doSomething(1, "abc");

    // ok
    gt.doSomething2(1, 2);

    // Still ok
    gt.doSomething2(1, "abc");

  }

}

0voto

Aman Goyal Points 119

Dans le cas statique, vous ne définissez pas T manuellement, il est dérivé des paramètres. Dans le cas doSomethingStaticList (list1, list2) où list1 est une liste générique String tandis que list2 est une liste générique Integer. L'algorithme d'inférence du compilateur ne pourra pas reconnaître car List et List n'appartiennent à aucun type commun.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X