在java中加载一个类作为组件
Posted
技术标签:
【中文标题】在java中加载一个类作为组件【英文标题】:Loading a class as a component in java 【发布时间】:2011-06-02 08:30:56 【问题描述】:我正在制作一个程序,允许您在其主窗口中添加任何扩展 java.awt.Component
到 javax.swing.JToolBar
的类文件。我创建了一个测试类,它只是一个名为“test.class”的空javax.swing.JButton
。当我只知道这个类文件存储在计算机上的什么位置时,如何将它作为我的javax.swing.JToolBar
中的一个组件加载到程序中?
或者:假设最终项目是单个 jar 文件 (TinyExplorer.jar),并且它位于 C:\Users\Username\Desktop\TinyExplorer.jar 中,应将附加类放在哪里罐子应该如何寻找它?
编辑
我已经实现了以下代码:
if (addOnFile.exists())
System.out.println(addOnFile.getName() + " is there!");
java.util.Scanner scan = new java.util.Scanner(addOnFile);
while (scan.hasNextLine())
String str = scan.nextLine();
System.out.println(str);
java.io.File f = new java.io.File(str);
if (f.exists())
try
java.awt.Component comp;
Class cls = Class.forName(str);
Object obj = cls.newInstance();
if (obj instanceof java.awt.Component)
comp = (java.awt.Component)obj;
catch (Exception err)
err.printStackTrace();
但是每次我运行它,我都会得到以下异常:
java.lang.ClassNotFoundException: G:\Java\NetBeansProjects\TinyExplorer\build\classes\testAddOn\test.class
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at explorer.Frame$24.run(Frame.java:1091)
【问题讨论】:
【参考方案1】:教程http://download.oracle.com/javase/tutorial/uiswing/components/toolbar.html 给出了如何添加按钮的示例。建议您在您的环境中运行和工作。然后您应该能够通过类比将其扩展到您自己的组件。
【讨论】:
我知道如何制作组件并将它们添加到工具栏;那是儿戏。我想知道如何将第三方类文件作为组件添加到工具栏,而我唯一知道的是类文件在计算机上的位置。请在发布答案之前阅读整个问题。 在你成为试图破译它的人的混蛋之前,请先问一个清晰连贯的问题。 我在评论中没有说问题中没有提到的内容 您添加了您希望第三方组件使用此功能的声明,而不是您自己的组件。因此,当您没有提出明确的问题时,请不要这么快发表评论或判断,尤其是考虑到您在收到问题答案时懒得阅读 API 的发帖历史。 @Supuhstar。 @Falmani 和 @camickr 制作了有价值的 cmets。你最初的帖子只包含 4 行,措辞很糟糕,没有明确的问题。我试图弄清楚你想要什么 - 我的答案是针对可能需要帮助但不知道教程存在的人。没有理由粗鲁和投反对票。【参考方案2】:听起来你想要这样的东西:
Component comp = null;
String cls_name = "test"; // include your package ie "java.lang.String"
try
Class cls = Class.forName(cls_name);
Object obj = cls.newInstance();
if (obj instanceof Component)
comp = (Component) obj;
catch (Exception err)
err.printStackTrace();
setLayout(new BorderLayout() );
JToolBar toolbar = new JToolBar();
if (comp != null)
toolbar.add(comp);
add(toolbar, BorderLayout.NORTH);
Class.forName()
和 Class.newInstance()
实例化您的新对象。 try 块有很多潜在的异常,你可能想要做得比包罗万象的更好。如果你的类没有默认构造函数,这将不起作用,你需要通过反射获取一个构造函数对象,并通过调用Constructor.newInstance(...)
创建对象。
【讨论】:
谢谢。这看起来很完美,我会尝试看看这是否有效。现在,我想知道......如果类的名称是计算机中的路径,这会起作用吗?这就是它的输入方式。【参考方案3】:问题
这里的问题可以从堆栈跟踪中的以下消息中找到:
java.lang.ClassNotFoundException: G:\Java\NetBeansProjects\TinyExplorer\build\classes\testAddOn\test.class
这表明代码正在尝试查找实际上是class
文件的文件路径的类名。这是Class.forName
方法的错误用法。
Class.forName
方法 (link to the Java API Specification of the method) 采用的 name 是应加载的类的完全限定类名。例如,如果我们要加载JPanel
类,我们必须提供"javax.swing.JPanel"
,不是class
文件的完整路径。
解决方案
从代码来看,意图似乎是应该在运行时加载class
文件中包含的类,完整文件系统路径为G:\Java\NetBeansProjects\TinyExplorer\build\classes\testAddOn\test.class
。
为了做到这一点,我们必须
-
在classpath 中包含
class
文件。
为Class.forName
类提供完全限定的类名以获得Class<?>
对象。
使用reflection 实例化Class<?>
的对象。
执行 (1) 将成为 Java 虚拟机能够找到应在 (2) 中加载的类的要求——不在类路径中的 class
文件不会在运行时可用。
在类路径中包含文件通常是 IDE 中的某种构建配置,或者必须告诉javac
添加path to the classpath。
点 (2) 和 (3) 似乎已在给定代码中部分实现,并且看起来正朝着正确的方向前进。
【讨论】:
假设最终项目是单个 jar 文件 (TinyExplorer.jar),并且它位于 C:\Users\Username\Desktop\TinyExplorer.jar 中,附加组件应该在哪里放置类,jar 应该如何查找它? @Supuhstar:如果目标类包含在 JAR 中,那么只要 JAR 在类路径中,那么只需要完全限定的类名。以上是关于在java中加载一个类作为组件的主要内容,如果未能解决你的问题,请参考以下文章
无法在标记为 @SpringBootTest 的组件测试中加载 @Configuration 类