2010-02-08 4 views
6

Je souhaite transmettre une valeur enum à method dans la classe utilitaire et obtenir une autre valeur enum de même type enum. Quelque chose comme ceci:Java: énumérations spécifiques et paramètres génériques Enum <?>

public class XMLUtils { 

    public static Enum<?> getEnumAttribute(Element element, String name, 
      Enum<?> defaultValue) { 

     if (element.hasAttribute(name)) { 
      String valueName = element.getAttribute(name); 
      // search for value 
      for (Enum<?> value: defaultValue.getClass().getEnumConstants()) 
       if (value.toString().equalsIgnoreCase(valueName)) 
        return value; 
     } 
     // not found, return default value 
     return defaultValue; 
    } 
} 

Utilisation de la méthode getEnumAttribute():

// simple enum 
public enum EUploadMethod { 
    INSERT, UPDATE, DELETE 
} 

// read enum value from XML config file 
EUploadMethod method = XMLUtils.getEnumAttribute(element, "method", 
     EUploadMethod.INSERT); 

Ce code est entièrement fonctionnel, Eclipse compile et fonctionne sans avertissements ou des erreurs et cela fonctionne comme un charme.

Mais quand je nettoie et compilent projet de ligne de commande par Maven2, il échoue avec l'erreur en ligne où est getEnumAttribute appelé:

$ mvn clean compile 
.... 
[ERROR] /home/.... DataUploader.java:[173,53] inconvertible types 
found : java.lang.Enum<capture#414 of ?> 
required: .....DataUploader.EUploadMethod 

J'utilise Sun JDK 1.6 dans les deux Eclipse et Maven:

$ mvn -version 
Apache Maven 2.2.1 (r801777; 2009-08-06 21:16:01+0200) 
Java version: 1.6.0_14 
Java home: /usr/lib/jvm/java-6-sun-1.6.0.14/jre 
Default locale: en_US, platform encoding: UTF-8 
OS name: "linux" version: "2.6.27-17-generic" arch: "i386" Family: "unix" 

questions:

  1. Pourquoi ce code est compilable et fonctionnel dans Eclipse, et la compilation échoue dans Maven qui utilise aussi loin que je connais même compilateur javac?

  2. Quel est le problème de passer des énumérations spécifiques aux paramètres génériques Enum<?>?

Merci,

Martin Schayna

+0

J'ai supprimé la balise maven-2 car ce n'est pas un problème lié à maven mais un problème de compilateur eclipse/javac pur. –

+0

Eclipse possède son propre compilateur, indépendant du JDK. C'est pourquoi il ne nécessite pas l'installation du JDK (vous n'avez besoin que du JRE.) – finnw

Répondre

9
  1. compilateur Eclipse et javac ont quelques différences, notamment en ce qui concerne les médicaments génériques. On croit que l'éclipse est correcte, mais cela n'a pas d'importance :)

  2. Essayez

    public static <T extends Enum<T>> Enum<T> getEnumAttribute(Element element, String name, 
        Enum<T> defaultValue) { 
        ... 
    } 
    
+0

Merci, vous avez absolument raison, mec! Avec votre méthode alternative, la signature est ma source compilable dans Eclipse et Maven. Je suis un peu confus par les différences entre les deux compilateurs ... Bref, merci encore! – mschayna

+2

La contrainte '> 'est correcte mais vous pouvez définir le type de retour' T' (le type enum réel) plutôt que' Enum 'qui est une superclasse abstraite de' T'. – finnw

1

Je ne sais pas quelle version d'Eclipse vous utilisez, mais je pense qu'il est faux ici. Ma version signale la même erreur que vous voyez avec Maven, ce qui semble être une véritable erreur.

Le problème est que vous avez deux caractères génériques ("?") dans la signature de getEnumAttribute() mais il n'y a aucune contrainte (il n'est pas possible d'en créer un) qui les force à être identiques. Ainsi, un client peut transmettre une énumération d'un type comme valeur par défaut et obtenir une énumération d'un type différent en retour.

Vous pouvez éliminer l'erreur dans le code d'appel en remplaçant les deux jokers avec un paramètre de type nommé:

class XMLUtils { 

    @SuppressWarnings("unchecked") 
    public static <E extends Enum<E>> E getEnumAttribute(Element element, String name, 
      E defaultValue) { 

     if (element.hasAttribute(name)) { 
      String valueName = element.getAttribute(name); 
      // search for value 
      for (Enum<?> value: defaultValue.getClass().getEnumConstants()) 
       if (value.toString().equalsIgnoreCase(valueName)) 
        return (E) value; 
     } 
     // not found, return default value 
     return defaultValue; 
    } 
} 

Mais je ne pense pas qu'il est possible d'éliminer la distribution non contrôlée, car Enum<E>.getClass() retours Class<Enum<?>> de sorte que le Le compilateur ne peut pas dire quel type d'enum est contenu dans le tableau enumConstants.

+0

Merci pour l'analyse théorique, en particulier la tolérance "non désirée" à deux types enum différents (un pour 'defaultValue' et un pour le résultat) est important, mais dans mon cas, il ne causerait probablement pas beaucoup d'erreurs. Pour être complet: j'utilise Eclipse 3.5.1. – mschayna

Questions connexes