反射机制
概念:
反射是Java的特征之一,是一种间接操作目标对象的机制,核心是JVM在运行状态的时候才动态加载类,对于任意一个类都能够知道这个类所有的属性和方法,并且对于任意一个对象,都能够调用它的方法/访问属性。这种动态获取信息以及动态调用对象方法的功能成为Java语言的反射机制。通过使用反射我们不仅可以获取到任何类的成员方法(Methods)、成员变量(Fields)、构造方法(Constructors)等信息,还可以动态创建Java类实例、调用任意的类方法、修改任意的类成员变量值等。
解释:
下图是java运行的一个流程图:

类文件会被javac编译成class文件 不过值得注意的是class文件还会自动生成一个Class对象 里面有各种变量和方法
1 2 3
| fields[]:存了你定义的各种变量。 methods[]:存了你写的各种方法。 constructors[]:存了构造函数。
|
一旦你拿到了Class对象你就可以用Class对象中的获取成员变量Field,成员方法Method和构造方法Constructor等方法,再去动态获取一个类或者调用一个类的属性,变量,构造方法等方式。
反射机制本质是带给我们便利,但是便利可能就会带来安全隐患,所以我们可以使用Java的反射机制来绕过一些安全权限机制检查以及一些操作。
获取Class对象的方法
1.通过类名来获取
1
| Class p1 = People.class;
|
2.通过getClass()方法来获取
不过前提是得有一个对象
1 2
| Peole p2 = new People(); Class c2 = p2.getClass();
|
3.通过动态加载类
调用Class类中的forName()方法
1 2
| Class c3 = Class.forName("com.reflectdemo.ReflectDemo");
|
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class ReflectTemo { public static void main(String[] args) throws ClassNotFoundException { Class c1 = ReflectTemo.class; System.out.println("c1: " + c1.getName());
ReflectTemo demo = new ReflectTemo(); Class c2 = demo.getClass(); System.out.println("c2: " + c2.getName());
Class c3 = Class.forName("ReflectTemo"); System.out.println("c3: " + c3.getName()); } }
|
获取filed
1 2 3 4 5 6 7
| Field[] getFields() :获取所有public修饰的成员变量
Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符
Field getField(String name) 获取指定名称的 public修饰的成员变量
Field getDeclaredField(String name) 获取指定的成员变量
|
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| import java.lang.reflect.Field;
public class FieldTest { public String name; public String profession; protected int age; private String number; char sex;
public static void main(String[] args){ try{
Class c1 = Class.forName("FieldTest");
Field[] fieldArray1 = c1.getDeclaredFields(); Field[] fieldArray2 = c1.getFields();
for (Field field : fieldArray1){ System.out.println(field.getName()); }
System.out.println("-------分割线---------");
for (Field field : fieldArray2){ System.out.println(field.getName()); } System.out.println("-------分割线---------");
Field fieldArray3 = c1.getField("name"); System.out.println(fieldArray3.getName()); System.out.println("-------分割线---------");
Field fieldArray4 = c1.getDeclaredField("number"); System.out.println(fieldArray4.getName()); } catch (Exception e) { e.printStackTrace(); } } }
|
获取成员方法Method
1 2 3 4 5 6 7
| Method getMethod(String name, 类<?>... parameterTypes)
Method getDeclaredMethod(String name, 类<?>... parameterTypes)
Method[] getMethods()
Method[] getDeclaredMethods()
|
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| import java.lang.reflect.Constructor; public class ConstructorTest { public ConstructorTest() { System.out.println("无参构造函数"); } public ConstructorTest(String name) { System.out.println("有参构造函数" + name); } private ConstructorTest(boolean n) { System.out.println("私有构造函数"); } public static void main(String[] args) { try { Class c1 = Class.forName("ConstructorTest"); Constructor[] constructors1 = c1.getDeclaredConstructors(); Constructor[] constructors2 = c1.getConstructors(); for (Constructor c : constructors1) { System.out.println(c); } System.out.println("-------分割线---------"); for (Constructor c : constructors2) { System.out.println(c); } System.out.println("-------分割线---------"); Constructor constructors3 = c1.getConstructor(String.class); System.out.println(constructors3); System.out.println("-------分割线---------"); Constructor constructors4 = c1.getDeclaredConstructor(boolean.class); System.out.println(constructors4); } catch (Exception e) { e.printStackTrace(); } } }
|
反射创建类对象
使用Class对象的newInstance()方法来进行创建类对象。
1 2
| Class c1 = Class.forName('MethodTest'); Object m1 = c1.newInstance();
|
invoke()方法 构造形式如下:
1
| public Object invoke(Object obj, Object... args)
|
利用反射调用runtime示例
请使用java 1.8
1 2 3 4 5 6 7 8 9 10 11 12
| import java.lang.reflect.Constructor;
public class RuntimeTest { public static void main(String[] args) throws Exception { Class c1 = Class.forName("java.lang.Runtime"); Constructor m = c1.getDeclaredConstructor(); m.setAccessible(true); Object runtimeInstance = m.newInstance(); c1.getMethod("exec", String.class).invoke(runtimeInstance, "calc"); } }
|
CC1 链