158 votes

Est-il possible de résoudre le "générique de la matrice de T est créé pour une varargs paramètre" avertissement du compilateur?

C'est une version simplifiée du code en question, une classe générique utilise une autre classe avec des paramètres de type générique et doit passer l'un des types génériques à une méthode avec varargs paramètres:

class Assembler<X, Y> {
    void assemble(X container, Y... args) { ... }
}

class Component<T> {
    void useAssembler(T something) {

        Assembler<String, T> assembler = new Assembler<String, T>();

        //generates warning:
        // Type safety : A generic array of T is
        // created for a varargs parameter
        assembler.assemble("hello", something);
    }

}

Est-il une bonne façon de transmettre le paramètre générique d'un varargs méthode sans rencontrer de cet avertissement?

Bien sûr, quelque chose comme

assembler.assemble("hello", new T[] { something });

ne fonctionne pas puisque vous ne pouvez pas créer générique tableaux.

88voto

Kevin Points 19613

Autre que l'ajout d' @SuppressWarnings("unchecked"), je ne le pense pas.

Ce rapport de bug a plus d'informations, mais elle se résume au compilateur de ne pas aimer les tableaux de types génériques.

58voto

Cowan Points 17235

Tom Hawtin a souligné dans un commentaire, mais pour être plus explicite: "oui, vous pouvez résoudre ce problème à la déclaration du site (plutôt que de l' (éventuellement plusieurs) sites d'appel): interrupteur à JDK7.

Comme vous pouvez le voir dans Joseph Darcy blog, le Projet de Pièce de monnaie de l'exercice de sélectionner quelques petites différentiels de la langue des améliorations pour Java 7 acceptée Bob Lee proposition pour permettre à quelque chose comme @SuppressWarnings("varargs") à la méthode de côté pour faire de cette alerte s'en aller dans les situations où elle était connue pour être sûr.

Cela a été mis en œuvre dans OpenJDK avec ce commit.

Cela peut ou peut ne pas être utile à votre projet (beaucoup de gens ne serait pas heureux de passer à une version pré-version instable de la JVM!) mais c'est peut-être - ou peut-être quelqu'un qui trouve cette question un peu plus tard (après JDK7) le trouverez utile.

16voto

npgall Points 975

Si vous êtes après un fluide-type d'interface, vous pouvez essayer le générateur de modèle. Pas aussi concis que varargs, mais il est de type sécurisé.

Statique générique de type de méthode peut éliminer une partie du standard lors de l'utilisation du générateur de rapports, tout en conservant le type de sécurité.

Le constructeur

public class ArgBuilder<T> implements Iterable<T> {

    private final List<T> args = new ArrayList<T>();

    public ArgBuilder<T> and(T arg) {
        args.add(arg);
        return this;
    }

    @Override
    public Iterator<T> iterator() {
        return args.iterator();
    }

    public static <T> ArgBuilder<T> with(T firstArgument) {
        return new ArgBuilder<T>().and(firstArgument);
    }
}

En l'utilisant

import static com.example.ArgBuilder.*;

public class VarargsTest {

    public static void main(String[] args) {
        doSomething(new ArgBuilder<String>().and("foo").and("bar").and("baz"));
        // or
        doSomething(with("foo").and("bar").and("baz"));
    }

    static void doSomething(Iterable<String> args) {
        for (String arg : args) {
            System.out.println(arg);
        }
    }
}

5voto

Explicitement casting paramètres de l'Objet dans vararg invocation de méthode va faire le bonheur du compilateur sans recourir à @SuppressWarnings.

public static <T> List<T> list( final T... items )
{
    return Arrays.asList( items );
}

// This will produce a warning.
list( "1", 2, new BigDecimal( "3.5" ) )

// This will not produce a warning.
list( (Object) "1", (Object) 2, (Object) new BigDecimal( "3.5" ) )

// This will not produce a warning either. Casting just the first parameter to 
// Object appears to be sufficient.
list( (Object) "1", 2, new BigDecimal( "3.5" ) )

Je crois que le problème ici est que le compilateur a besoin de comprendre à quel type de béton de tableau pour créer. Si la méthode n'est pas générique, le compilateur peut utiliser les informations de type de la méthode. Si la méthode est générique, il essaie de comprendre le type de tableau basé sur les paramètres utilisés lors de l'invocation. Si les types de paramètres sont très homogène, que la tâche est facile. S'ils varient, le compilateur essaie d'être trop intelligent, à mon avis, et crée une union de type générique de la matrice. Ensuite, il se sent obligé de vous avertir à ce sujet. Une solution plus simple aurait été de créer un Objet[] lorsque le type ne peut pas être mieux rétréci vers le bas. La solution ci-dessus des forces de que.

Pour mieux comprendre ce processus, jouer avec les invocations à la liste ci-dessus méthode par rapport à la suite de la liste 2 de la méthode.

public static List<Object> list2( final Object... items )
{
    return Arrays.asList( items );
}

0voto

KLE Points 11711

Lors de travaux avec des tableaux de type générique, je suis obligé de passer une référence pour le type générique. Avec ça, je peux vraiment faire le générique de code, à l'aide de java.lang.de réfléchir.Tableau.

http://java.sun.com/javase/6/docs/api/java/lang/reflect/Array.html

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