注解和反射

注解和反射

注解annotation

概述:对程序做出解释并可被编译器读取,以@注释名的形式存在,还可添加参数值。可附加在包、类、方法、属性上面,为其增加辅助信息。

  • 内置注解

    • @Override:表示打算重写超类中的方法
    • @Deprecated:该元素不推荐使用,表示已过时(元素上会划横线)
    • @SuppressWarnings:抑制编译时的警告信息
  • 元注解:负责注解其他注解,分别有

    • @Target,描述注解的使用范围
    • @Retention,描述注解生命周期即有效范围(source源码<class<runtime运行时)
    • @Document,说明该注解被包含在javadoc
    • @Inherited,说明子类可继承父类中该注解
  • 自定义注解

    @Target({ElementType.TYPE,ElementType.METHOD}) //作用域为类、方法,属性为FIELD
    @Retention(RetentionPolicy.RUNTIME)
    public @interface myAnnotation{ //若在类中定义则去掉public
        String name() default ""; //注解的参数而非方法,可通过default来声明参数的默认值
        int age();
    }
    

    标记注解(若只有一个参数,一般名为value,且赋值时可省略参数名直接写值)

    @myAnnotation(age = 20) //若某属性无默认值,就必须在标注时赋值
    

反射

概述:反射是Java被视为准动态语言的关键,允许程序在执行期取得任何类的内部信息,并操作任意对象的内部属性和方法。

  • 反射对象

    加载完类之后,在堆内存的方法区中产生一个Class类型的对象(一个类只有一个Class对象),通过该对象就可以反射出完整的类的结构信息。

  • 获取class对象方式

    • 通过类名:类名.class
    • 通过实例对象:对象.getClass()(不同的实例对象也会获取到相同的Class对象)
    • 通过子类对象获得父类对象:子对象.getSuperClass()
    • 通过类路径:CLass.forName("路径.类名")
    • 基本内置类:包装类名.Type
    • 利用ClassLoader
  • 可获取Class对象的类型

    类、接口、数组(同种类型的数组Class对象相同,与长度无关)、注解、枚举、基本类型

  • 通过反射可获取的对象信息

    • 类名、属性(Field)、方法、构造器、注解、父类或接口,可获得所有或指定获取
    • getXxx只能获取public修饰的信息,getDeclaredXxx可获取任意
  • 通过反射对象进行操作

    • 创建对象
      • 无参:在类有无参构造器且访问权限足够的情况下,调用newInstance()方法
      • 有参:先get指定形参的构造器,再调用带参的newInstance()方法
    • 调用指定方法
      1. 通过class类的getMethod(方法名,参数类型)指定方法并获取一个Method对象
      2. 使用Method对象调用invoke(原类对象,参数值)方法对指定方法进行激活
    • setAccessible权限开关
      • 方法、属性、构造器对象都有setAccessible(false)方法
      • 设参数值为true可取消访问检测,从而可以访问私有成员
      • 性能分析:反射会降低执行效率,关闭安全检查可相对提升反射效率
  • 类加载内存分析

    • Java内存
      • 方法区中存放各类模板(class对象),包括静态变量以及常量池,是特殊的堆
      • 栈中存放引用对象名(new出来的)和一些基本数据类型的值和引用方法(main方法压在底下)
      • 堆中存放引用对象的具体信息,栈中对象会指向堆中某一地址
    1. 加载:通过类加载器将class文件字节码加载到内存中,在堆中生成代表这个类的class对象

    2. 链接:将Java类的二进制代码合并到JVM的运行状态中,分为验证、准备、解析三阶段

      ​ 准备:为类变量(static)在方法区分配内存,设置变量默认初始值

    3. 初始化:执行类构造器<clinit>()方法,执行静态代码块以及类变量赋值动作(栈中)

      • 类的主动引用会发生类初始化,如new对象、反射调用、子类引发的父类初始化
      • 类的被动引用不会发生类初始化,如子类引用父类静态变量、引用常量、数组定义引用

通过反射获取注解信息
  1. 获取该类的class对象

  2. 获得指定注解对象:class对象.getAnnotation(注解名.class)

    也可获取类的指定属性,再获取该属性的注解信息

  3. 获得注解的该属性值:注解对象.属性名()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值