注解和反射

注解与反射

注解 Annotation

  • 注解概念
  • 内置注解
  • 元注解
  • 自定义注解

1.注解是干什么的?

  • 对程序作出解释,规范与约束程序
  • 注解可以被其他程序(如 编译器等) 读取 reflection
  • 可以使用在 包,类,方法,变量等,相当于给它们添加额外的信息-(通过反射访问)

2.内置注解(三个)

  • @Override 重写
  • @Deprecated 已过时的
  • @SuppressWarnings(value = "all") 镇压警告

3.元注解 (四个)

  • @Target @Target({ElementType.TYPE}) 注解能用在哪
  • @Retention @Retention(value = RetentionPolicy.RUNTIME) 注解作用范围
  • @Document 把注解生成在Javadoc
  • @Inherited 子类可继承父类注解

4.自定义注解

  • @Interface xxx{ 参数类型 + 参数名( ) }
  • 若只有一个参数,可使用 String value() , 这样调用注解可以直接赋值

上代码:

@myAnnotation(name = "参数类型 + 参数名()",length = 2,type = "lll",likes ={"芜","湖"} )
@myAnnotation2("直接写参数")
public static void main(String[] args) {
}

//注解能用在哪里
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD,ElementType.PACKAGE}) 
@Retention(value = RetentionPolicy.RUNTIME) //注解在哪里有效
@Documented //注解也生成javadoc文档
@Inherited //子类可继承父类注解
@interface myAnnotation{   //自定义注解 参数类型+变量名()
    String name();
    int length();
    String type();
    String[] likes();
}
@interface myAnnotation2{ //只有一个参数时 用 参数类型+value()
    String value(); 
}

反射 reflection

1.反射机制 是干嘛的?

  • 反射机制,允许程序在执行期间 借助Reflection API 获得并操作 任何类的内部信息
  • 类,对象,构造器,方法,属性,泛型信息,注解

2.类的加载

  • 加载 (把类的class文件读取到内存,生成Class对象)

  • 链接 保证代码没有错误,为 **static **变量 默认初始值

  • 初始化 static 静态变量静态方法块 赋值 ,初始化子类会先初始化其父类

    2.1 类加载器Classloader

    • 引导类 (根)加载器 java核心库 rt.jar 无法直接获取
    • 拓展类加载器 jre/lib/ext下的jar ExtClassloader
    • 系统类加载器 项目jar,最常用 AppClassloader

    2.2 类什么时候初始化

    • main方法所在类,new对象,调用static (除final) 属性/方法,调用反射子类(先初始化父类)
    • 不会初始化:子类调用父类static,数组定义类 Son[] array = new Son[5];

3.获取Class对象

  • 三种方式获取Class对象 + 基本数据类型 (类,对象,地址+类名)

    Class c1 = person.getClass(); //对象.getClass
    Class c2 = Student.class; //类.class
    Class c3 = Class.forName("com.kuang.reflection.Student"); //Class.forName("")
    Class c4 = Integer.TYPE; 
    //八大基本数据类型:Integer,Short,Long,Float,Double,Byte,Character,Boolean
    
  • 哪些类型有Class对象 (.class)

    Class c1 = Object.class;     //类
    Class c2 = Comparable.class; //接口
    Class c3 = String[].class;   //一维数组
    Class c4 = int[][].class;    //二维数组
    Class c5 = Override.class;   //注解
    Class c6 = ElementType.class; //枚举
    Class c7 = Integer.class;     //基本数据类型
    Class c8 = void.class;        //void
    Class c9 = Class.class;       //Class
    
    //只要元素类型与维度一样,就是同一个Class
    int[] a = new int[10];
    int[] b = new int[100];
    

4.创建运行时类的对象

  1. 获得类的信息

    Name,Field,Method,Constructor,SuperClass,Interface,Annotation

    // 通过reflection获取Class对象  名字/对象/类
    Class c1 = Class.forName("com.kuang.reflection.User");
    //c1 = new User().getClass();
    //c1 = User.class;
    
    //1.获得类的名字
    System.out.println(c1.getName()); //包名+类名
    System.out.println(c1.getSimpleName()); //类名
    
    //2.获得类的属性
    System.out.println("=====================");
    Field[] fields = c1.getFields(); //只能获得public属性
    fields = c1.getDeclaredFields(); //获得全部属性
    for (Field field : fields) {
        System.out.println(field);
    }
    	//获得指定属性 (属性名)
    Field name = c1.getDeclaredField("name");
    System.out.println(name);
    
    //3.获得类的方法
    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);
    }
    	//获得指定方法 方法名+参数    (?加参数-->因为重载)
    Method getName = c1.getMethod("getName", null);
    Method setName = c1.getMethod("setName", String.class);
    System.out.println("指定方法:"+getName);
    System.out.println("指定方法:"+setName);
    
    //4.获得构造器
    System.out.println("=======================");
    Constructor[] constructors = c1.getConstructors();
    for (Constructor constructor : constructors) {
        System.out.println(constructor);
    }
    constructors = c1.getDeclaredConstructors();
    for (Constructor constructor : constructors) {
        System.out.println("all:"+constructor);
    }
    	//获得指定构造器 (参数)
    Constructor constructor = c1.getConstructor(String.class, int.class, int.class);
    System.out.println("指定构造器:"+constructor);
    constructor = c1.getDeclaredConstructor(null);
    System.out.println("公共指定构造器:"+constructor);
    
  2. 创建类的 对象 newInstance()

    • 直接通过Class对象创建 (类中必须要有无参构造方法,有构造器的访问权限)
    • 通过构造器创建
    //1.Class对象直接 构造对象 newInstance
    User user = (User) c1.newInstance(); //本质 调用类的 无参构造器
    
    //2.通过构造器创建对象 (有参)
    Constructor constructor = c1.getDeclaredConstructor(String.class, int.class,int.class);
    User user2 = (User) constructor.newInstance("刘波", 001,18);
    
  3. 获取,操作 类的 方法 .invoke(对象,值)

    Method setName = c1.getMethod("setName", String.class);//先获得指定 方法
    setName.invoke(user2,"张三"); //.invoke(对象,值)
    
  4. 获取,操作 类的 属性 .set(对象,值)

    • 注:无法直接操作私有 属性/方法 , 需要关闭安全检测 .setAccessible(true)
    Field name = c1.getDeclaredField("name");
    name.setAccessible(true); //直接操作私有属性/方法 需要关闭安全检测
    name.set(user2,"李四"); // .set(对象,值)
    
  5. 关闭安全检测 .setAccessible(true)

    • Method, Field , Constructor 都有 setAccessible 方法
    • 取消java语言访问检查;提高反射效率;得以访问修改 私有成员 ;

5.反射操作注解

  1. 通过反射获取注解

    • 获取 的指定注解: (注解名).getAnotation( 注解名.class ); (注意强转)
    • 获取指定属性/方法 注解 指定属性.getAnnotation( 注解名.class );
    • 获得注解的值 .参数名()
    //获得注解的value的值
    Table_kuang table_kuang = (Table_kuang)c1.getAnnotation(Table_kuang.class);//类型强转
    System.out.println(table_kuang.value()); //.value()
    
    //获得类 (属性,方法) 指定的注解
    Field name = c1.getDeclaredField("name");//先获取属性
    Field_kuang annotation = name.getAnnotation(Field_kuang.class);//通过属性 获得注解信息
    System.out.println(annotation.columnName()); //.参数名()
    System.out.println(annotation.type());
    System.out.println(annotation.length());
    
  2. 与ORM 对象关系映射 结合

    • 注解和反射

    实例:

    import java.lang.annotation.*;
    import java.lang.reflect.Field;
    
    //利用注解和反射,完成类和表 结构的映射关系
    public class Test11 {
      public static void main(String[] args) throws Exception {
        //通过反射获取注解
        Class c1 = Class.forName("com.kuang.reflection.Student02");
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
          System.out.println(annotation);
        }
    
        //获得注解的value的值
        Table_kuang table_kuang = (Table_kuang)c1.getAnnotation(Table_kuang.class);//类型强转
        System.out.println(table_kuang.value()); //.value()
    
        //获得类 (属性,方法) 指定的注解
        Field name = c1.getDeclaredField("name");//先获取属性
        Field_kuang annotation = name.getAnnotation(Field_kuang.class);//通过属性 获得注解信息
        System.out.println(annotation.columnName()); //.参数名()
        System.out.println(annotation.type());
        System.out.println(annotation.length());
      }
    }
    
    //类名的注解
    @Target(ElementType.TYPE) //注解作用域(目标)
    @Retention(value = RetentionPolicy.RUNTIME) //注解作用范围
    @interface Table_kuang{
      String value(); //注解类型+参数名
    }
    
    //属性的注解
    @Target(ElementType.FIELD)
    @Retention(value = RetentionPolicy.RUNTIME)
    @interface Field_kuang{
      String columnName(); //列名
      String type(); //类型
      int length(); //长度
    }
    
    @Table_kuang("db_kuang")
    class Student02{
      @Field_kuang(columnName = "db_id",type = "int",length = 10)
      private int id;
      @Field_kuang(columnName = "db_age",type = "int",length = 5)
      private int age;
      @Field_kuang(columnName = "db_name",type = "varchar",length = 20)
      private String name;
    
      public Student02(){
      }
      public Student02(int id,int age,String name){
        this.id = id;
        this.age = age;
        this.name = name;
      }
    
      @Override
      public String toString() {
        return "Student02{" +
              "id=" + id +
              ", age=" + age +
              ", name=‘" + name + ‘\‘‘ +
              ‘}‘;
      }
    
      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;
      }
    }
    

注解和反射

上一篇:定义常量类


下一篇:kubeadm快速部署一套K8S集群