1. 反射
反射是指对于任何一个Class类,在“运行的时候,都可以直接得到这个类的全部成分”。在运行时可以得到类的构造器对象,成员变量对象,成员方法对象。这种运行时动态获取类信息以及动态调用类中成分的能力称为Java语言反射机制。
反射在运行时获取类的字节码文件对象,然后可以解析类中的全部成分。反射的核心思想和关键就是:得到编译后的class文件对象。
2. 步骤
2.1 获取Class类对象
public class Test {
public static void main(String[] args) throws Exception{
//1、Class类中的一个静态方法:forName
Class c = Class.forName("com.qjz.reflectclass.Student");
System.out.println(c);
//2、类名.class
Class c1 = Student.class;
System.out.println(c1);
//3、对象.getClass();
Class c2 = new Student().getClass();
System.out.println(c2);
}
}
2.2 反射获取构造器
通过反射技术获取构造器,构造器还是用来创建对象的,如果是非public的构造器,需要打开权限进行暴力反射,然后再创建对象。
/**
* 通过类类型对象获取构造函数,注意共有私有的问题
*/
@Test
public void getConstructor() throws Exception {
Class c = Student.class;
//获取一个指定的,私有的,带参的构造器
Constructor cons = c.getDeclaredConstructor(String.class, int.class);
//Constructor constructor = c.getConstructor();获取一个共有的无参构造函数。
//打印构造函数对象属于的类,及构造函数需要的参数个数
System.out.println(cons.getName() + "====>" + cons.getParameterCount());
//通过构造器创建对象
//非public的构造器,需要打开暴力反射开关
cons.setAccessible(true);
Student s = (Student) cons.newInstance("孙行者",1001);
System.out.println(s);
}
2.3 反射获取成员变量
反射第一步得到类对象,然后从类对象中获取类的成分对象。
/**
* 通过反射获取对象成员变量
*/
@Test
public void getDeclareFields() throws Exception {
Class c = Student.class;
//拿到全部的成员变量
Field[] fields = c.getDeclaredFields();
for (Field f : fields) {
System.out.println(f.getName() + "的类型为:" + f.getType());
}
//拿到某个成员变量
Field f = c.getDeclaredField("name");
System.out.println(f.getName() + "的类型为:" + f.getType());
//为"名字"成员变量赋值
Student s = new Student();//要为名字对象赋值需现有学生对象
f.setAccessible(true);//该变量为私有变量需要开启暴力反射
f.set(s, "孙行者");
System.out.println(s);
//f是学生类的,成员变量对象中的,名字对象;
//名字对象要取值,就得交代是哪个学生对象中的“值,这里的对象为s,
//这个值是名字对象取的,所以取到名字成员变量值(总不能让 名字 去取 编号吧)
String name = (String) f.get(s);
System.out.println(name);
}
2.3 反射获取方法对象
/**
* 反射获取方法,然后调用
* @throws Exception
*/
@Test
public void getMethod() throws Exception {
Class c = Student.class;
//通过名字和参数类型确定要拿的是哪个方法。
Method m1 = c.getDeclaredMethod("studentOtherAction");
Method m2 = c.getMethod("studenAcction", int.class);
Method[] methods = c.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method.getName()+"的返回值类型为:"+method.getReturnType());
}
//触发方法的执行
Student s = new Student();
//暴力反射
m1.setAccessible(true);
m1.invoke(s);
//用一个变量接返回结果
Object result = m2.invoke(s,1);
System.out.println(result);
}