stringtranslate.com

Anotación de Java

En el lenguaje de programación Java , una anotación es una forma de metadatos sintácticos que se pueden agregar al código fuente de Java . [1] Las clases , métodos , variables , parámetros y paquetes Java pueden anotarse. Al igual que las etiquetas Javadoc , las anotaciones Java se pueden leer desde archivos fuente. A diferencia de las etiquetas Javadoc , las anotaciones Java también se pueden incrustar y leer desde archivos de clase Java generados por el compilador Java . Esto permite que la máquina virtual Java conserve las anotaciones en tiempo de ejecución y las lea a través de la reflexión . [2] Es posible crear metaanotaciones a partir de las existentes en Java. [3]

Historia

La plataforma Java tiene varios mecanismos de anotación ad hoctransient , por ejemplo, el modificador o la @Deprecatedetiqueta javadoc. La solicitud de especificación de Java JSR-175 introdujo la función de anotación de propósito general (también conocida como metadatos ) en el Proceso de la Comunidad Java en 2002; obtuvo la aprobación en septiembre de 2004. [4]

Las anotaciones se hicieron disponibles en el lenguaje a partir de la versión 1.5 del Java Development Kit (JDK). La aptherramienta proporcionó una interfaz provisional para el procesamiento de anotaciones en tiempo de compilación en la versión 1.5 del JDK; JSR-269 la formalizó y se integró en el compilador javac en la versión 1.6.

Anotaciones integradas

Java define un conjunto de anotaciones que están integradas en el lenguaje. De las siete anotaciones estándar, tres forman parte de java.lang y las cuatro restantes se importan desde java.lang.annotation. [5] [6]

Anotaciones aplicadas al código Java:

Anotaciones aplicadas a otras anotaciones (también conocidas como "Metaanotaciones"):

Desde Java 7, se han agregado tres anotaciones adicionales al lenguaje.

Ejemplo

Anotaciones integradas

Este ejemplo demuestra el uso de la @Overrideanotación. Indica al compilador que compruebe las clases principales en busca de métodos coincidentes. En este caso, se genera un error porque el gettype()método de la clase Cat no reemplaza getType()al de la clase Animal como se desea, debido a la falta de coincidencia de case . Si la @Overrideanotación no existiera, gettype()se crearía un nuevo método de nombre en la clase Cat.

clase pública Animal { public void speak () { }         public String getType () { return "Animal genérico" ; } }      clase pública Gato extiende Animal { @Override public void speak () { // Esta es una buena anulación. System . println ( "Miau." ) ; }              @Override public String gettype () { // Error en tiempo de compilación debido a un error tipográfico: debería ser getType() y no gettype(). return "Cat" ; } }        

Anotaciones personalizadas

Las declaraciones de tipo de anotación son similares a las declaraciones de interfaz normales. Un signo de arroba (@) precede a la palabra clave "interfaz".

 // @Twizzle es una anotación para el método toggle(). @Twizzle public void toggle () { }       // Declara la anotación Twizzle. public @interface Twizzle { }     

Las anotaciones pueden incluir un conjunto de pares clave-valor, que se modelan como métodos del tipo de anotación. Cada declaración de método define un elemento del tipo de anotación. Las declaraciones de método no deben tener ningún parámetro ni una cláusula throws. Los tipos de retorno están restringidos a primitivos , String , Class, enums , anotaciones y matrices de los tipos anteriores. Los métodos pueden tener valores predeterminados .

 // Igual que: @Edible(value = true) @Edible ( true ) Item item = new Carrot ();       público @interface Edible { valor booleano () predeterminado falso ; }         @Autor ( primero = "Oompah" , último = "Loompah" ) Libro libro = nuevo Libro ( );           público @interface Autor { Cadena primero (); Cadena último (); }        

Las anotaciones en sí pueden anotarse para indicar dónde y cuándo pueden usarse:

 @Retention ( RetentionPolicy . RUNTIME ) // Hacer que esta anotación sea accesible en tiempo de ejecución a través de la reflexión. @Target ({ ElementType . METHOD }) // Esta anotación solo se puede aplicar a métodos de clase. public @interface Tweezable { }        

El compilador reserva un conjunto de anotaciones especiales (incluidas @Deprecated, @Overridey @SuppressWarnings) para fines sintácticos.

Los frameworks suelen utilizar anotaciones como una forma de aplicar de forma cómoda comportamientos a clases y métodos definidos por el usuario que, de otro modo, se deben declarar en una fuente externa (como un archivo de configuración XML) o mediante programación (con llamadas a API). La siguiente es, por ejemplo, una clase de datos JPA anotada:

@Entity // Declara esto como un bean de entidad @Table ( name = "people" ) // Asigna el bean a la tabla SQL "people" public class Person implements Serializable { @Id // Asigna esto a la columna de clave principal. @GeneratedValue ( strategy = GenerationType . AUTO ) // La base de datos generará nuevas claves principales, no nosotros. private Integer id ;                   @Column ( length = 32 ) // Trunca los valores de la columna a 32 caracteres. private String name ;       público entero getId () { devolver id ; }       público void setId ( entero id ) { este . id = id ; }         public String getName () { devolver nombre ; }       public void setName ( String nombre ) { this.name = nombre ; } }        

Las anotaciones no son llamadas a métodos y, por sí mismas, no harán nada. En cambio, el objeto de clase se pasa a la implementación de JPA en tiempo de ejecución , que luego extrae las anotaciones para generar un mapeo relacional de objetos .

A continuación se ofrece un ejemplo completo:

paquete com.annotation ; importar java.lang.annotation.Documented ; importar java.lang.annotation.ElementType ; importar java.lang.annotation.Inherited ; importar java.lang.annotation.Retention ; importar java.lang.annotation.RetentionPolicy ; importar java.lang.annotation.Target ;      @Documented @Retention ( RetentionPolicy . RUNTIME ) @Target ({ ElementType . TYPE , ElementType . METHOD , ElementType . CONSTRUCTOR , ElementType . ANNOTATION_TYPE , ElementType . PACKAGE , ElementType . FIELD , ElementType . LOCAL_VARIABLE }) @Inherited  público @interface Unfinished { enumeración pública Priority { BAJA , MEDIA , ALTA } String value (); String [] changedBy () predeterminado "" ; String [] lastChangedBy () predeterminado "" ; Priority priority () predeterminado Priority . MEDIUM ; String createdBy () predeterminado "James Gosling" ; String lastChanged () predeterminado "2011-07-08" ; }                                 
paquete com.annotation ; público @interface UnderConstruction { String propietario () predeterminado "Patrick Naughton" ; String valor () predeterminado "El objeto está en construcción." ; String creado por () predeterminado "Mike Sheridan" ; String último cambio () predeterminado "2011-07-08" ; }                   
paquete com.validators ; importar javax.faces.application.FacesMessage ; importar javax.faces.component.UIComponent ; importar javax.faces.context.FacesContext ; importar javax.faces.validator.Validator ; importar javax.faces.validator.ValidatorException ;     importar com.annotation.UnderConstruction ; importar com.annotation.Unfinished ; importar com.annotation.Unfinished.Priority ; importar com.util.Util ;    @UnderConstruction ( propietario = "Jon Doe" ) clase pública DateValidator implementa Validator { public void validar ( contexto FacesContext , componente UIComponent , objeto valor ) lanza ValidatorException { String fecha = ( String ) valor ; String errorLabel = "Ingrese una fecha válida." ; if ( ! componente.getAttributes ( ). isEmpty ()) { errorLabel = ( String ) componente.getAttributes ( ). get ( " errordisplayval " ); }                                  if ( ! Util . validaAGivenDate ( fecha )) { @Unfinished ( changedBy = "Steve" , valor = "si desea agregar un mensaje al contexto o no, confirme" , prioridad = Priority . HIGH ) FacesMessage mensaje = new FacesMessage (); mensaje . setSeverity ( FacesMessage . SEVERITY_ERROR ); mensaje . setSummary ( errorLabel ); mensaje . setDetail ( errorLabel ); generar una nueva ValidatorException ( mensaje ); } } }                         

Tratamiento

Cuando se compila el código fuente de Java, las anotaciones pueden procesarse mediante complementos del compilador denominados procesadores de anotaciones. Los procesadores pueden producir mensajes informativos o crear archivos o recursos fuente de Java adicionales, que a su vez pueden compilarse y procesarse. Sin embargo, los procesadores de anotaciones no pueden modificar el código anotado en sí. (Las modificaciones del código pueden implementarse utilizando métodos que van más allá de la especificación del lenguaje Java). El compilador de Java almacena de forma condicional los metadatos de las anotaciones en los archivos de clase, si la anotación tiene un carácter RetentionPolicyde CLASSo RUNTIME. Más tarde, la JVM u otros programas pueden buscar los metadatos para determinar cómo interactuar con los elementos del programa o cambiar su comportamiento.

Además de procesar una anotación mediante un procesador de anotaciones, un programador Java puede escribir su propio código que utilice la reflexión para procesar la anotación. Java SE 5 admite una nueva interfaz que se define en el java.lang.reflectpaquete. Este paquete contiene la interfaz llamada AnnotatedElementque se implementa mediante las clases de reflexión de Java, incluidas Class, Constructor, Field, Methody Package. Las implementaciones de esta interfaz se utilizan para representar un elemento anotado del programa que se está ejecutando actualmente en la máquina virtual de Java. Esta interfaz permite leer las anotaciones de forma reflexiva.

La AnnotatedElementinterfaz proporciona acceso a las anotaciones que tienen RUNTIMEretención. Este acceso lo proporcionan los métodos getAnnotation, getAnnotationsy isAnnotationPresent. Debido a que los tipos de anotaciones se compilan y almacenan en archivos de código de bytes al igual que las clases, las anotaciones devueltas por estos métodos se pueden consultar como cualquier objeto Java normal. A continuación, se proporciona un ejemplo completo de procesamiento de una anotación:

importar java.lang.annotation.Retention ; importar java.lang.annotation.RetentionPolicy ;  // Esta es la anotación que se procesará // El valor predeterminado para Target son todos los elementos Java // Cambiar la política de retención a RUNTIME (el valor predeterminado es CLASS) @Retention ( RetentionPolicy . RUNTIME ) public @interface TypeHeader { // Valor predeterminado especificado para el atributo de desarrollador String developer () predeterminado "Unknown" ; String lastModified (); String [] teamMembers (); int meaningOfLife (); }               
// Esta es la anotación que se aplica a una clase @TypeHeader ( developer = "Bob Bee" , lastModified = "2013-02-12" , teamMembers = { "Ann" , "Dan" , "Fran" }, meaningOfLife = 42 )               clase pública SetCustomAnnotation { // El contenido de la clase va aquí }    
// Este es el código de ejemplo que procesa la anotación import java.lang.annotation.Annotation ; import java.lang.reflect.AnnotatedElement ;  clase pública UseCustomAnnotation { pública estática void main ( String [] args ) { Clase < SetCustomAnnotation > classObject = SetCustomAnnotation . class ; readAnnotation ( classObject ); }                 static void readAnnotation ( AnnotatedElement element ) { try { System.out.println ( "Valores del elemento de anotación : \n" ) ; if ( element.isAnnotationPresent ( TypeHeader.class ) ) { // getAnnotation devuelve el tipo de anotación Annotation singleAnnotation = element.getAnnotation ( TypeHeader.class ) ; TypeHeader header = ( TypeHeader ) singleAnnotation ;                      Sistema . out . println ( "Desarrollador: " + header . developer ()); Sistema . out . println ( "Última modificación: " + header . lastModified ());      // teamMembers devuelto como String [] System . print ( " Miembros del equipo: " ) ; for ( String miembro : header . teamMembers ()) System . print ( miembro + ", " ); System . print ( " \n" ) ;           Sistema . out . println ( "Sentido de la vida: " + header . meaningOfLife ()); } } catch ( Exception exception ) { exception . printStackTrace (); } } }          

Véase también

Referencias

  1. ^ "Anotaciones". Sun Microsystems . Archivado desde el original el 25 de septiembre de 2011. Consultado el 30 de septiembre de 2011 ..
  2. ^ Sun Microsystems (2005). Especificación del lenguaje Java(TM) (3.ª ed.). Prentice Hall . ISBN 0-321-24678-0..
  3. ^ Dare Obasanjo (2007). "UNA COMPARACIÓN DEL LENGUAJE DE PROGRAMACIÓN C# DE MICROSOFT CON EL LENGUAJE DE PROGRAMACIÓN JAVA DE SUN MICROSYSTEMS: Anotaciones de metadatos". Dare Obasanjo. Archivado desde el original el 19 de septiembre de 2012. Consultado el 20 de septiembre de 2012 .
  4. ^ Coward, Danny (2 de noviembre de 2006). "JSR 175: una herramienta de metadatos para el lenguaje de programación JavaTM". Proceso de la comunidad Java . Consultado el 5 de marzo de 2008 .
  5. ^ "Tipos de anotaciones predefinidos". Oracle Corporation . Consultado el 17 de diciembre de 2016 .
  6. ^ "Las anotaciones integradas: anotaciones estándar" . Consultado el 17 de diciembre de 2016 .

Enlaces externos