反射是框架的灵魂
1、什么是反射?
Java反射机制:是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。
可以拿到类的字节码对象,通过字节码对象拿到这个类中所有的信息(类的信息:类名,包名,属性,构造方法,普通方法,继承来的方法)
思考:1.类的字节码对象如何拿到?
2.如何通过类的字节码对象获取类中的信息?
3.如何使用获取到的对象中的信息?
使用反射的步骤:
1.拿到类的字节码对象
2.取出类中信息
3.使用类的信息
2.反射的使用
Java反射机制就是获取类的信息,即获取类的字节码文件的内容,并将这些内容封装到一个字节码对象中,所以我们只需要使用反射的代码获取字节码对象,就能拿到类的信息了。
3.Class类简介
Class代表类的实体,在运行的Java应用程序中表示类和接口。
获取Class的三种方法:
Class.forName(“全类名”);
对象。getClass();
类名.class;
获取类的基本信息的方法:
getName() 获取类的完整路径名字
newInstance() 创建类的实例
getPackage() 获取类的包
getSimpleName() 获得类的名字
getSuperclass() 获得当前类继承的父类的名字
getInterfaces() 获得当前类实现的类或是接口
获取类中属性相关的方法
getField(String name) 获得某个公有的属性对象
getFields() 获得所有的属性对象
getDeclaredField(String name) 获得某个属性对象
getDeclaredFirlds() 获得所有属性对象
获得类中注解相关的方法
getAnnotation(Class<A> annotationClass) 返回该类中与参数类型匹配的公有注解对象
getAnnotations() 返回该类所有的公有注解对象
getDeclaredAnnotation(Class<A> annotionClass) 返回该类中与参数类型匹配的所有注解对象
getDeclaredAnnotations() 返回该类所有的注解对象
获得类中构造器相关的方法
getConstructor(Class...<?> parameterTypes) 获得该类中与参数类型匹配的公有构造方法
getConstructors() 获得该类的所有构造方法
getDeclaredConstructor(Class...<?> parameterTypes) 获得该类中与参数类型匹配的构造方法
getDeclaredConstructors() 获得该类所有构造方法
获得类中方法相关的方法
getMethod(String name,Class<?>...parameterTypes) 获得该类某个公有的方法//String name 表示方法名,,type表示类型.class
getMethods() 获得该类所有公有的方法
getDeclareMethod(String name,Class<?>...parameterTypes) 获得该类某个方法
getDeclaredMethods() 获得该类所有方法
获取类的字节码对象—三种方式
根据类的全类名获取
class.forName(“全类名”)
通过类名获取字节码对象
类名.class
通过类的实例对象获取字节码对象
类名 变量名=new 类名();
变量名.getclass();
public static void main(String[] args) throws Exception {
//三种方式
//1.Class.forName("全类名"); 获取 类的字节码对象 通过类路径
Class pClass1 = Class.forName("com.qy129.reflex.demo1.People");
System.out.println(pClass1);
//2.类名.class
Class pClass2 = People.class;
System.out.println(pClass2);
//3.通过 对象.getClass();
People people = new People();
Class pClass3 = people.getClass();
System.out.println(pClass3);
System.out.println(pClass1 == pClass2);//true
System.out.println(pClass1 == pClass3);//true
//三种方式获取的字节码对象是相同的
}
4、根据类的字节码对象获取类的信息,并使用。
获取并调用类的构造函数
public void test1() throws Exception {
//1.获取类的字节码对象
Class pClass = People.class;
//2.获取字节码对象中的构造信息
Constructor constructor = pClass.getConstructor(int.class);
System.out.println(constructor);
//通过从类的字节码对象中获取到的构造器 调用newInstance方法 并且传入需要的参数 创建实例对象
People o = (People) constructor.newInstance(5);
System.out.println(o);
Constructor constructor1 = pClass.getConstructor(int.class, String.class);
System.out.println(constructor1);
Constructor constructor2 = pClass.getConstructor(int.class, String.class, String.class);
System.out.println(constructor2);
//通过从类的字节码对象中获取到的构造器 调用newInstance方法 并且传入需要的参数 创建实例对象
Object o1 = constructor2.newInstance(18, "张三", "男");
System.out.println(o1);
//获取所有的公有(public)构造
Constructor[] constructors = pClass.getConstructors();
System.out.println(Arrays.toString(constructors));
//不考虑构造的修饰符 获取构造器
//单个的
Constructor declaredConstructor = pClass.getDeclaredConstructor(String.class, String.class);
System.out.println(declaredConstructor);
//获取所有的构造器
Constructor[] declaredConstructors = pClass.getDeclaredConstructors();
System.out.println(Arrays.toString(declaredConstructors));
//pClass.newInstance(); 默认调用无参空构造方法
Object o2 = pClass.newInstance();
System.out.println(o2);
}
注意:不获取无参空构造,直接使用代码 字节码对象.newInstance();
就默认调用无参空构造。
获取并调用类的属性
Field类:Firld代表类的成员变量(成员变量也称为类的属性)
get(Object obj) 获得obj中对应的属性值
set(Object obj,Object value) 设置obj中对应属性值
setAccessible(boolean b) 忽略权限修饰符,如果成员变量是私有的,需要开启
获取并调用类的普通方法
Method类代表类的方法
invoke(Object obj,Object… args) 传递object对象及参数调用该对象对应的方法
获取注解信息
/**
* 获取注解信息
*/
@Test
public void test4() throws Exception{
//1.获取类的字节码对象
Class<People> pClass = People.class;
//2.获取注解的信息
//获取到注解对象
Annotation annotation1 = pClass.getAnnotation(MyAnno.class);
System.out.println(annotation1);
//将Annotation类型的注解对象强转成我们使用的 子类类型
MyAnno myanno = (MyAnno) pClass.getAnnotation(MyAnno.class);
System.out.println(myanno);
System.out.println(myanno.value());
}
注意:如果想取出注解中设置的值 需要把获取到的Annotation对象强转成,自己所使用的注解对象