2010-02-08 17 views
6

voglio passare qualsiasi valore enum al metodo nella classe di utilità e ottenere un altro valore enum dello stesso tipo enum. Qualcosa di simile a questo:Java: enumerazioni specifici e generici Enum <?> parametri

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; 
    } 
} 

L'uso del metodo getEnumAttribute():

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

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

Questo codice è completamente funzionante, Eclipse compila e lo esegue senza avvisi o errori e funziona come un fascino.

Ma quando ho pulito e compilare progetto dalla riga di comando da Maven2, non riesce con l'errore on line dove si getEnumAttribute chiama:

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

sto utilizzando Sun JDK 1.6 sia in Eclipse e 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" 

Domande:

  1. Perché questo codice è compilabile e funzionale in Eclipse e compila fallisce in Maven che utilizza per quanto ne so lo stesso compilatore javac?

  2. Cosa c'è di sbagliato nel passare specifiche enum ai parametri generici Enum<?>?

Grazie,

Martin Schayna

+0

Ho rimosso il tag maven-2 in quanto non si tratta di un problema relativo a Maven ma di un problema di compilatore eclipse/javac puro. –

+0

Eclipse ha il proprio compilatore, indipendente dal JDK. Ecco perché non richiede l'installazione del JDK (hai solo bisogno del JRE.) – finnw

risposta

9
  1. Eclipse compilatore e javac hanno alcune differenze, soprattutto quando si tratta di farmaci generici. Si ritiene che Eclipse è corretto, ma che non importa :)

  2. Prova

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

Grazie, hai assolutamente ragione, amico! Con il tuo metodo alternativo la firma è la mia fonte compilabile sia in Eclipse che in Maven. Sono un po 'confuso dalle differenze tra i due compilatori ... Comunque, grazie ancora! – mschayna

+2

Il vincolo '>' è corretto ma è possibile rendere 'T' (il tipo effettivo enum) il tipo restituito piuttosto che' Enum 'che è una superclasse astratta di' T'. – finnw

1

Non so quale versione di Eclipse che si sta utilizzando, ma penso che sia sbagliato Qui. La mia versione riporta lo stesso errore che si sta vedendo con Maven, che sembra essere un errore in buona fede.

Il problema è che ci sono due jolly ("?") nella firma del getEnumAttribute() ma non v'è alcun vincolo (né è possibile crearne uno) che li costringe a essere la stessa. Quindi, un cliente potrebbe passare in un enum di un tipo come valore di default e ottenere un enum di tipo diverso in cambio.

è possibile eliminare l'errore nel codice chiamante sostituendo entrambi i caratteri jolly con un parametro di tipo denominato:

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; 
    } 
} 

Ma non credo che sia possibile eliminare il cast incontrollato, perché Enum<E>.getClass() ritorna Class<Enum<?>> in modo che il compilatore non può dire che tipo di enum è contenuta nella matrice enumConstants.

+0

Grazie per l'analisi teorica, la tolleranza "indesiderata" a due tipi di enumerazione differenti (uno per "defaultValue" e uno per il risultato) è importante, ma nel mio caso probabilmente non causerebbe molti errori. Per completezza: sto utilizzando Eclipse 3.5.1. – mschayna

Problemi correlati