2011-12-22 8 views
8

¿Alguien puede explicar por qué los parámetros de anotación String y Class se esperan de forma diferente? ¿Por qué el compilador requiere literales para Clases, si acepta constantes para Cadenas también?El atributo de anotación debe ser un literal de clase? ¿Por qué? Las constantes también deberían estar bien

Ejemplo de trabajo con @RequestMapping de primavera:

public class MyController { 
    public static final String REQUEST_MAPPING = "/index.html"; 
    @RequestMapping(MyController.REQUEST_MAPPING) // ALL OK! 
    ... 
} 

WTF ejemplo, con @test de TestNG:

public class MyControllerTest { 
    public static final Class TEST_EXCEPTION = RuntimeException.class; 
    @Test(expectedExceptions = MyControllerTest.TEST_EXCEPTION) // compilation error, WTF: 
    // The value for annotation attribute Test.expectedExceptions must be a class literal 
    ... 
} 

Lo que funciona, por supuesto, es @test (expectedExceptions = RuntimeException.class). ¿Pero por qué? La única diferencia en el parámetro de anotación que veo es su tipo: String vs Class. ¿Por qué en la tierra el compilador de Java también aceptaría String constant pero solo aceptaría literales de clase?

Respuesta

5

La especificación del lenguaje Java no le permite utilizar las constantes de tiempo de compilación con parámetros de tipo Class. Solo puedes usar literales de clase.

El JLS tiene la siguiente que decir sobre valores de los parámetros adecuados para las anotaciones:

un tipo de elemento T es acorde con un valor de elemento de V si y sólo si una de las siguientes condiciones es verdadera :

  • T es un e [] y, o bien tipo de matriz :
    • V es un ElementValueArrayInitializer y cada ElementValueInitializer (análogo a un inicializador variable en un inicializador array) en V es acorde con E. O
    • V es un ElementValue que es proporcional a T .
  • El tipo de V es la asignación compatible (§5.2) con T y, además:
    • Si T es un tipo primitivo o String, V es una expresión constante (§15.28) .
    • V no es nulo.
    • si T es de clase, o una invocación de la clase, y V es una clase literal (§15.8.2).
    • Si T es un tipo de enumeración, y V es una constante de enumeración.

Es un error en tiempo de compilación si el tipo de elemento no se corresponde con la ElementValue.

No puedo decir por qué esta restricción está en el JLS, sin embargo.

+0

Wow, no entiendo el objetivo de esto. ¿Por qué esta restricción en Class? Gracias por señalar esto. – sibidiba

0

mirar esto:

public static final Class TEST_EXCEPTION = RuntimeException.class; 

La clase debe ser un Throwable que el compilador es capaz de comprobar. Por lo tanto, intente esto:

public static final Class<? extends Throwable> TEST_EXCEPTION = RuntimeException.class; 
+1

buena idea, pero desafortunadamente no funciona de todos modos. – AlexR

+0

Dejé intencionalmente genéricos, es independiente de eso. – sibidiba

+0

Bueno, en este caso, no sé. Parece que esta es una limitación accidental del idioma, pero no estoy seguro. :( –

1

que tiene el "valor de anotación debe ser una clase literal" en lo siguiente:

@ServerEndpoint(value="/story/notifications", 
     encoders = (StickerEncoder.class), 
     decoders = (StickerDecoder.class)) 

que esto ocurra mientras siguiendo uno de los oráculos tutoriales en websockets. Resulta que el video no es de la calidad de 720p y la falta de claridad oculta las llaves que parecen corchetes. Entonces el error desaparece al cambiar los corchetes (paréntesis) por llaves.

@ServerEndpoint(value="/story/notifications", 
     encoders = {StickerEncoder.class}, 
     decoders = {StickerDecoder.class}) 

hth cualquiera que pueda tropezar con lo mismo en el futuro.

Cuestiones relacionadas