Java基础13-注解和反射

注解和反射

注解和反射是Java框架的重要基础,需要在框架的学习中进一步加深理解。

Annotation注解

与注释Comment区分

Java注解用于为Java代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。Java注解是从Java5开始添加到Java的。
注解有三类:内置注解、自定义注解和元注解。内置注解就是java自带的注解,元注解是用于修饰注解的注解,使用元注解来定义自定义注解。

内置注解

@Overwrite:限定重写父类方法,该注解只能运用于方法
@Deprecated:用于表示某个程序元素(类,方法等)已过时
@SuppressWarnings:抑制编译器警告

自定义注解,如下例

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
    String name() default "MyAnnotation";

    int id() default -1;

    String[] paras() default {"参数类型", "参数名()"};
}

用@interface声明一个注解
注解的属性需要在使用注解时进行赋值,赋值的方式(属性名=属性值,属性名=属性值)
使用default关键字可以在定义注解时给属性赋予一个默认值如果注解中只有一个属性需要被复制,如果这个属性的名字叫做value,则在赋值时可以省去value=
注解的属性必须是 基本数据类型、String、Class、枚举、其他注解和以上数据类型的一维数组

元注解

最常用的元注解是@Target和@Retention。如上例,@Target用来修饰注解的使用范围,通过@Target里面的参数确定范围;@Retention用来修饰注解存在的时段。

@Target参数类型只能为ElementType,有以下几种:

  • @Target(ElementType.TYPE) 作用接口、类、枚举、注解
  • @Target(ElementType.FIELD) 作用属性字段、枚举的常量
  • @Target(ElementType.METHOD) 作用方法
  • @Target(ElementType.PARAMETER) 作用方法参数
  • @Target(ElementType.CONSTRUCTOR) 作用构造函数
  • @Target(ElementType.LOCAL_VARIABLE)作用局部变量
  • @Target(ElementType.ANNOTATION_TYPE)作用于注解(@Retention注解中就使用该属性)
  • @Target(ElementType.PACKAGE) 作用于包
  • @Target(ElementType.TYPE_PARAMETER) 作用于类型泛型,即泛型方法、泛型类、泛型接口 (jdk1.8加入)
  • @Target(ElementType.TYPE_USE) 类型使用.可以用于标注任意类型除了 class (jdk1.8加入)
    一般比较常用的是ElementType.TYPE类型

@Retention参数类型只能为RetentionPolicy,有以下几种:

  • @Retention(RetentionPolicy.SOURCE),注解仅存在于源码中,不包含在class字节码文件中
  • @Retention(RetentionPolicy.CLASS), 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得
  • @Retention(RetentionPolicy.RUNTIME), 注解会在class字节码文件中存在,在运行时可以通过反射获取到
    如果是自定义注解,则通过前面分析,自定义注解如果只存着源码中或者字节码文件中就无法发挥作用,而在运行期间能获取到注解才能实现我们目的,所以自定义注解中肯定是使用 @Retention(RetentionPolicy.RUNTIME)

其他元注解
@Documented - 标记这些注解是否包含在用户文档中。
@Inherited - 一个被@Inherited注解了的注解修饰了一个父类,如果他的子类没有被其他注解修饰,则它的子类也继承了父类的注解。
@Repeatable - Repeatable的英文意思是可重复的。顾名思义说明被这个元注解修饰的注解可以同时作用一个对象多次,但是每次作用注解又可以代表不同的含义。

@SafeVarargs - Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。
@FunctionalInterface - Java 8 开始支持,标识一个匿名函数或函数式接口。
@Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次。

反射

给与Java动态语言特性

动态语言和静态语言:

动态语言是一类可以在运行时改变其结构的语言。例如:JavaScript、Python。
静态语言是运行时结构不可变的语言。例如:Java、C、CPP

反射Reflection

反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。

Class c = Class.forName("java.lang.String")

反射机制提供的功能
在运行时判断对象的类
在运行时构造任意类的对象
在运行时判断任意类的成员变量和方法
在运行时获取泛型在运行时调用任意对象的成员变量和方法
在运行时处理注解
生成动态代理

优缺点:灵活,慢

相关类
java.lanng.Class
java.lang.reflect.Method
java.lang.reflect.Field
java.lang.reflect.Constructor

Class类常用方法
static ClassofrName(String name)
Object newInstance()
getName()
Class getSuperClass()
Class[] getinterfaces()
ClassLoader getClasssLoader()
Constructor[] getConstructors()
Method getMethod(String name,Class..T)
Field[] getDeclarderFields()

获取类的完整对象
Field、Method、Constructor、Superclass、Interface、Annotation

创建类的对象
有无参构造方法及其权限:newInstance()
无条件
通过Class类的getDeclaredConstructor(Class...parameterTypes)获取有参构造器
通过Constructor实例化对象

调用指定方法
getMethod(String name, Class...parameterTypes)
Object invoke(Object obj, Object[] args)

访问private方法和属性:调用setAccessible(true)

反射操作注解
getAnnotations
getAnnotaion

posted @ 2021-01-18 08:48  tanjr  阅读(101)  评论(0编辑  收藏  举报