Pregunta

No entiendo por qué no hay herencia en las anotaciones de Java, al igual que las clases de Java. Creo que sería muy útil.

Por ejemplo: quiero saber si una anotación dada es un validador. Con la herencia, podría navegar reflexivamente a través de superclases para saber si esta anotación extiende una ValidatorAnnotation . De lo contrario, ¿cómo puedo lograr esto?

Entonces, ¿alguien puede darme una razón para esta decisión de diseño?

¿Fue útil?

Solución

Sobre la razón por la que no fue diseñado de esa manera, puede encontrar la respuesta en JSR 175 Preguntas frecuentes de diseño, donde dice:

  

¿Por qué no admite el subtipo de anotación (donde un tipo de anotación se extiende a otro)?

     

Complica el tipo de anotación.   sistema, y ??lo hace mucho más   difícil de escribir "Herramientas específicas".

     

...

     

“Herramientas específicas” - Programas que consultan   tipos conocidos de anotación de arbitrario   programas externos Generadores de trozos,   por ejemplo, caer en esta categoría.   Estos programas se leerán anotados.   Clases sin cargarlas en el   máquina virtual, pero se cargará   interfaces de anotación.

Entonces, sí, supongo, la razón es que solo KISS. De todos modos, parece que este problema (junto con muchos otros) se está analizando como parte de JSR 308 , e incluso puede encontrar un compilador alternativo con esta funcionalidad ya desarrollada por Mathias Ricken .

Otros consejos

Las anotaciones extensibles agregarían efectivamente la carga de especificar y mantener otro tipo de sistema. Y este sería un sistema de tipos bastante único, por lo que no podría simplemente aplicar un paradigma de tipo OO.

Piense en todos los problemas cuando introduzca polimorfismo y herencia en una anotación (por ejemplo, ¿qué sucede cuando la subnotación cambia las especificaciones de la meta-anotación, como la retención?)

¿Y toda esta complejidad agregada para qué caso de uso?

¿Quieres saber si una anotación dada pertenece a una categoría?

Prueba esto:

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

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

}

Como puede ver, puede agrupar y clasificar fácilmente las anotaciones sin molestias utilizando las instalaciones proporcionadas.

Por lo tanto, KISS es la razón para no introducir un sistema de tipo meta tipo en Java idioma.

[p.s. editar]

Utilicé el String simplemente como demostración y en vista de una meta anotación abierta. Para su propio proyecto dado, obviamente puede usar una enumeración de tipos de categoría y especificar múltiples categorías (" herencia múltiple ") para una anotación dada. Tenga en cuenta que los valores son totalmente falsos y solo para fines de demostración:

@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 {

}

En un sentido, ya lo tienes con Annotations - meta Annotations. Si realiza anotaciones en una anotación con metainformación, esto equivale de muchas maneras a extender una interfaz adicional. Las anotaciones son interfaces, por lo que el polimorfismo no entra realmente en juego, y como son de naturaleza estática, no puede haber un despacho dinámico en tiempo de ejecución.

En el ejemplo de tu validador, puedes obtener el tipo anotado en la anotación y ver si tiene una meta-anotación del validador.

El único caso de uso que podría ver que la herencia ayudaría es si quisiera poder obtener la anotación por supertipo, pero eso agregaría un montón de complejidad, porque un método o tipo dado puede tener dos anotaciones de este tipo en él, lo que significa que se debería devolver una matriz en lugar de un solo objeto.

Así que creo que la respuesta definitiva es que los casos de uso son esotéricos y complican los casos de uso más estándar, por lo que no vale la pena.

Los diseñadores de soporte de anotación de Java realizaron una serie de " simplificaciones " en detrimento de la comunidad de Java.

  1. Ningún subtipo de anotaciones hace que muchas anotaciones complejas sean innecesariamente feas. Uno no puede simplemente tener un atributo dentro de una anotación que pueda contener una de tres cosas. Uno debe tener tres atributos separados, lo que confunde a los desarrolladores y requiere la validación en tiempo de ejecución para garantizar que solo se use uno de los tres.

  2. Solo una anotación de un tipo dado por sitio. Esto ha llevado a un patrón de anotación de colección completamente innecesario. @Validation y @Validations, @Image y @Images, etc.

El segundo está siendo remediado en Java 8, pero es demasiado tarde. Muchos marcos se han escrito en función de lo que era posible en Java 5 y ahora estas API verrugas están aquí para quedarse por un buen tiempo.

Una cosa en la que podría pensar es en la posibilidad de tener múltiples anotaciones. Así que puedes agregar un validador y una anotación más específica en el mismo lugar. Pero podría estar equivocado :)

Nunca pensé en eso, pero ... parece que tienes razón, no hay ningún problema con la facilidad de herencia de anotaciones (al menos no veo el problema).

Acerca de su ejemplo con la anotación 'validador' : puede explotar el enfoque 'meta-anotación' . Es decir. aplica una meta-anotación particular a toda la interfaz de anotación.

Podría tardar tres años en responder a esta pregunta, pero me pareció interesante porque me encontré en el mismo lugar. Aquí está mi opinión sobre ello. Puedes ver las anotaciones como enumeraciones. Proporcionan un tipo de información unidireccional: la utilizan o la pierden.

Tuve una situación en la que quería simular GET, POST, PUT y DELETE en una aplicación web. Tenía tantas ganas de tener un " super " anotación que se llamó "HTTP_METHOD". Más tarde me di cuenta de que no importaba. Bueno, tuve que conformarme con el uso de un campo oculto en el formulario HTML para identificar DELETE y PUT (porque POST y GET estaban disponibles de todos modos).

En el lado del servidor, busqué un parámetro de solicitud oculto con el nombre, " _method " ;. Si el valor era PUT o DELETE, entonces anuló el método de solicitud HTTP asociado. Dicho esto, no importaba si necesitaba o no extender una anotación para hacer el trabajo. Todas las anotaciones parecían iguales, pero fueron tratadas de manera diferente en el lado del servidor.

Entonces, en su caso, elimine la comezón para extender las anotaciones. Trátelos como 'marcadores'. Ellos " representan " alguna información, y no necesariamente " manipular " alguna información.

el mismo problema que tengo. No, no puedes. Me "discipliné" a mí mismo para escribir las propiedades en las anotaciones para respetar algunos estándares, por lo que fuera de ellas, puede "oler" qué tipo de anotación es por las propiedades que tiene.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top