【问题标题】:Can't find Class with Class.forName() but it exists找不到带有 Class.forName() 的类,但它存在
【发布时间】:2016-09-22 09:06:17
【问题描述】:

我有一个程序,我在运行时生成类(仅包括变量和相关的 getter 和 setter 方法)。稍后我想补课。

要获取该类 - 我知道它的名称,但它不在类路径中 - 我尝试了 .forName() 但我总是得到一个 ClassNotFoundException。

这是我的例子:

Exception in thread "main" java.lang.ClassNotFoundException: com.test.wam.business.wsobjects.Testclass
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at gui.Application.main(Application.java:94)

还有代码:

URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
    DynamicURLClassLoader dynamicURLClassLoader = new DynamicURLClassLoader(urlClassLoader);
    dynamicURLClassLoader.addURL(new URL("file://C:\\dev\\Eclipse_was\\guitest\\generated"));

    Class c = Class.forName("com.test.wam.business.wsobjects.Testclass");

    Object classInstance = c.newInstance();

类加载器:

public class DynamicURLClassLoader extends URLClassLoader {

public DynamicURLClassLoader(URLClassLoader classLoader) {
    super(classLoader.getURLs());
}

@Override
public void addURL(URL url) {
    super.addURL(url);
}

}

文件的全限定名(用 eclipse 创建 -> 复制全限定名)

/guitest/generated/com/test/wam/business/wsobjects/Testclass.java

这里有什么问题?

【问题讨论】:

  • “但它不在类路径中”。那个。
  • Class.forName 需要 class 文件,Testclass.java 不需要。
  • 在这种情况下我该怎么办 - 我只有生成的 java 文件,没有类文件?
  • 仅仅创建DynamicURLClassLoader 什么都不做,Class.forName(...) 不会以某种方式自动使用该类加载器。当然,必须先编译 Java 源代码。
  • 我在问题中添加了 DynamicURLClassLoader 的代码

标签: java reflection classloader urlclassloader


【解决方案1】:

我可以看到两个问题:

1) 您正在创建一个DynamicURLClassLoader 并向其中添加 URL,但您实际上并没有使用它。本声明:

 Class c = Class.forName("com.test.wam.business.wsobjects.Testclass");

将使用加载当前类的类加载器。这可能是应用程序的默认类加载器,但它肯定不是您刚刚创建的类加载器。 javadoc 说:

[Class.forName(className)] 返回与具有给定字符串名称的类或接口关联的Class 对象。调用该方法等价于:

Class.forName(className, true, currentLoader) 

其中currentLoader 表示当前类的定义类加载器。

所以....解决方案是:

Class c = Class.forName("com.test.wam.business.wsobjects.Testclass",
                        true, dynamicURLClassLoader);

2) 这个字符串:

"file://C:\\dev\\Eclipse_was\\guitest\\generated"

不是有效的“文件:”URL。您尝试引用的路径的正确 URL 是:

"file:///C:/dev/Eclipse_was/guitest/generated"

您编写 URL 的方式可能有效,但这不是正确的方式。

参考:

【讨论】:

    【解决方案2】:

    Class.forName(String) 方法使用调用者类的ClassLoader,如果你想使用特定的ClassLoader 来加载你的类,你需要使用Class.forName(String name, boolean initialize, ClassLoader loader) 来代替:

    Class c = Class.forName(
        "com.test.wam.business.wsobjects.Testclass", true, dynamicURLClassLoader
    );
    

    注意:当且仅当您提供给您的 DynamicURLClassLoaderURL 有效并且是您的班级所在的父文件夹的路径时,这才有效

    【讨论】:

      猜你喜欢
      • 2018-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-25
      • 2014-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多