【问题标题】:When exactly is NoClassDefFoundError thrown?NoClassDefFoundError 究竟是什么时候抛出的?
【发布时间】:2011-08-19 05:54:49
【问题描述】:

Java 中的运行时依赖项是如何工作的。例如,如果 Impl1Impl2 在运行时不在类路径中,这样的代码是否可行:

Thinger t;
if (classIsAvailable(Impl1.class)) t = new Impl1();
else t = new Impl2();
t.doThing();

或者如果没有通用接口:

if (classIsAvailable(Impl1.class)) Impl1.doThingThisWay();
else Impl2.doThingTheOtherWay();

【问题讨论】:

    标签: java dependencies runtime classpath


    【解决方案1】:

    当您的类在类路径中未使用Impl1Impl2 加载时,您的示例将失败并显示NoClassDefFoundError,因此在这种情况下不会执行任何代码。

    【讨论】:

    • 好吧,我想这个问题的合理扩展应该是什么时候加载类?。如果我有例如Impl1Wrapper 指代Impl1Impl2 的等价物,如果ImplX 不在类路径上(但两个包装器都在),则是否可以加载引用两个没有反射的包装器的ImplChooser 类?
    • @Bart:我认为这取决于这些类的具体实现方式。如果缺少的类不是包装器中任何方法签名或字段定义的一部分(即它们仅出现在方法主体中),我相信它会起作用。但最简单的确定方法是尝试一下。
    【解决方案2】:

    ClassNotFoundException 抛出时 应用程序尝试通过其字符串名称加载一个类,使用:

    * The forName method in class Class.
    * The findSystemClass method in class ClassLoader .
    * The loadClass method in class ClassLoader. 
    

    但找不到具有指定名称的类的定义。

    您可能还会发现http://www.xyzws.com/javafaq/what-does-classforname-method-do/17 很有用。

    HTH

    【讨论】:

    • 我使用了错误的异常名称。我的意思是NoClassDefFoundError
    • @Bart NoClassDefFoundError 当你成功编译代码并且由于缺少类文件库而导致运行代码在运行时找不到所需的类时发生。
    • 我知道。问题是在运行时究竟什么时候成为必需的类。
    【解决方案3】:

    您不能完全这样做,因为为了评估Impl1.class,所述类必须可用(即已加载)。但是,您可以尝试按名称加载特定类

     Class aClass = classLoader.forName("Impl1");
    

    如果这没有失败(抛出异常),您可以使用 newInstance() 创建此类的实例。

    当然,为了能够使用您的类,您必须确保它实现了一个接口,该接口在编译时已知的。在这种情况下,您可以将创建的对象转换为该接口类型并继续使用它。

    This article 有一些示例代码。

    【讨论】:

    • 如果两个实现提供相同的功能但没有共享接口怎么办?那么反射是调用它们的唯一方法吗?
    猜你喜欢
    • 1970-01-01
    • 2018-10-12
    • 1970-01-01
    • 1970-01-01
    • 2021-04-15
    • 2014-09-09
    • 2017-12-11
    • 2023-02-25
    • 1970-01-01
    相关资源
    最近更新 更多