注解和反射
什么是注解
-
Annotation是从JDK5开始引入的,作用是对程序做出解释,但并不是程序本身,可以被其他程序读取。
-
Annotation的格式是:@注释名,也可以添加一些参数值
-
在哪里使用:可以附加在package、class、method、field等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制编程实现对元素的访问
内置注解
例:
-
@Override:重写类注解,定义在java.lang.Override中,声明一个方法打算重写超类另一个方法
//重写toString 方法 @Override public String toString(){ return super.toString(); }
注解一般都是定义在java.lang包中的
元注解
元注解作用是负责注解其他的注解,java定义了4个标准的meta-annotation类型用来提供解释说明
- @Target:用于描述注解的适用范围
- @Retention:表示需要在什么级别保存该注释信息,用于描述注解的生命周期
- @Document:说明该注解将被包含在javadoc中
- @Inherited:说明子类可以继承父类中的该注解
自定义注解
-
使用@interface自定义注解,箱单关于自动继承一个java.lang.annotation.Annotation
@Target({ElementType.ANNOTATION_TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface CeShi{ //注解的参数:参数类型 + 参数名() String name (); //可以设置默认值,设置后如果没有赋值则使用默认参数 int age() default 0; } @Target({ElementType.ANNOTATION_TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @interface CeShi{ //如果是只要一个参数可以使用value代替,并且调用时的value可以省略 String value(); }
反射机制
java反射机制概述
-
Reflection(反射)是java被视为动态语言的关键,反射机制允许程序在执行期间借助与Reflection API取得任何类的内部信息,并直接操作任何对象的内部属性及方法。
-
当类加载完成后,在堆内存的方法区中就产生了一个Class类型的对象,这个对象就包含了完整的类的结构信息。我们可以通过对象看到类的结构。
正常方式:引入需要的包类名称——通过new实例化——取得实例化对象
反射方式:实例化对象——getClass()方法——得到完整的包名称
优缺点:
- 优点:可以实现动态创建对象和编译,灵活性好
- 缺点:对性能有影响
反射相关的主要API
-
java.lang.Class:代表一个类
-
java.lang.reflect.Method:代表类的方法
-
java.lang.reflect.Field:代表类的成员变量
-
java.lang.reflect.Constructor:代表类的构造器
//新建一个实体类来进行测试 //通过反射创建 Class c = Class.forName("Annotation.User");//需要传入类所在的位置 System.out.println(c); Class c1 = Class.forName("Annotation.User"); Class c2 = Class.forName("Annotation.User"); //创建多个对象比较会相等,因为一个类在内存中只有一个Class对象 //一个类被加载后,类的整个结构都会被封装在Class对象中 System.out.println(c1.hashCode()); System.out.println(c2.hashCode());
Class类:
获取Class类的的实例的方式:
-
如果已知具体的类,通过类的class属性获取,该方法比较可靠:Class c = Person.class;
-
已知某个类的实例,调用该实例的getClass()方法获取Class对象:
Class c = person.getClass;
-
已知一个类的全类名,且该类在类的路径下,可以通过Class的静态方法forName()huoqu
Class c = Class.forName(“类所在位置”)
那些类有class对象
- class:外部类,成员内部类,局部内部类,匿名内部类
- interface:接口
- 【】:数组
- enum:枚举
- annotation:注解@interface
- primitive type :基本数据类型
- void
Class c = Object.class;//类
Class c1 = Comparable.class;//接口
Class c2 = String[].class;//数组
Class c3 = Override.class;//注解
Class c4 = ElementType.class;//枚举
Class c5 = Integer.class;//数据类型
Class c6 = void.class;//void
Class c7 = Class.class;//Class
只要元素类型一样,其底层的Class都相同
获得类的信息
- Class.getName():获得包名和类名
- Class.getSimpleName():获得类名
- Class.getFields():只能获得public的属性
- Class.getDeclaredFields():可以获得全部类的属性
- Class.getDeclaredField():获得指定属性的值
- Class.getMethods():获得本类及父类的方法。
- Class.getDeclaredMethods():获得本类的方法
- Class.getMethod(参数):获得指定的方法。
- Class.getConstructors():获得构造器
- Class.getDeclaredConstructors():获得全部的构造器
- Class.getDeclaredConstructor(参数):获得指定的构造器