博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java 强大的反射机制
阅读量:5303 次
发布时间:2019-06-14

本文共 4398 字,大约阅读时间需要 14 分钟。

这段时间,在对接一个开源的版本时,发现由于依赖的开源版本api老是随着版本的变化而变化,导致代码经常需要修改,异常痛苦。

终于,在一个风和日丽的下午(五月末的广州异常暴晒),楼主下定决心要修掉这个大篓子。

在Internet寻找了很久,终于找到了解决方法,参考的文章在本文最后,感谢文章的作者。

使用java的反射机制,在代码里判断当前运行的是什么版本,然后调用相应的方法。

这样,代码就做到了自适应。

假设:

在自己的代码中,有这么一个工程。

Function.java

package chen.test.function;public class Function{
public static void test(String name ){ System.out.println(name); System.out.println("test function have one input"); } public static void test(String name , int id){ System.out.println(name); System.out.println(id); System.out.println("test function have two input"); }}

对上面的Function.java程序编译出一个jar包,名为function.jar

这个Function类是我自己构造的,为了将Main.java程序编译通过,自己伪造一个方法即可。它有两个test方法,通过参数个数进行重载,但是实际的运行环境里,依赖的jar包中只有一个test方法,可能是两个输入参数的,也有可能是一个输入参数的。

 

请看Main.java程序怎么动态识别。

开发的程序中,依赖function.jar

Main.java

package chen.test.client;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import chen.test.function.Function;public class Main {    public static void main(String[] args){        Function aa = new  Function();                tCl( aa );    }    /*    * 本程序是基于JDK1.7 编写,如果使用JDK1.6,那么下面有一些Exception JDK1.6 是不支持的         * 不支持的Exception 去除即可         */        private static void tCl( Object obj ){        Class
classExec = obj.getClass(); Method exec = null; try { //如果运行的jar包支持两个参数的,就运行这个方法 //如果运行的jar包不支持两个参数,就进入catch 段,执行输入一个参数的方法 exec = classExec.getMethod("test", String.class, Integer.class); try { String re = (String) exec.invoke( classExec.newInstance(), "chenfool good", 123); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | InstantiationException e1) { e1.printStackTrace(); } } catch (NoSuchMethodException | SecurityException e) { try { //运行中,依赖的jar包,不支持两个参数,导致进入此段代码 //运行只有一个输入参数的函数 exec = classExec.getMethod("test", String.class); try { String re = (String) exec.invoke( classExec.newInstance(), "chenfool good"); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | InstantiationException e1) { e1.printStackTrace(); } } catch (NoSuchMethodException | SecurityException e1) { e1.printStackTrace(); } } }}

上面的Main.java程序虽然可以通过,但是方法中有一个缺陷,当Function类是不可构建的时,方法就不能通过了,它会报Function.class.getInterfaces()出错。

拥有私有构建函数的Function.java

package chen.test.function;public class Function{    private Function(){    }    public static void test(String name ){        System.out.println(name);        System.out.println("test function have one input");    }    public static void test(String name , int id){        System.out.println(name);        System.out.println(id);        System.out.println("test function have two input");    }}

这时,我们就要用别的方法来解决这个问题。

考虑,我们的目的就是判断当前运行的环境中,Function.test方法的输入参数是一个还是两个,所以我们使用getDeclaredMethod()方法,通过是否抛出异常来区分究竟是调用哪个test方法。

改进版本的Main.java程序

package chen.test.client;import java.lang.reflect.Method;import chen.test.function.Function;public class Main {  public static void main(String[] args){    Class[] parameterTypes = new Class[2];    parameterTypes[0] = String.class;    parameterTypes[1] = int.class;    try {      //如果没有抛出异常,则证明此环境的Function类是调用两个参数的方法      //如果抛出异常,则调用一个输入参数的test方法      Method method = Function.class.getDeclaredMethod("test", parameterTypes);      Function.test("chenfool is great", 123);    } catch (SecurityException e) {      e.printStackTrace();    } catch (NoSuchMethodException e) {      parameterTypes = new Class[1];      parameterTypes[0] = String.class;      Method method = null;      try {        //系统捕获异常,证明此运行环境调用的是一个输入参数的test方法        method = Function.class.getDeclaredMethod("test", parameterTypes);        Function.test("chenfool is good");      } catch (SecurityException e1) {        e1.printStackTrace();      } catch (NoSuchMethodException e1) {        e1.printStackTrace();      }    }  }}

通过java的反射机制,我们就能动态的调用相应的方法,而无需因为依赖jar包的Api不兼容,导致开发多个程序来适配对应不同版本的Api,这样项目工程一旦变大,或者时间拉长,程序的维护成本会越来越高。

参考文章:

转载于:https://www.cnblogs.com/chenfool/p/3755652.html

你可能感兴趣的文章
哈希表等概率情况下查找成功和查找不成功的平均查找长度的计算
查看>>
Windows Phone 7你不知道的8件事
查看>>
脚本删除文件下的文件
查看>>
实用拜占庭容错算法PBFT
查看>>
java b组 小计算器,简单计算器..
查看>>
java的二叉树树一层层输出,Java构造二叉树、树形结构先序遍历、中序遍历、后序遍历...
查看>>
php libevent 定时器,PHP 使用pcntl和libevent实现Timer功能
查看>>
php仿阿里巴巴,php实现的仿阿里巴巴实现同类产品翻页
查看>>
Node 中异常收集与监控
查看>>
七丶Python字典
查看>>
Excel-基本操作
查看>>
面对问题,如何去分析?(分析套路)
查看>>
Excel-逻辑函数
查看>>
面对问题,如何去分析?(日报问题)
查看>>
数据分析-业务知识
查看>>
nodejs vs python
查看>>
poj-1410 Intersection
查看>>
Java多线程基础(一)
查看>>
TCP粘包拆包问题
查看>>
Java中Runnable和Thread的区别
查看>>