4

我正在寻找一个转换器来从普通的 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);
4

2 回答 2

1

你应该尽量避免在你的java代码中使用反射。您可以使用其他方法,例如@mwittrock建议的方法来避免获得那些NoClassDefFoundError.

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

核心反射工具最初是为基于组件的应用程序构建工具设计的……有一些复杂的应用程序需要反射。示例包括类浏览器、对象检查器、代码分析工具和解释性嵌入式系统……如果您对您的应用程序是否属于这些类别之一有任何疑问,它可能不会。

Joshua Bloch,“有效的 Java”,第 2 版。

于 2010-08-10T14:14:47.013 回答
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)。

于 2010-08-10T15:13:23.020 回答