Reflection(反射)是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说“自审”,也有称作“自省”。反射非常强大,它甚至能直接操作程序的私有属性。我们前面学习都有一个概念,private的只能类内部访问,外部是不行的,但这个规定被反射赤裸裸的打破了。
反射就像一面镜子,它可以在运行时获取一个类的所有信息,可以获取到任何定义的信息(包括成员变量,成员方法,构造器等),并且可以操纵类的字段、方法、构造器等部分。
为什么需要反射:
好好的我们new User(); 不是很好,为什么要去通过反射创建对象呢?那我要问你个问题了,你为什么要去餐馆吃饭呢?例如:我们要吃个牛排大餐,如果我们自己创建,就什么都得管理。
好处是,每一步做什么我都很清晰,坏处是什么都得自己实现,那不是累死了。牛接生你管,吃什么你管,屠宰你管,运输你管,冷藏你管,烹饪你管,上桌你管。就拿做菜来说,你能有特级厨师做的好?
那怎么办呢?有句话说的好,专业的事情交给专业的人做,饲养交给农场主,屠宰交给刽子手,烹饪交给特级厨师。那我们干嘛呢?
我们翘起二郎腿直接拿过来吃就好了。再者,饭店把东西做好,不能扔到地上,我们去捡着吃吧,那不是都成原始人了。那怎么办呢?很简单,把做好的东西放在一个容器中吧,如把牛排放在盘子里。
在开发的世界里,spring就是专业的组织,它来帮我们创建对象,管理对象。我们不在new对象,而直接从spring提供的容器中beans获取即可。Beans底层其实就是一个Map
总结一句,类不是你创建的,是你同事或者直接是第三方公司,此时你要或得这个类的底层功能调用,就需要反射技术实现。有点抽象,别着急,我们做个案例,你就立马清晰。
反射Class类对象
- Class.forName(“类的全路径”);
- 类名.class
- 对象.getClass();
常用方法
!!成员变量定义信息
!!构造方法定义信息
方法定义信息
反射新建实例
反射调用成员变量
反射调用成员方法
创建类
class Student{
String name="jack";
int age=20;
public Student() {
System.out.println("无参构造");
}
public Student(String name) {
this.name=name;
System.out.println("含参构造"+name);
}
public void show(int a) {
System.out.println("show()..."+a);
}
}
获取类对象
private static void method() throws Exception {
Class clazz = Student.class;
Class<?> clazz2 = Class.forName("seday15.Student");
Class clazz3 = new Student().getClass();
System.out.println(clazz.getName());
System.out.println(clazz2.getName());
System.out.println(clazz3.getName());
}
获取构造方法
private static void method3(Class clazz) {
Constructor[] cs = clazz.getDeclaredConstructors();
for (Constructor c : cs) {
String name = clazz.getSimpleName();
System.out.println(name);
Class[] cs2 = c.getParameterTypes();//参数
System.out.println(Arrays.toString(cs2));
}
}
获取成员方法
private static void method4(Class clazz) {
Method[] ms = clazz.getMethods();
for (Method m : ms) {
String name = m.getName();
System.out.println(name);
Class<?>[] cs = m.getParameterTypes();
System.out.println(Arrays.toString(cs));
}
}
获取成员变量
private static void method2(Class clazz) {
Field[] fs = clazz.getFields();//获取public的属性
for (Field f : fs) {
String name = f.getName();
String tname = f.getType().getSimpleName();
System.out.println(name);
System.out.println(tname);
}
}
我们再来说说暴力反射,什么是暴力反射呢?Java中有许多的方法和对象为了安全考虑,都被封装在类中。通常这些私有的方法和对象都只能在该类的内部进行调用,对于外部的类来说,都是隐藏、不可见的。为了能够在外部类中获取和操作这些私有的对象和方法,就可以使用暴力反射的方式来实现。简单来讲就是指可以将程序中的私有的属性或者方法通过反射技术,暴力的获取到资源。
创建Person类
class Person{
private String name="jack";
private int age = 30;
private void show(int[] a) {
System.out.println("show()..."+Arrays.toString(a));
}
private void test() {
System.out.println("test()...");
}
}
看以上这个例子,成员变量和成员方法都是私有的,那么我们将如何获取它的值呢?我们来测试一下
package seday16new;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectPerson {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("seday16new.Person");
// method(clazz);//隐私属性
method2(clazz);//执行方法
}
private static void method2(Class<?> clazz) throws Exception {
Method m = clazz.getDeclaredMethod("show", int[].class);
Object obj = clazz.newInstance();
m.setAccessible(true);//方法隐私可见
m.invoke(obj, new int[]{1,2,3});//执行
}
private static void method(Class clazz) throws Exception {
Field f = clazz.getDeclaredField("name");
System.out.println(f.getType().getName());
f.setAccessible(true);//属性隐私可见
Object obj = clazz.newInstance();
// f.set(obj, "rose");//设置值
System.out.println(f.get(obj));//获取值
//---所有属性
Field[] fs = clazz.getDeclaredFields();
for (Field ff : fs) {
System.out.println(ff);
ff.setAccessible(true);//暴力反射
System.out.println(ff.get(obj));
}
}
}
结果: