Question

J'ai mis en œuvre cette fonction:

 static <X,Y> Y castOrNull(X obj) {
  try {
   return (Y)obj;
  }
  catch(ClassCastException e) {
   return null;
  }
 }

Cela me donne l'avertissement du compilateur:

Type safety: Unchecked cast from X to Y

Ce que je ne comprends pas exactement. N'est pas le try/catch que je fais ici un chèque pour elle? Puis-je ignorer l'avertissement?

Est-ce que mon travail de fonction comme prévu ou non? Comment puis-je mettre en œuvre correctement?

J'ai aussi essayé avec un chèque de obj instanceof Y mais qui ne fonctionne pas à cause de la façon dont Java génériques de poignée.

BTW., Cette fonction semble tout à fait utile pour moi (pour faire un autre code plus propre). Je me demande si une telle fonction peut exister déjà en Java?


Un exemple où je veux l'utiliser:

    void removeEmptyRawStrings() {
        for(Iterator<Entity> e = entities.iterator(); e.hasNext();) {
            RawString s = castOrNull(e.next());
            if(s != null && s.content.isEmpty()) e.remove();
        }
    }

J'ai des cas comme ceux-ci assez souvent dans mon code. Et je pense que cela est plus lisible et plus simple que toute autre chose. Mais s'il vous plaît me donner une meilleure suggestion si vous avez sur la façon de rendre ce code encore plus simple.

Était-ce utile?

La solution

Le problème ici est que le paramètre générique Y lorsqu'il est utilisé pour la coulée dynamique est traitée comme Object. Il ne sera jamais jeter un CCE. Vous obtenez un CCE jeté dans la appelant méthode, que vous avez cassé la sécurité de type statique.

Aussi X est tout à fait inutile ici:

Presque certainement la bonne solution est de ne rien tenter de ce genre. null est mauvais. Le casting est mauvais.

Toutefois, si vous êtes déterminé à un non-sens d'écriture, vous pouvez passer l'objet Class:

public static <T> T evilMethod(Class<T> clazz, Object obj) {
    try {
        return clazz.cast(obj);
    } catch (ClassCastException exc) {
        return null;
    }
}

Autres conseils

Je suis sûr que pas tout à fait cela fonctionnera comme prévu. (En fonction de ce que vous attendez bien sûr :-) mais ce code pour résultat d'instance dans un java.lang.ClassCastException ( ideone ) :

public class Main {

    public static void main(String[] args) {
        Integer o = Main.<String, Integer>castOrNull("hello");
    }


    public static <X, Y> Y castOrNull(X obj) {
        try {
            return (Y) obj;
        } catch (ClassCastException e) {
            return null;
        }
    }
}

a Hawtin @ Tom la solution "correcte" .

Vous pouvez supprimer l'avertissement dans cette méthode si vous savez avec certitude que ce n'est pas un problème en annotant avec @SuppressWarnings("unchecked")

Merci aux génériques de Java façon où conçu ce code wont travail du tout. Generics ne sont utiles que pour la vérification du type de compilation que les classes ne pas utiliser des informations de type générique lors de l'exécution.

Votre code sera compilé à ceci:

 static Object castOrNull(Object obj) {
  try {
   return (Object)obj;//FAIL: this wont do anything
  }
  catch(ClassCastException e) {
   return null;
  }
 }

Le casting de l'objet ne manquera jamais, et le code compilé n'a pas accès aux types génériques présents au moment de la compilation. Étant donné que le casting ne se produit pas comme il devrait vous recevoir un avertissement pour une opération non contrôlée.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top