反射

前言

java的反射机制是指在运行时获取类的属性和方法。并且能够动态修改属性和调用方法。

在日常开发中尤其是在集成代码,简化代码的时候,我们经常会遇到不能在编译时就能获取属性。这时候我们会用反射来解决这个问题。

首先要明确的是:通过来反射获取属性和调用方法,肯定比直接用代码硬编码要慢。所以反射我们需要谨慎的使用,尤其是当自己编写的方法可能会频繁调用的时候。就需要考虑加入缓存或者考虑是否不使用反射来达到效果。

对于反射为什么会慢,其实我自己也没有深刻理解。这篇stackoverflow有些讨论。

大致可以看到是:

  1. 反射相对直接调用,JVM并不是很好的去对其优化。
  2. 必须发现正在调用/创建的所有内容
  3. 参数需要重新包装成数组,同时还要捕获异常InvocationTargetException
  4. 反射并不慢,相对网络传输、解析xml等其他耗时行为。

反射的基本使用

java中反射的api相对比较简单。这里简单写一下常用的

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
40
41
public class main {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException,
InstantiationException, NoSuchMethodException, InvocationTargetException {
Class<ReflectBean> clzss = ReflectBean.class;
// 1. 创建实例
ReflectBean reflectBean = clzss.newInstance();

// 2. 字段操作
// 获取字段 (只能获取public的,但是可以获取从父类继承过来的public属性)
Field name = clzss.getField("pubName");
Field[] fields = clzss.getFields();

// 获取字段 (获取当前类的所有字段,但是获取不到父类继承来的属性)
Field name1 = clzss.getDeclaredField("name");
Field[] declaredFields = clzss.getDeclaredFields();

// 获取字段属性
// 在获取private属性时,必须将该属性设为true才能直接get。你可以选择通过get,set方法来获取
name1.setAccessible(true);
name1.set(reflectBean,"反射设置的name");
String str = (String)name1.get(reflectBean);
System.out.println(str);

// 3. 方法操作
// 获取方法 这里和field一样操作。不多赘述
Method method = clzss.getMethod("method");
Method[] methods = clzss.getMethods();
Method priMethod = clzss.getDeclaredMethod("priMethod", String.class);
Method[] declaredMethods = clzss.getDeclaredMethods();

// 调用方法
Object invoke = method.invoke(reflectBean);

priMethod.setAccessible(true); // 下面是私有的方法,也要加上这句
Object string = priMethod.invoke(reflectBean, "string");
System.out.println(invoke);
System.out.println(string);

System.out.println(reflectBean);
}
}

以上就是如此了。反射暂时没有发掘有撒可扩充的。有实际的比较好的实际使用再来更新。