Java反射
反射的原理
在我们编写好一个Java程序后,这个程序并不是直接就可以在机器上运行,而是需要编译器将程序编译为字节码(.class文件),然后通过JVM解释器,将字节码解释为具体系统可以读懂的数据。反射就是直接从字节码中提取信息。这也是Java一次编写,到处运行的原理。
反射的使用
反射主要基于class包,使用Class包中的一个静态方法Class.forName来加载类
//User是我们自己设置的类
//加载需要完整的包名
Class<User> mClass = (User) Class.forName("com.company.User")
这样我们就得到了一个Class对象(注意,是class对象,而不是User对象),这里还有一点就是,一个具体类的class对象,只会存在一个。
随后可以使用这个class对象来构建一个user对象
//Java已经过时的方法
User user = mClass.newInstance();
//Java目前推荐的方法
User user = (User) mClass.getConstructor().newInstance();
但是这并不是反射的主要作用,反射的主要目的是获取类中私有的对象。
获取类中的对象
获取类中对象有两种方法
//第一种方法会返回所有可以访问的参数
Field[] fields = mClass.getFields();
//第二种方法会返回所有参数,不论是否有权限访问
Field[] fields1 = mClass.getDeclaredFields();
//还可以指定返回参数,参数是目标的变量名
Field field = mClass.getField("name");
//同样也有declared方法
Field field1 = mClass.getDeclaredField("name");
获取到field后,我们可以通过一些内置方法得到参数的相关信息
for (Field field : fields1) {
System.out.println(Modifier.toString(field.getModifiers()) + " " +
field.getGenericType().toString() + " " +
field.toString());
}
获取类中的方法
//获取方法对象,getMrthods获取的方法包括了父类的方法
Method[] methods = mClass.getMethods();
//与上面类似,但没有父类方法
Method[] methods1 = mClass.getDeclaredMethods();
//获取构造方法
Constructor[] constructors = mClass.getDeclaredConstructors();
Constructor[] constructors1 = mClass.getConstructors();
使用获取到的方法
在使用获取到的方法之前,需要先创建对象,创建对象的方法在上面已经介绍过了。获取到对象和方法后,可以使用invoke方法来执行目标方法
//创建一个对象,后面是使用构造方法时传入的参数
User user = (User) mClass.getConstructor(int.class, String.class, String.class).newInstance(1, "hyb", "123456");
//通过方法名和参数获取方法对象,这里需要参数的原因是有重载
Method method = mClass.getMethod("print", String.class);
//运行方法,这里需要绑定对象和传入参数
method.invoke(user, "Use this method by reflection");
修改获取到的对象
获取到的对象有时需要修改,方法步骤见下
User user = (User) mClass.getConstructor(int.class, String.class, String.class).newInstance(1, "hyb", "123456");
Field field = mClass.getDeclaredField("name");
field.setAccessible(true);
field.set(user, "my name is xxx");
System.out.print(user.getName());