一个事半功倍的Java反射库

z00124908 7年前
   <p>在Java和Android中,我们常常会使用反射来达到一些兼容的目的。Java原生提供的反射很是麻烦,使用起来很是不方便。比如我们想要调UserManager的静态方法get,使用原生的实现如下</p>    <pre>  <code class="language-java">try {      final Method m = UserManager.class.getMethod("get", Context.class);      m.setAccessible(true);      m.invoke(null, this);  } catch (NoSuchMethodException e) {      e.printStackTrace();  } catch (IllegalAccessException e) {      e.printStackTrace();  } catch (InvocationTargetException e) {      e.printStackTrace();  }  </code></pre>    <p>实现起来好不麻烦。这其中</p>    <ul>     <li>需要确定方法名和参数来获取对应的Method对象</li>     <li>设置Method对象的assessible为true</li>     <li>调用invoke方法,并且传入对应的参数</li>     <li>捕获其中可能抛出来的一连串异常</li>    </ul>    <p>那么反射能简单点么,当然,而且还会简单很多。</p>    <p>这就是本文想要介绍的,jOOR(Java Object Oriented Reflection),它是一个对java.lang.reflect包的简单封装,使得我们使用起来更加直接和方便。</p>    <p>使用jOOR,上面的代码可以缩短成一行。</p>    <pre>  <code class="language-java">Reflect.on(UserManager.class).call("get", getApplicationContext());  </code></pre>    <h2>依赖</h2>    <ul>     <li>jOOR没有依赖。</li>     <li>使用jOOR只需要将这两个文件( Reflect.java , ReflectException.java ),加入工程即可。</li>    </ul>    <h2>API介绍</h2>    <h3>Reflect</h3>    <ul>     <li>Reflect.on 包裹一个类或者对象,表示在这个类或对象上进行反射,类的值可以使Class,也可以是完整的类名(包含包名信息)</li>     <li>Reflect.create 用来调用之前的类的构造方法,有两种重载,一种有参数,一种无参数</li>     <li>Reflect.call 方法调用,传入方法名和参数,如有返回值还需要调用get</li>     <li>Reflect.get 获取(field和method返回)值相关,会进行类型转换,常与call和field组合使用</li>     <li>Reflect.field 获取属性值相关,需要调用get获取该值</li>     <li>Reflect.set 设置属性相关。</li>    </ul>    <h3>ReflectException</h3>    <p>引入ReflectException避免了我们去catch过多的异常,也减少了纵向代码量,使得代码简洁不少。ReflectException抛出,可能是发生了以下异常。</p>    <ul>     <li>ClassNotFoundException</li>     <li>IllegalAccessException</li>     <li>IllegalArgumentException</li>     <li>InstantiationException</li>     <li>InvocationTargetException</li>     <li>NoSuchMethodException</li>     <li>NoSuchFieldException</li>     <li>SecurityException</li>    </ul>    <p>除此之外,ReflectException属于unchecked 异常,语法上不需要显式进行捕获,但是也需要根据实际情况,斟酌是否进行显式捕获该异常。</p>    <h2>使用示例</h2>    <h3>创建实例</h3>    <pre>  <code class="language-java">String string = Reflect.on(String.class).create("Hello World").get();  </code></pre>    <h3>访问属性(public,protected,package,private均可)</h3>    <pre>  <code class="language-java">char pathSeparatorChar = Reflect.on(File.class).create("/sdcard/droidyue.com").field("pathSeparatorChar").get();  </code></pre>    <h3>修改属性(final属性也可以修改)</h3>    <pre>  <code class="language-java">String setValue = Reflect.on(File.class).create("/sdcard/drodiyue.com").set("path", "fakepath").get("path");  </code></pre>    <h3>调用方法(public,protected,package,private均可)</h3>    <pre>  <code class="language-java">ArrayList arrayList = new ArrayList();  arrayList.add("Hello");  arrayList.add("World");  int value = Reflect.on(arrayList).call("hugeCapacity", 12).get();  </code></pre>    <h2>实现原理</h2>    <p>Reflect实际是对原生java reflect进行封装,屏蔽了无关细节。</p>    <p>以fields方法为例,其内部实现可以看出是调用了java原生提供的反射相关的代码。</p>    <pre>  <code class="language-java">public Map<String, Reflect> fields() {      Map<String, Reflect> result = new LinkedHashMap<String, Reflect>();      Class<?> type = type();        do {          for (Field field : type.getDeclaredFields()) {              if (!isClass ^ Modifier.isStatic(field.getModifiers())) {                  String name = field.getName();                if (!result.containsKey(name))                result.put(name, field(name));              }          }            type = type.getSuperclass();      } while (type != null);        return result;  }  </code></pre>    <h2>库地址</h2>    <ul>     <li>jOOR</li>    </ul>    <p>以上就是这些,希望jOOR可以对大家的开发日常有所帮助。</p>    <p> </p>    <p>来自:http://droidyue.com/blog/2017/01/09/joor-examples/</p>    <p> </p>