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

发布于 2024-09-13 11:56:06 字数 1539 浏览 12 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

乖不如嘢 2024-09-20 11:56:06

您应该尽量避免在 Java 代码中使用反射。您可以使用其他方法,例如 @mwittrock 建议的方法来避免出现这些 NoClassDefFoundError

您也许能够使用反射来解决问题,但您可能会在设计中引入新的问题。考虑性能成本以及反射代码的冗长性。

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

Joshua Bloch,《Effective Java》,第二版。

You should try to avoid the use of reflection in your java code as much as you can. You can use other approaches, like the one suggested by , @mwittrock to avoid getting those NoClassDefFoundError.

You might be able to solve a problem using reflection, but you're likely to introduce new ones in your design. Consider the performance cost as well as the verbosity of the reflection code.

The core reflection facility was
originally designed for
component-based application builder
tools... There are a few
sophisiticated applications that
require reflection. Examples include
class browsers, object inspectors,
code analysis tools, and interpretive
embedded systems... if you have any
doubt as to whether you application
falls into one of these categories, it
probably doesn't.

Joshua Bloch, "Effective Java", 2nd Edition.

魔法唧唧 2024-09-20 11:56:06

这可能是一种技术上可行的方法,但像其他海报一样,我敦促您考虑这是否是解决您的问题的正确方法(并且您问的是如何实现此解决方案而不是如何解决您原来的问题,所以我无法真正告诉您您是否走在正确的道路上)。

您是否可能有兴趣选择依赖某个库,但不强迫您的客户提供它?根据您的构建系统,这并不难实现。例如,Maven 允许您将依赖项指定为 optional,这允许您针对它编译代码,但不将其包含为传递依赖项。

话虽这么说,确实可以选择依赖某些库,并在它们不可用时采取替代路线。根据我的经验,通过将细节隐藏在界面后面最容易做到这一点。

例如,我有一个 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)

This might be a technically possible approach, but like other posters, I urge you to consider if this is the right way to solve your problem (and you've asked how to implement this solution rather than how to solve your original problem, so I can't really tell you if you're on the right track or not).

Are you perhaps interested in optionally depending on a library but not forcing your clients to provide it? Depending on your build system, this isn't that hard to accomplish. Maven, for example, allows you to specify a dependency as <scope>optional</scope>, which allows you to compile code against it but doesn't include it as a transitive dependency.

That being said, it is indeed possible to optionally depend on certain libraries and to take an alternate route if they're not available. In my experience, this is most easily done by hiding the details behind an interface.

As an example, I have a ProfilingAdvisor interface that works with an AspectJ aspect to profile methods I've marked with a custom annotation. I have a rudimentary implementation of this interface called SimpleProfilingAdvisor, which has no external dependencies. I have a more detailed implementation that uses the Java Simon library for additional information, called SimonProfilingAdvisor.

If clients choose to include the Java Simon library, they get the "better" implementation. If they choose not to, the "base" approach is implemented (which in your case may be to do nothing at all).

My code always operates to the interface, ProfilingAdvisor, but when instantiating the instance variable of this type, I have to determine whether the optional Simon library is on the classpath:

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

One last point. While you can determine a class's existence using reflection as you're suggesting, I can't think of anything you're gaining by making reflective method accesses to it after instantiation, and you're effectively bypassing the compiler's ability to so much as check your spelling on method names, etc.

At the least, you should be working with a build system that allows you to compile against a library at compile-time but not necessarily include it in your distribution later (e.g., Maven).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文