2010-02-08 5 views
6

Quiero pasar cualquier valor enum al método en la clase de utilidad y obtener otro valor enum del mismo tipo enum. Algo como esto:Java: enumeraciones genéricas y Enum <?> parámetros

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

Uso del método getEnumAttribute():

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

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

Este código es completamente funcional, Eclipse compila y se ejecuta sin advertencias o errores y funciona como un encanto.

Pero cuando limpio y compilar el proyecto de línea de comandos por Maven2, se produce el error en línea donde se getEnumAttribute llama:

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

estoy utilizando Sun JDK 1.6, ya sea en Eclipse y 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" 

Preguntas:

  1. ¿Por qué este código es compilable y funcional en Eclipse, y compilar falla en Maven que utilizando por lo que sé el mismo compilador javac?

  2. ¿Qué pasa al pasar enumeraciones específicas a los parámetros genéricos Enum<?>?

Gracias,

Martin Schayna

+0

Eliminé la etiqueta maven-2 ya que no es un problema relacionado con el experto, sino un problema del compilador de eclipse/javac puro. –

+0

Eclipse tiene su propio compilador, independiente del JDK. Es por eso que no requiere que se instale el JDK (solo necesita el JRE). – finnw

Respuesta

9
  1. Eclipse compilador javac y tiene algunas diferencias, sobre todo cuando se trata de los genéricos. Se cree que el eclipse es correcta, pero eso no importa :)

  2. Trate

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

¡Gracias, tiene toda la razón, amigo! Con su firma de método alternativo, mi fuente puede compilarse en Eclipse y Maven. Estoy un poco confundido por las diferencias entre ambos compiladores ... De todos modos, ¡gracias de nuevo! – mschayna

+2

La restricción '>' es correcta, pero puede hacer que 'T' (el tipo de enumeración real) sea el tipo de retorno en lugar de' Enum 'que es una superclase abstracta de' T'. – finnw

1

No sé qué versión de Eclipse que está utilizando, pero creo que es un error aquí. Mi versión informa el mismo error que está viendo con Maven, que parece ser un error genuino.

El problema es que tiene dos comodines ("?") en la firma de getEnumAttribute() pero no hay ninguna restricción (ni es posible crear uno) que los fuerce a ser lo mismo. Entonces un cliente podría pasar una enumeración de un tipo como valor predeterminado y obtener una enumeración de un tipo diferente a cambio.

puede eliminar el error en el código de llamada mediante la sustitución de los dos comodines con un parámetro de tipo de llamada:

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

Pero no creo que es posible eliminar el yeso no se controla, porque Enum<E>.getClass() vuelve Class<Enum<?>> por lo que la el compilador no puede decir qué tipo de enumeración está contenida en la matriz enumConstants.

+0

Gracias por el análisis teórico, especialmente la tolerancia "no deseada" a dos tipos de enum diferentes (uno para 'defaultValue' y otro para el resultado) es importante, pero en mi caso probablemente no causaría muchos errores. Para completar: estoy usando Eclipse 3.5.1. – mschayna

Cuestiones relacionadas