¿Qué son las anotaciones?
La anotación de Java (Annotation), también conocida como anotación de Java, es un mecanismo de anotación introducido por JDK5.0. Por ejemplo, nuestros comunes @Override y @Deprecated son anotaciones. Las anotaciones se pueden agregar a clases, métodos, variables miembro, etc., de forma similar a " etiquetarlas ".
¿Cómo se definen las anotaciones?
El nombre de la anotación de la @interfaz pública {} se parece mucho a la interfaz de definición, excepto que hay una interfaz de símbolo @ adicional: anotación del nombre de la interfaz de la interfaz pública : nombre de la anotación de la @interfaz pública
public @interface lkx {
}
¿Cómo usar las anotaciones?
Ahora que se han definido nuestras anotaciones, podemos usar directamente "nombre de anotación @" al usarlas. Por ejemplo, podemos definirlas en " clases, variables miembro y métodos miembro " de la siguiente manera:
@lkx
public class Test {
@lkx
private int num;
@lkx
public static void main(String[] args) {
System.out.println("hello");
}
}
Ahora que la anotación se ha definido y utilizado, pero no quiero definirla en la clase o el método miembro, solo quiero definirla en el método miembro. ¿Cómo puedo hacer que la anotación solo se defina en el método y el informe? un error cuando se define en otro lugar? El efecto deseado:
En este momento, es necesario usar metanotaciones para limitar el alcance.
anotación meta
En términos simples, las meta-anotaciones son anotaciones definidas en annotations.Hay cuatro meta-anotaciones en Java @Target @Retention @Documented @Inherited
@Objetivo
@Target se usa para describir el alcance de la definición de la anotación, que puede limitar el tipo de elemento definido por esta anotación.
parámetro | efecto |
---|---|
TipoDeElemento.ANOTATION_TYPE | Se puede aplicar a tipos de anotaciones. |
ElementType.CONSTRUCTOR | se puede aplicar al constructor |
ElementType.FIELD | Se puede aplicar a campos o propiedades. |
TipoDeElemento.LOCAL_VARIABLE | se puede aplicar a variables locales |
ElementType.METHOD | Se puede aplicar a las anotaciones a nivel de método |
TipoDeElemento.PAQUETE | Se puede aplicar a declaraciones de paquetes. |
ElementType.PARAMETER | parámetros que se pueden aplicar a los métodos |
TipoDeElemento.TIPO | Se puede aplicar a cualquier elemento de la clase. |
Debido a que queremos restringir solo a las variables miembro, debemos usar ElementType.FIELD
@Target(ElementType.FIELD)
public @interface lkx {
}
Pero, ¿qué pasa si queremos definir tanto las variables de miembro como los métodos de miembro al mismo tiempo? Los parámetros múltiples solo necesitan estar encerrados entre llaves y separados por comas.
@Target({
ElementType.FIELD,ElementType.METHOD})
public @interface lkx {
}
Ahora solo las anotaciones definidas en la clase reportan un error
@Retención
@Retention se utiliza para definir el ciclo de vida de las anotaciones y también puede entenderse como un método de almacenamiento.
parámetro | efecto |
---|---|
RetentionPolicy.SOURCE | Las anotaciones marcadas se mantienen solo en el nivel de origen y el compilador las ignora. |
RetentionPolicy.CLASS | El compilador conserva las anotaciones marcadas en el momento de la compilación, pero la máquina virtual de Java (JVM) las ignora. |
RetentionPolicy.RUNTIME | La JVM conserva las anotaciones marcadas, por lo que el entorno de tiempo de ejecución puede usarlas. |
Las siguientes dos meta-anotaciones no se usan mucho, por lo que no las explicaré en detalle por el momento.
@Documentado
@Documentado se utiliza para describir si se debe conservar su información de anotación al generar documentos de ayuda.
@Heredado
@Inherited se usa para describir si la anotación modificada por él se hereda.
elemento de anotación
Acabamos de definir una anotación arriba, pero no podemos pasar ninguna información, es simplemente equivalente a una etiqueta. Ahora veamos cómo definir parámetros para la anotación:
@Target({
ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.SOURCE)
public @interface lkx {
String name() default "张三"; //可以使用default定义默认的值
int age();
}
Ahora veamos cómo pasar parámetros:
public class Test {
//name有默认值,也可以不写
@lkx(name = "李四",age = 18)
private int num;
public static void main(String[] args) {
System.out.println("hello");
}
}
combate
Ahora que se han definido las anotaciones y se han pasado los parámetros, ¿todavía se pregunta para qué sirven las anotaciones? . . Ahora tenemos un pequeño requisito para asignar los parámetros pasados en la anotación a las variables miembro. Por ejemplo:
@lkx(name = "李四",age = 18)
private int num; //num没有被赋值,等于0
赋值完成后
num = 18
Precauciones:
- El siguiente código necesita usar reflexión, si no sabes cómo hacerlo, puedes leer mis artículos anteriores.
- Debido a que necesita usar la reflexión para obtener parámetros de anotación, @Retention debe definirse como RetentionPolicy.RUNTIME
Código de implementación:
@Target({
ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface lkx {
String name() default "张三";
int age();
}
java复制代码public class Test {
//name有默认值,也可以不写
@lkx(name = "李四",age = 18)
private static int num;
@lkx(name = "王五",age = 38)
private static int age;
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
System.out.println("赋值前: num: " + num+" age: "+age);
//拿到类的字节码
Class<Test> testClass = Test.class;
//拿到所有成员变量
for (Field declaredField : testClass.getDeclaredFields()) {
//检测成员变量上是否有@lkx注解
if (declaredField.isAnnotationPresent(lkx.class)) {
lkx annotation = declaredField.getAnnotation(lkx.class);
//获取到注解中的age的值
int age = annotation.age();
declaredField.set(testClass.newInstance(),age);
}
}
System.out.println("赋值后: num: " + num+" age: "+age);
}
}
resultado de la operación:
java复制代码赋值前: num: 0 age: 0
赋值后: num: 18 age: 38