7
votes

Java Type de retour dynamique?

J'ai un conteneur (liste) de certains éléments de type T et souhaitez le filtrer. Donc, il ne contient que des éléments d'un sous-type spécifique U. Serait-il possible de définir un type de retour «dynamique»?

Exemple: P>

Note: SomeContainer.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.


2 commentaires

L'avertissement est parce que vous utilisez classe au lieu de la classe . Et je ne suis pas sûr que vous puissiez utiliser des types dynamiques dans des paramètres de modèle.


Il ne contient donc que des éléments d'un sous-type spécifique u Pourquoi ne pas déclarer avec ce sous-type spécifique u?


3 Réponses :


9
votes

java.lang.class Code> est un type générique paramétré sur lui-même. Vous pouvez donc utiliser son paramètre de type, comme celui-ci:

public <U extends T> SomeContainer<U> subset(Class<U> c){
    SomeContainer<U> output = new SomeContainer<U>();
    for (T val : this) {
        if (c.isInstance(val)) {
            output.add(c.cast(val));
        }
    }
    return output;
}


2 commentaires

Ou mieux, Sortie.Ajouter (C.Cast (Val)) Pour éviter l'avertissement non coché.


@ Bianroberts absolument! Merci pour une bonne suggestion!



1
votes

Les génériques sont un artefact de la compilation uniquement, votre schéma ne peut donc pas fonctionner. Le compilateur ne peut pas prédire quelle classe vous souhaiterez à chaque exécution de la ligne de code qui appelle à cette fonction. Vous ne pouvez pas faire de cette solution de type-coffre-fort sauf si vous avez un cas très contraint et assez inutile, où vous n'utilisez jamais des littéraux de classe pour appeler votre fonction. Cela vaincre presque certainement son but d'être, comme vous l'avez dit, dynamique.


0 commentaires

0
votes

Premier point: vous pouvez supprimer l'avertissement de fonctionnement non coché en remplaçant l'argument Classe C code> avec Classe C code>. Cela peut être tout ce dont vous avez besoin ... auquel cas ... =: - -)

second point: Habituellement, le code appelant Somecontainer.Subset () Sachez à la compilation Tapez le type U (dans le contexte logique). Cela doit être le cas pour vous, sinon vous ne seriez pas en mesure de transmettre l'argument code> Classe C code> dans. P>

Essayez: p>

public SomeContainer<? extends X> subset(Class<? extends X> c){
    SomeContainer<? extends X> output = null;

    // would like to use:  "if (c instance of Class<Z>)"
    // but instanceof does not allow generic type arguments
    if (c.getName().equals(Z.class.getName())) {
        SomeContainer<Z> outputZ = new SomeContainer<Z>();
        // put filtered elements into outputZ
        output = outputZ;
    } else if (c.getName().equals(Y.class.getName())) {
        SomeContainer<Y> outputY = new SomeContainer<Y>();
        // put filtered elements into outputZ
        output = outputY;
    } else if (c.getName().equals(X.class.getName())) {
        SomeContainer<X> outputX = new SomeContainer<X>();
        // put filtered elements into outputZ
        output = outputX;
    }
    return output;    
}


0 commentaires