反射
反射是什么
在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法,所谓反射其实是获取类的字节码文件,也就是.class文件
平时我们要调用某个类中的方法的时候都需要创建该类的对象,通过对象去调用类里面的方法,反射则是一开始并不知道我要初始化的类对象是什么,自然也无法使用 new 关键字来创建对象了,在这种情况下(没有创建对象)我们都能够对它的方法和属性进行调用,我们把这种 动态获取对象信息和调用对象方法的功能称之为反射机制。
为什么要有反射
- 反射让开发人员可以通过外部类的全路径名创建对象,并使用这些类,实现一些扩展的功能。
- 反射让开发人员可以枚举出类的全部成员,包括构造函数、属性、方法。以帮助开发者写出正确的代码。
- 测试时可以利用反射 API 访问类的私有成员,以保证测试代码覆盖率。
反射操作类
一般情况下我们使用反射获取一个对象的步骤:
1、获取类的 Class 对象实例的三种方式
第一种,使用Class.forName 静态方法。
当你知道该类的全路径名时,你可以使用该方法获取 Class 类对象最常用,必须掌握。
Class classDemo = Class.forname("com.FanSe.DemoOne");
第二种,使用 .class方法。
这种方法只适合在编译前就知道操作的 Class,但是这种方法需要导入类的包,依赖性太强,所以用的比第一种稍微要少【重点】
Class classDemo = 类名.class;
第三种,使用类对象的 getClass() 方法。
这种方法已经创建了对象,那么这个时候就不需要去进行反射了,显得有点多此一举。【不常用,了解即可】
ClassDemo str = new ClassDemo();
Class clz = str.getClass();
2.获取构造方法
获取构造方法同样包含了两个 API:用于获取所有构造方法的 getDeclaredConstructors和用于获取公有构造方法的getConstructors:
// 1.获取所有声明的构造方法
Constructor[] declaredConstructorList = studentClass.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructorList) {
System.out.println("declared Constructor: " + declaredConstructor);
}
// 2.获取所有公有的构造方法
Constructor[] constructorList = studentClass.getConstructors();
for (Constructor constructor : constructorList) {
System.out.println("constructor: " + constructor);
}
运行程序,输出如下:
declared Constructor: public com.test.reflection.Student()
declared Constructor: private com.test.reflection.Student(java.lang.String)
constructor: public com.test.reflection.Student()
3.获取非构造方法
同样地,获取非构造方法的两个 API 是:获取所有声明的非构造函数的 getDeclaredMethods 和仅获取公有非构造函数的 getMethods:
// 1.获取所有声明的函数
Method[] declaredMethodList = studentClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethodList) {
System.out.println("declared Method: " + declaredMethod);
}
// 2.获取所有公有的函数
Method[] methodList = studentClass.getMethods();
for (Method method : methodList) {
System.out.println("method: " + method);
}
运行程序,输出如下:
declared Method: public void com.test.reflection.Student.setStudentAge(int)
declared Method: private java.lang.String com.test.reflection.Student.show(java.lang.String)
method: public void com.test.reflection.Student.setStudentAge(int)
method: public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
method: public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
method: public final void java.lang.Object.wait() throws java.lang.InterruptedException
method: public boolean java.lang.Object.equals(java.lang.Object)
method: public java.lang.String java.lang.Object.toString()
method: public native int java.lang.Object.hashCode()
method: public final native java.lang.Class java.lang.Object.getClass()
method: public final native void java.lang.Object.notify()
method: public final native void java.lang.Object.notifyAll()
从输出中我们看到,getMethods 方法不仅获取到了我们声明的公有方法setStudentAge,还获取到了很多 Object 类中的公有方法。这是因为我们前文已说到:Object 是所有 Java 类的父类。所有对象都默认实现了 Object 类的方法。 而getDeclaredMethods是无法获取到父类中的方法的。