Anotaciones y reflexión en Java (notas)

1. Notas

1. ¿Qué es la anotación?

  • La anotación es una nueva tecnología introducida a partir de JDK5.0.
  • El papel de la anotación: no es el programa en sí, puede explicar el programa. Puede ser leído por otros programas (como compiladores, etc.).
  • Formato de anotación: la anotación es "@nombre de anotación" que existe en el código y también se pueden agregar algunos valores de parámetros.

2. Anotaciones integradas

  • @Override: se utiliza como figura retórica para indicar que la declaración de un método pretende anular otra declaración en la superclase.
  • @Deprecated: obsoleto, pero se puede utilizar o existe una forma mejor.
  • @SuppressWarnings: se utiliza para suprimir mensajes de advertencia durante la compilación, se deben agregar parámetros.

//SuppressWarnings 用来抑制编译时的警告信息,必须要添加参数
@SuppressWarnings("all")
public class test1 extends parent{
    
    
    public static void main(String[] args) {
    
    
    }
    //Override 重写的注解
    @Override
    public void test1() {
    
    
        super.test1();
    }
    //Deprecated 不推荐使用,但是可以使用,或存在更好的方式。
    @Deprecated
    public static void test2(){
    
    
        System.out.println("这是Deprecated");}
}

3. Metaanotación
La función de la metaanotación es anotar otras anotaciones. Java define 4 tipos de metaanotación estándar, que se utilizan para
proporcionar explicaciones para otros tipos de anotaciones.

  • @Target: se usa para describir el alcance de uso de las anotaciones (es decir, dónde se pueden usar las anotaciones descritas)
  • @Retention: indica en qué nivel se debe guardar la información de la anotación, que se utiliza para describir el ciclo de vida de la anotación (FUENTE <CLASE <TIEMPO DE EJECUCIÓN)
  • @Document: indica que la anotación se incluirá en javadoc
  • @Inherited: indica que las subclases pueden heredar esta anotación de la clase principal
public class Test2 {
    
    
    @MyAnnotation
    public void test(){
    
    

    }
}

//定义一个自己的注解
//Target 表示这个注解可以用在哪个地方
//Retention 表示我们注解在什么地方有效
//Inherited 子类可以继承父类的注解
@Target(value = {
    
    ElementType.METHOD,ElementType.ANNOTATION_TYPE})
//runtime>class>source
@Retention(value = RetentionPolicy.RUNTIME)
@Inherited
@interface  MyAnnotation{
    
    

}

4. Anotaciones personalizadas

  • Cuando se utiliza la anotación personalizada @interface, la interfaz java.lang.annotation.Annotation se hereda automáticamente.
  • @interface se utiliza para declarar una anotación, formato: público @interface nombre de anotación {contenido de definición}.
  • Cada uno de estos métodos en realidad declara un parámetro de configuración.
  • El nombre del método es el nombre del parámetro.
  • El tipo de valor de retorno es el tipo de parámetro (el valor de retorno solo puede ser tipos básicos, Clase, Cadena, enumeración).
  • Puede declarar el valor predeterminado de un parámetro de forma predeterminada.
  • Si solo hay un miembro de parámetro, el parámetro generalmente se denomina valor.
  • Los elementos de anotación deben tener valores. Cuando definimos elementos de anotación, a menudo usamos cadenas vacías y 0 como valor predeterminado.
public class Test3 {
    
    
    //注解可以显示赋值,如果没有默认值,我们就必须给注解赋值。
    @MyAnnotation2(age=23)
    public void test1(){
    
    

    }

}
@Target({
    
    ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
    
    
    //注解的参数:参数类型+参数名();
    String name() default "";
    int age();

}

2. Reflexión

1. ¿Qué es la reflexión?
La reflexión significa que podemos cargar, detectar y usar clases en tiempo de ejecución que son completamente desconocidas durante la compilación. Es un mecanismo dinámico que nos permite dirigir la creación de instancias de programas, operar atributos y llamar a métodos a través de cadenas. Esto hace que el código sea más flexible, pero también genera una mayor sobrecarga de recursos.
Una vez cargada la clase, se genera un objeto de tipo Clase en la memoria del montón (una clase tiene solo un objeto Clase), que contiene la información estructural completa de la clase. Podemos ver la estructura de la clase a través de este objeto. Este objeto es como un espejo a través del cual podemos ver la estructura de la clase, por eso lo llamamos vívidamente reflejo.

2. ¿Cómo obtener la clase reflejada?
Primero cree una clase de entidad de usuario

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    
    
    private String id;
    public String name;
    private Integer age;
}

Obtenido a través de tres métodos.

//获取反射
public class Test1 {
    
    
    //通过Class.forName()获取(最常用)
    public static void main(String[] args) {
    
    
        try {
    
    
            Class aClass = Class.forName("com.example.dci.Reflect.pojo.User");
        } catch (ClassNotFoundException e) {
    
    
            e.printStackTrace();
        }
        //通过getClass()获取
        User  user = new User();
        Class aClass1 = user.getClass();

        //通过.class来获取
        Class<User> userClass = User.class;
    }
}

2. ¿Cómo utilizar la reflexión?

  • Obtener nombres de clases, variables, campos y métodos
public class Test2 {
    
    
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
    
    

        Class aClass = Class.forName("com.example.dci.Reflect.pojo.User");
        //获取全类名
        String name = aClass.getName();
        System.out.println(name);
        //获取简单类名
        String simpleName = aClass.getSimpleName();
        System.out.println(simpleName);
        //获取类的字段、某些变量
        //获取该类的所有public字段,包括父类的
        Field[] fields = aClass.getFields();
        for ( Field field: fields ){
    
    
            System.out.println(field.getName());
        }
        //根据字段名获取该类的public字段
        Field name1 = aClass.getField("name");
        //根据字段名获取该类的字段
        aClass.getDeclaredField("age");


    }
 Class aClass = Class.forName("com.example.dci.Reflect.pojo.User");
        //获取该类的所有public方法,包括父类的
        Method[] methods = aClass.getMethods();
        //根据方法名获取该类的public方法
        Method method = aClass.getMethod("getName");

        //如果该类为重写方法,可以在第二个参数加上重写方法的参数类型,不写为无参数的方法
        Method paramMethod = aClass.getMethod("getName",String.class);

        //获取该类的所有方法,不包括父类(仅自定义)
        Method[] declaredMethods = aClass.getDeclaredMethods();
        //根据方法名获取该类的方法
        Method declaredMethod = aClass.getDeclaredMethod("getName");
    }
  • Obtener el constructor de la clase.
//获取类的构造器
public class Test4 {
    
    
    public static void main(String[] args) throws Exception {
    
    

        Class aClass = Class.forName("com.example.dci.Reflect.pojo.User");
        //获取该类的所有构造器,包括父类
        Constructor[] constructors = aClass.getConstructors();

        //根据构造器的参数类型来获取指定构造器,不写为无参构造器
        Constructor constructor = aClass.getConstructor();
        Constructor constructor1 = aClass.getConstructor(String.class,int.class);

        //获取该类的所有构造器,不包括父类
        Constructor[] declaredConstructors = aClass.getDeclaredConstructors();

        //根据构造器的参数类型来获取指定的自定义构造器,不写为无参构造器
        Constructor declaredConstructor = aClass.getDeclaredConstructor();
        Constructor declaredConstructor1 = aClass.getDeclaredConstructor(String.class, int.class);

    }
}
  • Crear una instancia de una clase
//类的实例化
public class Test5 {
    
    
    public static void main(String[] args) throws Exception {
    
    

        Class aClass = Class.forName("com.example.dci.Reflect.pojo.User");
        //通过class类直接实例化,使用的是User类的无参构造器
        User user = (User) aClass.newInstance();
        //获取构造器来进行实例化,这里获取有参构造器
        Constructor declaredConstructor = aClass.getDeclaredConstructor(String.class,String.class,Integer.class);
        //根据构造器进行实例化
        User user1 = (User) declaredConstructor.newInstance("12", "admin",44);
        System.out.println(user1);
    }
}
  • resultado de la operación

Insertar descripción de la imagen aquí

  • Utilice emisión para llamar a métodos.
public class Test6 {
    
    
    public static void main(String[] args) throws Exception{
    
    

        Class aClass = Class.forName("com.example.dci.Reflect.pojo.User");
        User user = (User) aClass.newInstance();
        Method setName = aClass.getMethod("setName", String.class);
        //第一个是调用底层方法的对象,也就是通过哪个对象来调用方法
        //第二个为可变参数,是用于方法调用的参数
        setName.invoke(user,"admin1");
        System.out.println(user);
    }
}
  • resultado de la operación
    Insertar descripción de la imagen aquí
  • Utilice la reflexión para modificar el valor de un campo (use id.setAccessible(true) para omitir controles de seguridad)
public class Test7 {
    
    
    public static void main(String[] args) throws Exception{
    
    
        Class aClass = Class.forName("com.example.dci.Reflect.pojo.User");

        User o = (User) aClass.newInstance();
        Field id = aClass.getDeclaredField("id");
        //使用id.setAccessible(true)跳过安全检查
         id.setAccessible(true);
        //第一个参数为修改的字段的对象
        //第二个为被修改字段的新值
        id.set(o,"123");
        System.out.println(o);
    }
}
  • resultado de la operación
    Insertar descripción de la imagen aquí

3. Uso de anotaciones y reflexión.

  • La anotación es una anotación personalizada creada previamente.
//定义一个自己的注解
//Target 表示这个注解可以用在哪个地方
//Retention 表示我们注解在什么地方有效
//Inherited 子类可以继承父类的注解
@Target(value = {
    
    ElementType.METHOD,ElementType.ANNOTATION_TYPE})
//runtime>class>source
@Retention(value = RetentionPolicy.RUNTIME)
@Inherited
public @interface  MyAnnotation{
    
    
     String name() default "";
}
  • Para obtener el valor de la anotación, primero use la reflexión para obtener la clase modificada por la anotación y luego obtenga el valor de la anotación llamando a ***getDeclaredAnnotation(annotation name.class)***.
//注解与反射
public class Test8 {
    
    

    public static void main(String[] args) throws Exception {
    
    
        Class aClass = Class.forName("com.example.dci.annotation.test1");
        Method test1 = aClass.getDeclaredMethod("test2");
        MyAnnotation declaredAnnotation = test1.getDeclaredAnnotation(MyAnnotation.class);
        String value = declaredAnnotation.name();
        System.out.println(value);


    }

}

Supongo que te gusta

Origin blog.csdn.net/lzfaq/article/details/122105249
Recomendado
Clasificación