【问题标题】:Java Class signature and dynamic loadingJava 类签名和动态加载
【发布时间】:2013-07-17 05:59:11
【问题描述】:

什么时候两个类被认为是相同的?比如,有没有什么东西可以作为一个类的签名?如果是这样,签名、包信息、类名等有什么影响?我问这个是因为我需要动态加载一个类,而且我总是得到一个ClassNotFoundException

更多细节:我正在使用 Eclipse。我的package com.example.project.sub1 中有一个abstract class Panel。和package com.example.project.sub2 中的class Test,它将调用

类加载器加载器 = 新 URLClassLoader( 新 URL[]{新 URL("file://" + path)}); /*路径是运行时指定的,可以是不同的 工作目录以外的目录。这是路径 到我需要加载的类文件的父目录。 */ 类&ltPanel&gt panelClass = (Class&ltPanel&gt)loader.loadClass(className); //类名是运行时指定的。

编译得很好。然后我将Panel.java 中的所有内容复制到一个新目录中,并创建了一个class MyPanel extends PanelPanel.java。这也编译得很好,但是当我指定新的MyPanel.class 的路径时,我总是得到一个ClassNotFoundException。知道我哪里错了吗?谢谢。

编辑: 堆栈跟踪:

java.lang.ClassNotFoundException: MyPanel 在 java.net.URLClassLoader$1.run(URLClassLoader.java:202) 在 java.security.AccessController.doPrivileged(本机方法) 在 java.net.URLClassLoader.findClass(URLClassLoader.java:190) 在 java.lang.ClassLoader.loadClass(ClassLoader.java:306) 在 java.lang.ClassLoader.loadClass(ClassLoader.java:247) 在 com.example.project.sub2 (Test.java:111) 在 java.lang.Thread.run(Thread.java:680)

【问题讨论】:

  • 文件很可能只是在错误的位置。你能显示所有涉及的路径吗?还有整个例外?
  • @Thilo 我使用了 JFileChooser 来定位文件,所以我假设路径是正确的?我会在一分钟内包含堆栈跟踪,但乍一看它并没有帮助。
  • 很有帮助 ;-) 说明你使用了错误的类名(缺少包)。

标签: java reflection


【解决方案1】:

java.lang.ClassNotFoundException: MyPanel

这个类不叫“MyPanel”,它是“com.example.project.sub1.MyPanel”。

这是我需要加载的类文件的父目录的路径。

是的,那行不通。它需要是包层次结构的根目录,所以不是“/some/path/classes/com/example/project/sub1/”,而是“/some/path/classes”

【讨论】:

  • 所以如果我没有在我的new目录中GamePanel.javaMyPanel.java指定包信息,这个MyPanel.class会被认为是GamePanel.class 在我的原包装中?谢谢。
【解决方案2】:

如果您想从文件 URL 动态加载类 com.example.project.sub1.Panel,则此 URL 应引用包含目录 com 的目录。从那里,ClassLoader 将在与包路径匹配的子目录路径中查找类。并且要传递的类名是完全限定名:com.example.project.sub1.Panel

此外,加载 MyPanel 类将返回 Class<MyPanel>,而不是 Class<Panel>。您应该使用Class<? extends Panel> 作为变量的类型。

我不确定您为什么要动态加载类。您尝试解决的实际问题可能可以通过其他方式解决。

【讨论】:

  • 我正在编写一个可扩展的应用程序,以便用户可以在我发布应用程序并插入他们自己的Panel 后提供他们自己的Panel 子类。其他更好的方法来实现这一目标?
  • 是的:让他们将自己的目录/jars 放在类路径中,并使用一些配置文件配置应用程序。然后按名称加载类,例如使用Class.forName()。使用几个类加载器并不是一件容易的事。如果用户足够精通编写和编译 Java 代码,他们应该足够精通配置和启动应用程序。
  • 我试图理解你在说什么,因为我在这方面有点缺乏经验。所以你的意思是如果用户编译,比如说,TheirPanel.class 并将它放在类路径中,我可以使用Class.forName 找到它?另外我假设我需要提供我的abstract Panel 的源代码作为蓝图,那么我是否还需要包含包信息?
  • 这就是您使用的所有库(jar 文件)的工作方式:库的供应商提供了一个包含类的 jar 文件。它还提供了 javadoc。使用此库的开发人员将 jar 放在构建和运行时类路径中,并使用文档使用该库开发他的应用程序。拥有库的源代码可能很有用,但如果 javadoc 详尽无遗,则没有必要。在这种情况下,您是一个库的开发人员,您将该库提供给其他开发人员。如果开发人员将他们的类放在类路径中,您的库可以使用 Class.forName()。
猜你喜欢
  • 2011-04-04
  • 2012-10-10
  • 2012-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-05
相关资源
最近更新 更多