- 反射
- 获取Class对象的三种方式
- 反射创建类对象
- 反射获取field
- 反射获取method
- 反射获取constructor
- 反射获取泛型
- 反射获取注解
- 注解
- jdk的3个内置注解
- 5个元注解:@Retention,@Target ...
- 注解的属性
- 注解的本质:Annotation接口的子接口
1. 反射概念
- 反射:在程序运行期,对于任意一个类,都能动态获取和调用它的所有方法和属性。
(1) 获取Class对象的方式(3种)
//1.Class类的静态方法+全限类名
Class cls1 = Class.forName("company.group.name.Person");
//2.类名.class
Class cls2 = Person.class;
//3.Object类中的getClass()
Person p = new Person();
Class cls3 = p.getClass();
(2)反射创建类对象(2种)
- Class的newInstance方法底层还是调用 无参构造器的newInstance()方法
- 如果该类没有无参构造器或者不是public,Class.newInstance()无法使用,会有异常
Person p = new Person();
Class cls = p.getClass();
//1.利用Class自带的newInstance()
Person p1 = (Person)cls.newInstance();
//2.先获取构造器,再创建对象
Constructor con1 = cls.getConstructor(); //调用无参
Person p2 = (Person)con1.newInstance();
Constructor con2 = cls.getConstructor(String.class, int.class); //调用有参
Person p2 = (Person)con2.newInstance(“李四”,25);
(3)反射获取field
- getFields()无法获取私有属性,只能获取 public属性 + 父类属性
- getDeclaredFields() 可以获取包括private在内的所有自定义属性(仅仅获取属性名,无法获取值或修改值)
- field.setAccessible(true):可以对private的get和set操作
Field getField(String name) //获得命名的公共字段
Field[] getFields() //获得类的所有公共字段
Field getDeclaredField(String name) //获得类声明的命名的字段
Field[] getDeclaredFields() //获得类声明的所有字段
//例子
Class cls = Person.class;
Field f = cls.getField("name");
Person p = new Person("张三",25);
Object value = f.get(p);
f.set(p, “李四”);
(4)反射获取方法
- 调用Method类的invoke()方法
Method getMethod(String name, Class[] params) //(方法名,参数1,参数2...)
Method[] getMethods() //获得类的所有public方法 + 父类方法
Method getDeclaredMethod(String name, Class[] params) //所有修饰符的方法(不含父类)
Method[] getDeclaredMethods() //所有方法(不含父类)
Class cls = Person.class;
Method eat1 = cls.getClass("eat") // 获取eat()方法
Method eat2 = cls.getClass("eat",String.class) //获取eat(String name)方法
Person p = new Person();
eat1.invoke(p); //执行p的eat()方法
eat2.invoke(p, "大饼"); //执行p的eat("大饼")方法
String name = eat1.getName(); //获取"eat"
(5)反射获取构造器
Constructor getConstructor(Class[] params) //(参数1,参数2...)
Constructor[] getConstructors()
Constructor getDeclaredConstructor(Class[] params) //所有修饰符的构造器
Constructor[] getDeclaredConstructors() //所有修饰符的构造器
Class cls = Person.class;
Constructor con1 = cls.getConstructor();
Constructor con2 = cls.getConstructor(String.class, int.class);
Person per1= (Person)con1.newInstance();
Person per2= (Person)con2.newInstance(“张三”, 25);
(6)反射获取泛型
(7)反射获取注解
- getAnnotation() 和 getDeclaredAnnotation()方法
2. 注解
- 注解作用
- 编写API文档:代码里进行注释,javadoc命令生成对应的API文档
- 编译检查:如Override检查
- 代码分析:反射
- 注解本质
public @interface MyTestAnnotation {}
(1)JDK内置注解,没啥大用处
@Override:检测该方法是否是继承自父接口
@Deprecated:标注该内容已过时,不建议使用
@SuppressWarnings:压制警告,例如在eat()方法上加上该注解,关于该方法编译阶段的警告(如never used)都不会出现
(2)元注解(5种):用来修饰注解的注解
- @Retention:它表示注解存在阶段是保留在源码(编译期),字节码(类加载)或者运行期(JVM中运行)
//@Retention(RetentionPolicy.SOURCE),注解仅存在于源码中,在class字节码文件中不包含
//@Retention(RetentionPolicy.CLASS), 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得
//@Retention(RetentionPolicy.RUNTIME), 注解会在class字节码文件中存在,在运行时可以通过反射获取到
//注:自己定义的注解一般都用RUNTIME
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTestAnnotation {
}
- @Target:它表示我们的注解作用的范围,可以是类,方法,方法参数变量等
//@Target(ElementType.TYPE) 作用接口、类、枚举、注解
//@Target(ElementType.FIELD) 作用属性字段、枚举的常量
//@Target(ElementType.METHOD) 作用方法
//@Target(ElementType.PARAMETER) 作用方法参数
//@Target(ElementType.CONSTRUCTOR) 作用构造函数
//@Target(ElementType.ANNOTATION_TYPE)作用于注解(@Retention注解中就使用该属性)
//一般比较常用的是ElementType.TYPE类型
@Target(ElementType.TYPE)
public @interface MyTestAnnotation {
}
- @Documented:它的作用是能够将注解中的元素包含到 Javadoc 中去
- @Inherited:表示它的子类也继承了父类的注解
- @Repeatable(JDK1.8加入):这个元注解修饰的注解可以同时作用一个对象多次,但是每次作用注解又可以代表不同的含义,见Reference
(3)注解的属性
- 可以有以下类型
- 8种基本数据类型
- String
- 枚举类
- 注解类
- Class类
- 以上类型的一维数组类
- 可以用default关键字设置初始化值,数组赋值时,可以用{}
- 如果只有一个属性需要赋值,且名称是value,则可以省略不写
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyTestAnnotation {
String name() default "mao";
int age() default 18;
}
@MyTestAnnotation(name = "father", age = 50)
public class Father {
}
(4)注解的本质:Annotation接口的子接口
本质:继承Annotation接口的子接口
public interface 注解名称 extends java.lang.annotation.Annotation{}
/**Annotation接口源码*/
public interface Annotation {
boolean equals(Object obj);
int hashCode();
Class<? extends Annotation> annotationType();
}
Reference
注解:https://www.jianshu.com/p/9471d6bcf4cf
2.4 注解与反射