Java:如何动态覆盖类的方法(类最终不在类路径中)?

jav*_*top 10 java reflection openjdk classpath nimbus

如何动态+有条件地调用类的方法?
(类最终不在类路径中)

让我们说,我需要这个类NimbusLookAndFeel,但在某些系统上它是不可用的(即OpenJDK-6).

所以我必须能够:

  • 了解该类是否可用(在运行时),
  • 如果不是这样,请跳过整个事情.
  • 如何设法覆盖动态加载类的方法
    (从而创建它的匿名内部子类)?

代码示例

public static void setNimbusUI(final IMethod<UIDefaults> method)
    throws UnsupportedLookAndFeelException {

  // NimbusLookAndFeel may be now available
  UIManager.setLookAndFeel(new NimbusLookAndFeel() {

    @Override
    public UIDefaults getDefaults() {
      UIDefaults ret = super.getDefaults();
      method.perform(ret);
      return ret;
    }

  });
}
Run Code Online (Sandbox Code Playgroud)

编辑:
现在我按照建议编辑了我的代码,NoClassDefFoundError使用try-catch 拦截.它失败.我不知道,如果是OpenJDK的错.我得到了InvocationTargetException,造成的NoClassDefFoundError.有趣,我无法抓住InvocationTargetException:无论如何它都被扔了.

EDIT2: :
原因发现:我包裹SwingUtilities.invokeAndWait(...)周围的测试方法,那很invokeAndWait调用抛出NoClassDefFoundError时加载雨云失败.

EDIT3: :
任何人都可以请澄清其中 NoClassDefFoundError可能会出现呢?因为它似乎总是调用方法,而不是使用不存在的类的实际方法.

whi*_*rra 4

了解该类是可用的(在运行时)
将用法放在 try 块中...

如果不是这种情况,请跳过整个过程
...并将 catch 块留空(代码异味?!)。

如何设法重写动态加载类的方法
只需执行此操作并确保满足编译时依赖关系。你在这里把事情搞混了。覆盖发生在编译时,而类加载是运行时的事情。

为了完整起见,您编写的每个类都会在需要时由运行时环境动态加载。

所以你的代码可能看起来像:

public static void setNimbusUI(final IMethod<UIDefaults> method)
    throws UnsupportedLookAndFeelException {

    try {
        // NimbusLookAndFeel may be now available
        UIManager.setLookAndFeel(new NimbusLookAndFeel() {

            @Override
            public UIDefaults getDefaults() {
                final UIDefaults defaults = super.getDefaults();
                method.perform(defaults);
                return defaults;
            }

        });
   } catch (NoClassDefFoundError e) {
       throw new UnsupportedLookAndFeelException(e);
   }
}
Run Code Online (Sandbox Code Playgroud)

  • 假设此代码已编译,如果运行时不存在“NimbusLookAndFeel”,则不会抛出“ClassNotFoundException”,而是抛出“NoClassDefFoundError”。 (3认同)