寻找代码转换器将普通Java代码转换为反射式代码

时间:2010-08-10 13:34:38

标签: java reflection converter noclassdeffounderror code-conversion

我正在寻找一个转换器,用普通的Java代码制作反射式Java代码。我这样做是为了防止像NoClassDefFoundError这样的异常(我想依赖于一个类,但是如果我正在使用的库没有那个依赖类,我希望Java简单地忽略代码)。

我希望这样的转换器:

初始代码:

com.foo.MyClass myClass = new com.foo.MyClass()
myClass.meth1();
转换后

Object myClass = Class.forName("com.foo.MyClass").newInstance();
myClass.getMethods("meth1").invoke(myClass);

2 个答案:

答案 0 :(得分:1)

您应尽量避免在Java代码中使用反射。您可以使用其他方法,例如@mwittrock建议的方法,以避免获取NoClassDefFoundError

您可以使用反射解决问题,但您可能会在设计中引入新问题。考虑性能成本以及反射代码的详细程度。

  

核心反射设施是   最初的设计   基于组件的应用程序构建器   工具......有几个   复杂的应用程序   需要反思。例子包括   类浏览器,对象检查器,   代码分析工具和解释   嵌入式系统......如果你有的话   怀疑你是否申请   它属于这些类别之一   可能不会。

Joshua Bloch,“Effective Java”,第2版。

答案 1 :(得分:1)

这可能是一种技术上可行的方法,但与其他海报一样,我建议您考虑这是否是解决问题的正确方法(并且您已经问过如何实施此解决方案而不是如何解决原始问题,所以我不能告诉你你是否走在正确的轨道上。)

您是否有兴趣选择依赖图书馆而不是强迫您的客户提供图书馆?根据您的构建系统,这并不难实现。例如,Maven允许您将依赖项指定为<scope>optional</scope>,这允许您针对它编译代码,但不将其作为传递依赖项包含在内。

话虽如此,确实可以选择性地依赖某些图书馆,并且如果它们不可用则采取替代路线。根据我的经验,通过隐藏界面背后的细节最容易做到这一点。

作为一个例子,我有一个ProfilingAdvisor接口,可以使用AspectJ方面来分析我用自定义注释标记的方法。我有一个名为SimpleProfilingAdvisor的这个接口的基本实现,它没有外部依赖。我有一个更详细的实现,它使用Java Simon库获取更多信息,名为SimonProfilingAdvisor。

如果客户选择包含Java Simon库,他们将获得“更好”的实现。如果他们选择不这样做,则实施“基础”方法(在您的情况下可能根本不做任何事情)。

我的代码总是对接口ProfilingAdvisor进行操作,但在实例化此类型的实例变量时,我必须确定可选的Simon库是否在类路径中:

    private ProfilingAdvisor advisor;
    /* ... */
    try {
        Class.forName("org.javasimon.SimonManager");
        this.advisor = new SimonProfilingAdvisor();
    } catch (ClassNotFoundException classNotFoundException) {
        this.advisor = new SimpleProfilingAdvisor();
    }

最后一点。虽然你可以像你建议的那样使用反射来确定一个类的存在,但是在实例化之后通过对它进行反射方法访问,我无法想到你正在获得的任何东西,并且你实际上绕过了编译器的能力。您对方法名称的拼写等。

至少,您应该使用一个构建系统,该系统允许您在编译时针对库进行编译,但不一定在以后将其包含在您的发行版中(例如,Maven)。