Domanda

Non capisco perché non ci sia ereditarietà nelle annotazioni Java, proprio come le classi Java. Penso che sarebbe molto utile.

Ad esempio: voglio sapere se una determinata annotazione è un validatore. Con l'eredità, ho potuto navigare riflessivamente tra le superclassi per sapere se questa annotazione estende un ValidatorAnnotation . Altrimenti, come posso raggiungere questo obiettivo?

Quindi, qualcuno può darmi un motivo per questa decisione di progettazione?

È stato utile?

Soluzione

Sul motivo per cui non è stato progettato in questo modo puoi trovare la risposta in JSR 175 Domande frequenti sulla progettazione, dove si dice:

  

Perché non supporti il ??sottotipo di annotazione (dove un tipo di annotazione ne estende un altro)?

     

Ciò complica il tipo di annotazione   sistema e lo rende molto di più   difficile da scrivere & # 8220; Strumenti specifici & # 8221 ;.

     

& # 8230;

     

& # 8220; Strumenti specifici & # 8221; & # 8212; Programmi che interrogano   tipi di annotazione noti arbitrari   programmi esterni. Generatori di stub,   ad esempio, rientrare in questa categoria.   Questi programmi leggeranno annotati   classi senza caricarle in   macchina virtuale, ma verrà caricata   interfacce di annotazione.

Quindi, sì, immagino, il motivo è solo KISS. Ad ogni modo, sembra che questo problema (insieme a molti altri) venga esaminato come parte di JSR 308 e puoi persino trovare un compilatore alternativo con questa funzionalità già sviluppata da Mathias Ricken .

Altri suggerimenti

Le annotazioni estendibili aggiungerebbero effettivamente l'onere di specificare e mantenere un altro sistema di tipi. E questo sarebbe un sistema di tipo abbastanza unico, quindi non potresti semplicemente applicare un paradigma di tipo OO.

Rifletti su tutti i problemi quando introduci il polimorfismo e l'ereditarietà in un'annotazione (ad es. cosa succede quando l'annotazione secondaria modifica le specifiche delle meta-annotazioni come la conservazione?)

E tutta questa complessità aggiunta per quale caso d'uso?

Vuoi sapere se una determinata annotazione appartiene a una categoria?

Prova questo:

@Target(ElementType.ANNOTATION_TYPE)
public @interface Category {
    String category();
}

@Category(category="validator")
public @interface MyFooBarValidator {

}

Come puoi vedere, puoi facilmente raggruppare e classificare le annotazioni senza indebito dolore utilizzando le strutture fornite.

Quindi, KISS è la ragione per non introdurre un sistema di tipo meta-tipo in Java lingua.

[P.S. modifica]

Ho usato la stringa semplicemente per dimostrazione e in vista di una meta annotazione aperta. Per il tuo progetto, puoi ovviamente usare un enum di tipi di categoria e specificare più categorie ("quotazione multipla") per una data annotazione. Si noti che i valori sono completamente fasulli e solo a scopo dimostrativo:

@Target(ElementType.ANNOTATION_TYPE)
public @interface Category {
    AnnotationCategory[] category();
}
public enum AnnotationCategory {
    GENERAL,
    SEMANTICS,
    VALIDATION,
    ETC
}

@Category(category={AnnotationCategory.GENERAL, AnnotationCategory.SEMANTICS})
public @interface FooBarAnnotation {

}

In un certo senso ce l'hai già con Annotazioni - meta Annotazioni. Se annoti un'annotazione con meta informazioni, ciò equivale in molti modi a estendere un'interfaccia aggiuntiva. Le annotazioni sono interfacce, quindi il polimorfismo non è realmente in gioco, e poiché sono di natura statica, non può esserci dispacciamento dinamico di runtime.

Nel tuo esempio di validatore, potresti semplicemente sull'annotazione ottenere il tipo annotato e vedere se ha una meta-annotazione validatore.

L'unico caso d'uso in cui ho potuto vedere che l'ereditarietà sarebbe utile se volessi essere in grado di ottenere l'annotazione per super tipo, ma ciò aggiungerebbe un sacco di complessità, perché un determinato metodo o tipo potrebbe avere due di tali annotazioni su di esso, il che significa che dovrebbe essere restituito un array anziché un singolo oggetto.

Quindi penso che la risposta definitiva sia che i casi d'uso sono esoterici e complicano i casi d'uso più standard rendendolo non ne vale la pena.

I progettisti del supporto per le annotazioni Java hanno apportato una serie di "semplificazioni" a scapito della comunità Java.

  1. Nessun sottotipo di annotazioni rende inutilmente brutte molte annotazioni complesse. Non si può semplicemente avere un attributo all'interno di un'annotazione che può contenere una di tre cose. È necessario disporre di tre attributi separati, che confondono gli sviluppatori e richiedono la convalida del runtime per garantire che venga utilizzato solo uno dei tre.

  2. Solo una annotazione di un determinato tipo per sito. Ciò ha portato al modello di annotazione della raccolta completamente inutile. @Validation e @Validations, @Image e @Images, ecc.

Il secondo è stato risolto in Java 8, ma è troppo tardi. Molti framework sono stati scritti in base a ciò che era possibile in Java 5 e ora queste verruche API sono qui per rimanere per un bel po 'di tempo.

Una cosa che mi viene in mente è la possibilità di avere più annotazioni. Quindi potresti aggiungere validatore e un'annotazione più specifica nello stesso posto. Ma potrei sbagliarmi :)

Non ci ho mai pensato ma ... sembra che tu abbia ragione, non ci sono problemi con la funzione di ereditarietà delle annotazioni (almeno non ci vedo il problema).

A proposito del tuo esempio con l'annotazione 'validator' - puoi sfruttare l'approccio 'meta-annotation' . Cioè applichi una particolare meta-annotazione all'intera interfaccia delle annotazioni.

Potrei essere in ritardo di tre anni per rispondere a questa domanda, ma l'ho trovato interessante perché mi sono trovato nello stesso punto. Ecco la mia opinione su di esso. Puoi visualizzare le annotazioni come Enum. Forniscono un tipo di informazione a senso unico: usale o perdila.

Ho avuto una situazione in cui volevo simulare GET, POST, PUT e DELETE in un'app Web. Volevo così tanto avere un "super" annotazione chiamata " HTTP_METHOD " ;. In seguito mi sono reso conto che non aveva importanza. Bene, ho dovuto accontentarmi di usare un campo nascosto nel modulo HTML per identificare DELETE e PUT (perché POST e GET erano comunque disponibili).

Sul lato server, ho cercato un parametro di richiesta nascosto con il nome, "quotmet _". Se il valore era PUT o DELETE, ha la precedenza sul metodo di richiesta HTTP associato. Detto questo, non importava se avessi bisogno o meno di estendere un'annotazione per fare il lavoro. Tutte le annotazioni sembravano uguali, ma sono state trattate diversamente sul lato server.

Quindi, nel tuo caso, elimina il prurito per estendere le annotazioni. Trattali come "marcatori". Essi "rappresentano" alcune informazioni e non necessariamente "manipolare" alcune informazioni.

lo stesso problema che ho. No, non puoi. Mi sono "disciplinato" a scrivere proprietà nelle annotazioni per rispettare alcuni standard, quindi al di fuori quando si ottiene un'annotazione è possibile "annusare" che tipo di annotazione è per proprietà che ha.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top