2011-12-22 12 views
8

Qualcuno può spiegare perché i parametri di annotazione String e Classe sono previsti in modo diverso? Perché il compilatore richiede valori letterali per Classi, accettando le costanti per le stringhe?L'attributo di annotazione deve essere un valore letterale di classe? Perché? Anche le costanti vanno bene

esempio Lavorare con @RequestMapping di Primavera:

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

WTF esempio con @Test di 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 
    ... 
} 

Che funziona, naturalmente, è @Test (expectedExceptions = RuntimeException.class). Ma perché? L'unica differenza nel parametro di annotazione che vedo è il suo tipo: String vs Class. Perché mai il compilatore Java accetta anche String constant ma accetta solo valori letterali di classe?

risposta

5

Il linguaggio Java Specification non permette di utilizzare le costanti in fase di compilazione con i parametri di tipo Class. Puoi utilizzare solo valori letterali di classe.

Il JLS ha quanto segue da dire sui valori dei parametri adatti per annotazioni:

Un tipo di elemento T è proporzionata ad un valore di elemento V se e solo se una delle seguenti condizioni :

  • T è un tipo di matrice e [] e:
    • V è un ElementValueArrayInitializer ed ogni ElementValueInitializer (analogo a un inizializzatore variabile in un inizializzatore array) in V è commisurata E. O
    • V è un elementValue che è commisurato T.
  • Il tipo di V è assegnazione compatibile (§5.2) con T e, inoltre:
    • Se T è un tipo primitivo o stringa, V è un'espressione costante (§15.28) .
    • V non è nullo.
    • se T è classe, o una chiamata di classe, e V è una classe letterale (§15.8.2).
    • Se T è un tipo enum e V è una costante enum.

Si tratta di un errore di compilazione se il tipo di elemento non è commisurata al elementValue.

Non posso dire perché questa restrizione è nel JLS, tuttavia.

+0

Wow, mi manca assolutamente il senso di questo, perché questa restrizione in classe? Grazie per averlo sottolineato. – sibidiba

0

Guardate questo:

public static final Class TEST_EXCEPTION = RuntimeException.class; 

La classe dovrebbe essere un Throwable che il compilatore è in grado di controllare. Quindi, provate questo:

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

buona idea, ma sfortunatamente non funziona comunque. – AlexR

+0

Ho intenzionalmente omesso i farmaci generici, è indipendente da quello. – sibidiba

+0

Beh, in questo caso, non lo so. Sembra che questa sia una limitazione accidentale della lingua, ma non ne sono sicuro. :( –

1

ho avuto il "valore di annotazione deve essere una classe letteralmente" su quanto segue:

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

ciò accada, mentre seguendo uno dei tutorial su Oracoli WebSockets. Risulta che il video non è la qualità 720p e la sfocatura nasconde le parentesi graffe che sembrano parentesi graffe. Quindi l'errore scompare quando si cambiano le parentesi (parentesi) per le parentesi graffe.

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

hth chiunque possa inciampare lo stesso in futuro.