Anteriormente...
Tipos Aceptados
- Tipos Primitivos: int, float, short, double, long, boolean, byte, char.
- String
- Class
- Enum: como en el ejemplo de la parte 1.
- Annotation: anotaciones.
- Array: un array de cualquiera de los anteriores (String[]).
Uso de Anotaciones, Reflexión / Reflection
El uso mas simple de una anotación es el de ayuda en el código, es decir pueden crearse anotaciones para informar algo al programador (por ejemplo @Deprecated), con el fin de organizar u ordenar nuestro código. Pero el uso de las anotaciones va mas allá, es por algo que los frameworks actuales hacen uso de estas para su funcionamiento.
Por ejemplo Hibernate y JPA (herramientas ORM) dan la posibilidad de definir el modelo de datos, es decir las tablas de una base de datos y sus relaciones utilizando clases y mediante anotaciones se explican características propias de una base de datos.
Me explico mejor con un ejemplo. Una clase que explicaría una tabla de una base de datos podría ser la siguiente:
public class Persona{
private String idNum;
private String nombre;
private String direccion;
private String telefono;
}
Si bien esta clase nos brinda información importante como que existe una tabla Persona y tiene los campos idNum, nombre, direccion y telefono, esta información no es suficiente, como respondo a las siguientes preguntas
- ¿Cual es el PrimaryKey de esta Tabla?
- ¿Cuales son los campos que pueden ser nulos?
- ¿Cual es la longitud máxima de cada campo?
- ¿La tabla en la base de datos se llama también "Persona"?
- ¿Algún campo es ForeignKey de otra tabla?
- etc
Aqui es donde juegan un papel importante las anotaciones porque nos permite agregar información adicional a los campos, metodos, clase, parametros, etc., sin afectar el codigo en si. La clase equivalente con anotaciones podría ser:
...
@Entity
@Table (name = "persona")
public class Persona implements java.io.Serializable {
@Id
@Column(name = "prsId", length = 15, nullable = false)
private String idNum;
@Column(name = "nombre", length = 200, nullable = false)
private String nombre;
@Column(name = "direccion", length = 200, nullable = false)
private String direccion;
@Column(name = "telefono", length = 15, nullable = false)
private String telefono;
...
}
...
El anterior es un fragmento de código que JPA o Hibernate utiliza para explicar al framework como se estructura la tabla, una explicación breve es: @Id indica el campo que es el PrimaryKey de la tabla, @Column indica que es una campo de la tabla y sus atributos indican el nombre en la base de datos(name) longitud máxima (length) si puede ser nulo (nullable).
En si el funcionamiento del framework no es el objetivo de este artículo, sino el de presentar una idea del uso que pueden tener las anotaciones.
Reflexión/Reflection
La Reflexión hace referencia a la lectura de las anotaciones. Una de los requerimientos para poder leer las anotaciones en tiempo de ejecución es que esta se de tipo @Retention(RetentionPolicy.RUNTIME).
La lectura de las anotaciones se la realiza utilizando las herramientas de java.lang.reflect (es por ello el nombre Reflection), En el siguiente ejemplo se mostraran los métodos y campos de la clase java.util.Date que tienen la anotación @Deprecated:
...
java.lang.reflect.Method[] ms = java.util.Date.class.getDeclaredMethods();
for (java.lang.reflect.Method m : ms) {
Deprecated an = m.getAnnotation(Deprecated.class);
if (an != null) {
System.out.println("El método " + m.getName() + " tiene @Deprecated");
}
}
java.lang.reflect.Field[] fs = java.util.Date.class.getDeclaredFields();
for (java.lang.reflect.Field f : fs) {
Deprecated an = f.getAnnotation(Deprecated.class);
if (an != null) {
System.out.println(f.getName()+" tiene @Deprecated");
//an.atributo(); //para obtener el atributo de la anotación
}
}
...
El resultado será
El método parse tiene @Deprecated
El método getDate tiene @Deprecated
El método UTC tiene @Deprecated
El método getDay tiene @Deprecated
El método getHours tiene @Deprecated
El método getMinutes tiene @Deprecated
El método getMonth tiene @Deprecated
El método getSeconds tiene @Deprecated
El método getYear tiene @Deprecated
El método setDate tiene @Deprecated
El método setHours tiene @Deprecated
El método setMinutes tiene @Deprecated
El método setMonth tiene @Deprecated
El método setSeconds tiene @Deprecated
El método setYear tiene @Deprecated
El método toGMTString tiene @Deprecated
El método getTimezoneOffset tiene @Deprecated
El método toLocaleString tiene @Deprecated
Entonces todos estos metodos estan obsoletos en la clase java.util.Date.
El algoritmo anterior es una idea de lo que se puede hacer con el paquete reflect, para una explicación mas avanzada revisa el tutorial Reflection - java.lang.reflect.*
Para obtener el atributo de una anotación y un ejemplo mas completo revisa la parte 3.
Para obtener el atributo de una anotación y un ejemplo mas completo revisa la parte 3.
Consideraciones
Los valores de los atributos de una anotación tiene que ser constantes al momento de compilar es decir NO puede utilizarse:
@MyAnotacion(atributo = "x" + obj.metodo())
Una anotación puede tener varios @Target:
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface myAnotacion
Para definir default de un Array es:
public String[] atributo() default {};
...
public int[] atributo() default {};
Las anotaciones pueden ser tan complejas como:
@AnotacionPadre({
@AnotacionHijo(at1="aaa", at2=33),
@AnotacionHijo(at1="bbb")
})
public void ....(){}
//-----------
@Target(ElementType.METHOD)
public @interface AnotacionHijo{
public String at1();
public int at2() default 0;
)
//-----------
@Target(ElementType.METHOD)
public @interface AnotacionPadre{
public AnotacionHijo[] value() default {};
)
Bibliografía
Mas...
Un ejemplo as complejo se lo puede revisar en la parte 3.