文章目录
Java注解与反射
什么是注解(Annotation)
注解的概述
注解是JDK5.0引入的技术,不是程序本身,却可以对程序作出解释和被其他程序(如:编译器)读取。
注解的格式
以 “@注释名” 在代码中存在,还可以添加数值,例如:“@SuppressWarning(value = “unchecked”)”,“@Override”。
注解的使用范围
可以附加在package,class,method,field的上面,给他们添加辅助信息,可以通过反射机制编程,实现对这些元数据的访问。
注解的类型
-
内置注解
包括了“@Override”,
“@Deprecated”,
“@SuppressWarning([para1])”,
JDK自带的注解,para1可以为 “all”或“unchecked”,“all”为镇压全部警告,加在class上则本class不会出现warning。 -
元注解(Meta-Annotation)
作用:解释或描述其他注解的注解;
种类:四个,@Targe,@Retention,@Document,@Inherited
- @Target 描述注解的使用范围,配合"ElementType.TYPE/METHOD/FIELD"使用。
- @Retention 描述注解的生命周期 (source< class < Runtime),一般框架内的注解都要写到Runtime,配合"RetentionPolicy.SOURCE/CLASS/RUNTIME"使用
- @Document 表示该注解将被包含在Java Doc中
- @Inherited 说明子类可以继承父类中的该注解
- 自定义注解
声明格式:使用 “public @interface 注解名 {定义内容}” ,自动继承java.lang.annotation.Annotation接口;
定义内容中的格式为 “ 数据类型 变量名()[default XX]”,其中如果变量名为value,在使用的时候可以省略" value = xx "直接写 “xx”即可,其他变量名不可如此。
什么是反射机制(Java Reflection)
反射机制的概述
反射机制使Java从 “静态语言” 变为 “准动态语言”,但是增加了不安全性。反射是由一个Class对象获得整个类的信息,包括构造函数,成员属性和方法。通过Class对象,Java可以实现动态加载。
动态语言
运行时代码可以根据某些条件改变自身结构,Object-C,C#,Python,PHP,JavaScript都是动态语言
静态语言
与动态语言相反,Java,C,C++
Class类
对于Java的每一个类而言,JRE都为其保留一个且唯一的对象,一个Class对象包含该类所有的相关信息,同时该类具有以下几种特点。
- Class本身即是一个类
- Class对象只能由系统建立,用户通过调用方法返回得到实例
- 一个加载的类在JVM中只会有一个实例,反复获取同一个类的实例得到的对象是同一个(可用Object.hashcode()方法证明,返回的值相同)
- 一个 “.class” 文件对应一个JVM中的class对象
- 每个类的实例都知道自己由哪个Class的实例生成(例如Class Person 生成的 Class Student)
- 通过Class对象可以得到其完整的数据结构
- Class是Java Reflection的根源,任何动态加载都要通过Class对象
- Class类常用方法:
- 获取Class类的实例的方法:
- 已知具体的类名,通过 “类名.class” 获取,该方法最安全可靠,程序性能最高
- 已知某个类的实例,通过 “实例.getClass()” 获取Class对象
- 已知类名和其项目路径,使用Class.forName(“项目路径”)获得
- 通过ClassLoader获得
- 内置基本数据类型用 “类名.Type” 获得
- 哪些类型可以获得Class对象:class,interface,[](数组),enum(枚举),annotation(注解@interface),primitive type(基本数据类型),void
Class类的加载过程
Class类什么时候会初始化
类加载器的作用
类加载器的种类
- Bootstrap Classloader (引导类加载器) 加载 rt.jar 包
- Extension Classloader (扩展类加载器) 加载ext下的jar包
- System Classloader (系统类加载器) 加载class path下的jar包
获得类的运行结构
- 获得类的名字:Class.getName()。
- 获得类的属性:Class.getFields()获得public属性;Class.getDeclaredFields()获得所有属性。
- 获得类的方法:Class.getMethods()获得本类及其父类的所有public方法;Class.getDeclaredMethods()获得本类的所有方法,包括private。
- 获得类内指定的方法:Class.getMethod(“方法名”,参数类型),参数如果是String,就是String.class,是int则为int.class。
- 获得指定的构造器:Class.getConstructor(),Class.getDeclaredConstructor(),两种使用方法同上。
- 获得类的注解:Class.getAnnotation(注解名.class),然后 " 注解名.value()" 获得注解的值
动态创建对象及其可执行的操作
了解了Class对象和加载器,我们可以获得它,有了上述的Class对象,我们能做什么?
创建类的对象
- 调用Class.newInstance()可以创建一个类的对象,条件是必须要有无参构造器,且该构造器的访问权限要够,不能为private。
- 如果没有无参构造器,通过Class类的Class.getDeclaredConstructor()取得有参构造器,然后向该构造器传递一个包含所需各个参数的对象数组,最后通过Constructor实例化对象。
通过反射操作方法
如果方法为static,invoke内的Object可以写null。如果没有形参,形参区写null。如果方法为private,调用invoke前要调用Method.setAccessible(true) 来使其可访问。
通过反射操作属性
setAccessible()方法小结
Method,Field,Constructor对象都有该方法,作用是,启动或禁止,访问安全检查,的开关。如果需要频繁的调用反射,则设置为true跳过“访问安全检查”会提高很多效率。
通过反射操作泛型
通过反射操作注解
作用:之所以要操作注解,主要是想通过读取注解内存储的信息,以后可以通过一个个对象Object,动态的在Java内生成SQL语句,从而动态的生成数据库内表格。换言之,通过注解和反射,完成类和表结构的映射关系。(什么是ORM?Object Relationship Mapping,对象关系映射;类对应数据库表结构;属性对应数据库字段结构;一个对象对应一行记录)。
获得“类注解”(注解上"@Target(ElementType.TYPE)")和其对应值:
获得类内 “变量注解” (注解上“@Target(ElementType.FIELD)”)和其对应值:
本节完。