反射
Java反射机制是在运行状态时,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的反射机制。
获取类
JVM为每个加载的class
创建了对应的Class
实例,并在实例中保存了该class
的所有信息;因此,如果获取了某个Class
实例,我们就可以通过这个Class
实例获取到该实例对应的class
的所有信息。
常用的由以下几种方式获取类:
1 2 3 4 5 6 7 8 9 10 11 12
| Class clazz = String.class;
String s = ""; Class clazz = s.getClass();
Class clazz = Class.forName("java.lang.String");
Class<?> clazz = this.getClass().getClassLoader().loadClass("com.spring.sec.ClassLoader.reflectTest");
|
获取类之后就可以对类进行访问修改等操作,值得注意的是,上述四种方法所获取的Class实例是同一个。
获取属性
1 2 3 4 5 6 7 8 9 10 11
| Class<?> clazz = Class.forName("com.spring.sec.reflectTest");
Field[] fields = clazz.getFields();
Field field = clazz.getField("property");
Field[] declaredFields = clazz.getDeclaredFields();
Field declaredField = clazz.getDeclaredField("property");
|
对于获取到的属性,我们想要在具体的实例中获取需要使用get()
方法,修改需要使用set()
方法.
1 2 3 4
| Object o = field.get(clazz.newInstance());
field.set(clazz.newInstance(),"edited_property");
|
另外对于private
,protected
修饰的属性需要先设置可编辑才能修改:
1
| privateField.setAccessible(true);
|
获取方法
getMehtod()
其原型是
1 2
| public reflect.Method getMethod(@NonNls @NotNull String name, Class<?>... parameterTypes)
|
一些例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| Class<?> clazz = Class.forName("com.spring.sec.reflectTest");
Method[] methods = clazz.getMethods();
Method method = clazz.getMethod("name");
Method[] methods = clazz.getDeclaredMethods();
Method method = clazz.getDeclaredMethod("name");
Method method = clazz.getDeclaredMethod("name",String.class);
|
调用: invoke()
获取方法后执行需要调用invoke()
,其原型是
1
| public Object invoke(Object obj, Object... args)
|
obj
是实例,args
是参数例如
1 2 3 4
| method.invoke(clazz,new String("springtime"));
method.invoke(clazz);
|
注意:若调用的方法为静态方法,则第一个参数必须是null
1 2 3 4 5
| Method m = Integer.class.getMethod("parseInt", String.class);
Integer n = (Integer) m.invoke(null, "23333"); System.out.println(n);
|
获取构造器
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| Constructor<?> constructor = clazz.getConstructor();
Constructor<?> constructor = clazz.getDeclaredConstructor()
Constructor<?> constructor = clazz.getConstructor(...parameterTypes)
Constructor<?> constructor = clazz.getDeclaredConstructor(...parameterTypes)
Constructor<?>[] constructors = clazz.getConstructors();
Constructor<?>[] Constructors = clazz.getDeclaredConstructors();
|
实例化: newInstance()
注意:java.lang.Class.newInstance()
与java.lang.refelct.Constructor.newInstance()
不同,前者是无参构造方法调用,而后者是构造方法重载调用。
1 2
| Object o = clazz.newInstance(); Object o = constructor.newInstance(@Nullable Object... initargs);
|
修改final关键字修饰的属性
被final关键字修饰的属性我们无法使用set()
方法修改,需要借助类中的modifiers
。
1 2 3 4 5 6 7 8 9 10 11
| Field modifiers = field.getClass().getDeclaredField("modifiers");
modifiers.setAccessible(true);
modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(obj, "edited_value");
|
反射命令执行
1
| Class.forName("java.lang.Runtime").getMethod("exec",String.class).invoke(Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(Class.forName("java.lang.Runtime")),"calc.exe");
|
高版本JDK下的反射
@TODO