定义:
反射是java中提供的一种机制,它允许我们在程序运行的时候,动态获取一个类中的基本信息,并且可以调用类中的属性、方法、构造器。
理解:
对Java中的类(八大基本类型+三个引用类型(类,接口,数组))进行抽象,将类中的属性,方法,构造器,注释等抽象出来成为一个叫做Class的类
使用对象表示:
//这个对象c就代表java中的int类型
Class c = int.class;
//判断对象c所代表的类型是否是基本类型
System.out.println(c.isPrimitive());
//获取对象c所代表的类型的名字
System.out.println(c.getName());
三种获取Class对象的方式:按需选择
使用类型名称直接获取
使用Class类中的静态方法forName获取
使用对象调用getClass方法获取
Class c1 = Student.class;
Class c2 = Class.forName("com.briup.demo.Student");
Student stu = new Student(); Class c3 = stu.getClass();
获取类基本信息
//获取类的修饰符
System.out.println(Modifier.toString(c.getModifiers()));
//获取类的名字,全限定名
System.out.println(c.getName());
//获取类的名字,简单类名
System.out.println(c.getSimpleName());
//获取类所属包的名字
System.out.println(c.getPackage().getName());
//获取类的修饰符
System.out.println(Modifier.toString(c.getModifiers()));
//获取类的父类型的名字
System.out.println(c.getSuperclass().getName());
//获取类实现的所有接口
System.out.println(Arrays.toString(c.getInterfaces()));
Class c2 = Object.class;
Class c3 = Action.class;
Class c4 = Mark.class;
Class c5 = String.class;
//判断c2代表的类型是不是c代表类型 的父类型
System.out.println(c2.isAssignableFrom(c));
//判断c3代表的类型是不是c代表类型 的父类型
System.out.println(c3.isAssignableFrom(c));
//判断c4代表的类型是不是c代表类型 的父类型
System.out.println(c4.isAssignableFrom(c));
//判断c5代表的类型是不是c代表类型 的父类型
System.out.println(c5.isAssignableFrom(c));
先获取再调用
获取:
获取类中的public修饰的属性,也包含从父类中继承过来的public属性
Field[] getFields()
Field getField(String name)
获取类中声明的属性(包含私有的),但是不能获取从父类中继承过来的属性
Field[] getDeclaredFields()
Field getDeclaredField(String name)
Class c = Class.forName("com.briup.demo.Student");
Field[] fields = c.getDeclaredFields();
for(Field f : fields){
System.out.println("属性的修饰符:"+Modifier.toString(f.getModifiers()));
System.out.println("属性的类型:"+f.getType().getName());
System.out.println("属性的名称:"+f.getName());
System.out.println("---------------------");
}
调用:
调用属性
Student stu = new Student();
Class c = stu.getClass();
//获取类中名字叫name的属性
Field f1 = c.getDeclaredField("name");
//设置私有属性可以被访问,否则报错
f1.setAccessible(true);
//用反射的方式,给指定对象的name属性赋值
//相当于之前的stu.name = "tom";
f1.set(stu,"tom");
//用反射的方式,获取这个属性的值
//相当于之前的stu.name
System.out.println(f1.get(stu));
System.out.println("----------------------");
//获取类中名字叫age的属性
Field f2 = c.getDeclaredField("age");
//用反射的方式,给指定对象的age属性赋值
//相当于之前的stu.age = 20;
f2.set(stu,20);
//用反射的方式,获取这个属性的值
//相当于之前的stu.age
System.out.println(f2.get(stu));
System.out.println("----------------------");
//获取类中名字叫num的属性
Field f3 = c.getDeclaredField("num");
//用反射的方式,给静态属性num赋值,不需要对象
//相当于之前的Student.num = 99;
f3.set(null,99);
//用反射的方式,获取这个静态属性的值,不需要对象
//相当于之前的Student.num
System.out.println(f3.get(null));
调用方法
注意, public Object invoke(Object obj, Object… args)
- obj,表示要调用哪个对象的方法,如果是静态方法,可以传null
- args,可变参数,表示要调用的方法的参数列表
- m.invoke(obj,null) 中的m,就是通过Class对象获取到的类中的某一个指定的方法
思考一下
Spring中XML文件中传入全限定类名,传入参数自动创建对象