注解与反射

Quinn / 2023-08-14 / 原文

注解与反射

1. 注解

1.1 内置注解

@SuppressWarnings("all")
String name;

1.2 元注解

  1. 负责解释其他注解

  2. @Target:表示注解可以用在哪些地方(class,method...)

  3. @Retention:表示注解在什么地方有效。

    runtime>class>sources

  4. @Documented:表示是否将我们的注解生成在javadoc中

  5. @Inherited:表示子类可以继承父类

package demo01;

import java.lang.annotation.*;

//元注解
public class AnnotationDemo01 {
    public static void main(String[] args) {

    }
    @MyAnnotation
    public void test(){

    }
}
//定义注解

@Target(value = {ElementType.METHOD,ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME) 
@Documented
@Inherited
@interface MyAnnotation{

}

1.3 自定义注解

package demo01;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

public class AnnotationDemo02 {
    //@MyAnnotation2(name = "quinn")
    @MyAnnotation2()
    public void test(){
        
    }

    @MyAnnotation3("quinn")
    public void test2(){

    }
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
    //注解的参数:参数类型 + 参数名() 
    //String name();
    String name() default "";
    int age() default 0;
    int id() default -1;//-1代表不存在
    String[] school() default {"清华大学"};
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation3{
    //一个值可以用value命名
    String value();
}

2. 反射

2.1 概述

  1. 动态语言:可以改变类的结构

    静态语言:运行时结构不可改变

  2. 正常方式:引入需要的包类名称 -->通过new实例化 -->取得实例化对象

​ 反射方式:实例化对象 -->getClass()方法 -->得到完整的包类信息

  1. 优点:可以实现动态创建对象,体现很大的灵活性

    缺点:对性能有影响

2.2 获得反射对象

package reflection.demo01;

public class ReflectionDemo01 {
    public static void main(String[] args) throws ClassNotFoundException {
        //通过反射获取类的class对象
        Class c1 = Class.forName("reflection.demo01.Student");
        System.out.println(c1);
        //一个类在内存中只有一个class对象
        //一个类被加载之后,类的整个结构都会被封装在class对象中
        Class c2 = Class.forName("reflection.demo01.Student");
        Class c3 = Class.forName("reflection.demo01.Student");
        Class c4 = Class.forName("reflection.demo01.Student");
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());
        System.out.println(c4.hashCode());
    }

}
//实体类:pojo,entity
class Student{
    private int id;
    private int sge;
    private String name;

    public Student() {
    }

    public Student(int id, int sge, String name) {
        this.id = id;
        this.sge = sge;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getSge() {
        return sge;
    }

    public void setSge(int sge) {
        this.sge = sge;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", sge=" + sge +
                ", name='" + name + '\'' +
                '}';
    }
}

2.3 得到Class类的方法

package reflection.demo01;

public class ReflectionDemo02 {
    public static void main(String[] args) throws ClassNotFoundException {
        Person student = new Student();
        System.out.println("这个是:"+student.name);

        //1. 通过对象获得
        Class c1 = student.getClass();
        System.out.println(c1.hashCode());
        //2. forName()
        Class c2 = Class.forName("reflection.demo01.Student");
        System.out.println(c2.hashCode());
        //3. 通过类名.class获得
        Class c3 = Student.class;
        System.out.println(c3.hashCode());
        //4. 通过包装类的TYPE属性获得
        Class c4 = Integer.TYPE;
        System.out.println(c4.hashCode());
        //获得父类类型
        Class c5 = c1.getSuperclass();
        System.out.println(c5.hashCode());
    }
}
class Person{
    String name;

    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}
class Student extends Person{
    public Student() {
        this.name = "学生";
    }
}
class Teacher extends Person{
    public Teacher() {
        this.name = "老师";
    }
}


2.4 类加载内存分析

package reflection.demo02;

public class Test01 {
    public static void main(String[] args) {
        A a = new A();
        System.out.println(a.m);
    }
}

class A{
    static {
        System.out.println("这是A类静态代码块");
        m = 300;
    }
    static int m = 100;

    public A(){
        System.out.println("A类无参构造初始化");
    }
}

image

2.5 类加载器

package reflection.demo03;

public class ReflectionDemo01 {
    public static void main(String[] args) throws ClassNotFoundException {
        //获得系统类的加载器
        ClassLoader loader = ClassLoader.getSystemClassLoader();
        System.out.println(loader);

        //获得系统类加载器的父类加载器-->扩展类加载器
        ClassLoader parent = loader.getParent();
        System.out.println(parent);

        //获得扩展类加载器的父类加载器-->跟加载器(c/c++)
        ClassLoader parent1 = parent.getParent();
        System.out.println(parent1);

        //获得当前类的加载器
        ClassLoader classLoader = Class.forName("reflection.demo03.ReflectionDemo01").getClassLoader();
        System.out.println(classLoader);

        //jdk内置的类加载器
        ClassLoader classLoader1 = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(classLoader1);
    }
}

2.6 类的运行时结构

package reflection.demo03;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectionDemo02 {
    public static void main(String[] args) throws Exception  {
        Class c1 = Class.forName("reflection.demo01.Student1");

        System.out.println(c1.getName());//获得包名+类名
        System.out.println(c1.getSimpleName());//获得类名
        System.out.println("==========================");

        //获得类的属性
        Field[] fields = c1.getFields();
        for (Field field : fields) {
            System.out.println(field);//只能获得public属性
        }
        fields = c1.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("==========================");

        //获得当前属性的值
        Field name = c1.getDeclaredField("name");
        System.out.println(name);
        System.out.println("==========================");

        //获得类的方法
        Method[] methods = c1.getMethods();//获得本类及其父类全部public方法
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("==========================");
        methods = c1.getDeclaredMethods();//获得本类的所有方法
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("==========================");

        //获得指定方法
        Method getName = c1.getMethod("getName", null);
        Method setName = c1.getMethod("setName", String.class);
        System.out.println(getName);
        System.out.println(setName);
        System.out.println("==========================");

        //获得指定的构造器
        Constructor[] cs = c1.getConstructors();
        for (Constructor c : cs) {
            System.out.println(c);
        }
        cs = c1.getDeclaredConstructors();
        for (Constructor c : cs) {
            System.out.println(c);
        }
        System.out.println("==========================");
    }
}

2.7 动态创建对象

package reflection.demo03;


import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectionDemo03 {
    public static void main(String[] args) throws Exception {
        Class c1 = Class.forName("reflection.demo03.Student1");

        //通过无参构造
        Student1 o = (Student1) c1.newInstance();
        System.out.println(o);
        System.out.println("==========================");

        //通过构造器创建对象
        Constructor constructor = c1.getDeclaredConstructor(int.class, int.class, String.class);
        Student1 s2 = (Student1) constructor.newInstance(1, 12, "quinn");
        System.out.println(s2);
        System.out.println("==========================");

        //通过反射调用普通方法
        Student1 s3 = (Student1) c1.newInstance();
        Method setName = c1.getDeclaredMethod("setName", String.class);
        setName.invoke(s3,"quinn");//激活
        System.out.println(s3.getName());
        System.out.println("==========================");

        //通过反射操作属性
        Student1 s4 = (Student1) c1.newInstance();
        Field name = c1.getDeclaredField("name");
        //关闭安全检测检测,操作private属性
        name.setAccessible(true);
        name.set(s4,"morita");
        System.out.println(s4.getName());

    }
}

2.8 操作泛型

package reflection.demo03;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

public class ReflectionDemo04 {
    public void test1(Map<String,Student1> map, List<Student1> list){
        System.out.println("test1");
    }
    public Map<String,Student1> test2(){
        System.out.println("test2");
        return null;
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method m1 = ReflectionDemo04.class.getMethod("test1", Map.class, List.class);
        //获得泛型参数类型
        Type[] t1 = m1.getGenericParameterTypes();
        for (Type type : t1) {
            System.out.println("##"+type);
            //是否是一种参数化类型
            if (type instanceof ParameterizedType){
                //获得真实参数信息
                Type[] types = ((ParameterizedType) type).getActualTypeArguments();
                for (Type type1 : types) {
                    System.out.println(type1);

                }
            }
        }
        System.out.println("======================");
        Method m2 = ReflectionDemo04.class.getMethod("test2",null);
        //获得返回参数类型
        Type returnType = m2.getGenericReturnType();
        if (returnType instanceof  ParameterizedType){
            Type[] typeTemp = ((ParameterizedType) returnType).getActualTypeArguments();
            for (Type type : typeTemp) {
                System.out.println(type);
            }
        }

    }
}

2.9 获取注解信息

package reflection.demo03;

import java.lang.annotation.*;
import java.lang.reflect.Field;

//反射操作注解
public class ReflectionDemo05 {

    public static void main(String[] args) throws Exception {
        Class<?> c1 = Class.forName("reflection.demo03.User");
        //通过反射获得注解
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
        //获得注解value的值
        TableQuinn table = c1.getAnnotation(TableQuinn.class);
        System.out.println(table.value());

        //获得类指定的注解的值
        Field field = c1.getDeclaredField("id");
        FiledQuinn filedQuinn = field.getAnnotation(FiledQuinn.class);
        System.out.println(filedQuinn.colName());
        System.out.println(filedQuinn.type());
        System.out.println(filedQuinn.len());
    }
}
@TableQuinn("db_user")
class User{
    @FiledQuinn(colName = "db_id",type = "int",len = 10)
    private int id;
    @FiledQuinn(colName = "db_age",type = "int",len = 10)
    private int age;
    @FiledQuinn(colName = "db_name",type = "varchar",len = 3)
    private String name;

    public User(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }

    public User() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

//类名注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableQuinn{
    String value();
}

//属性注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FiledQuinn{
    String colName();
    String type();
    int len();
}