Loading a class as a component in java
I'm making a program that allows you to add any class file that extends java.awt.Component
to a javax.swing.JToolBar
in its main window. I made a test class that is simply an empty javax.swing.JButton
called "test.class". How can I load this into the program as a component in my javax.swing.JToolBar
when all I know is where on the computer this class file is stored?
Alternatively: Given that the final project is a single jar file (TinyExplorer.jar), and that this is in, say C:\Users\Username\Desktop\TinyExplorer.jar, where should the add-on class be placed and how should the j开发者_如何学运维ar look for it?
Edit
I have implemented the following code:
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();
}
}
}
}
but every time I run it, I get the following exception:
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)
The issue
The issue here can be found from the following message in the stacktrace:
java.lang.ClassNotFoundException: G:\Java\NetBeansProjects\TinyExplorer\build\classes\testAddOn\test.class
This indicates that the code is trying to find a class name that's actually a file path to the class
file. This is an incorrect usage of the Class.forName
method.
The name that the Class.forName
method (link to the Java API Specification of the method) takes is a fully-qualified class name of the class that should be loaded. For example, if we want to load the JPanel
class, we'd have to provide "javax.swing.JPanel"
, not a full path to the class
file.
The solution
From looking at the code, the intention seems to be that the class contained in the class
file with the full file system path of G:\Java\NetBeansProjects\TinyExplorer\build\classes\testAddOn\test.class
should be loaded at runtime.
In order to do so, one must
- Include the
class
file in the classpath. - Give the fully-qualified class name to the
Class.forName
class to obtain aClass<?>
object. - Instantiate an object of the
Class<?>
using reflection.
Performing (1) is going to be a requirement for the Java virtual machine to be able to find the class that should be loaded in (2) -- a class
file that is not in the classpath is not going to be available during runtime.
Including the file in the classpath is usually going to be some type of build configuration in your IDE, or having to tell javac
to add a path to the classpath.
Points (2) and (3) appears to be already partially implemented in the given code, and appears like it is heading toward the right path.
It sounds like you want something like this:
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()
and Class.newInstance()
instantiate your new object. The try block has a lot of potential for exceptions, and you may want to do better than a catch-all. If your class doesn't have a default constructor, this won't work, and you'll need to get a Constructor object via reflection, and create the object by calling Constructor.newInstance(...)
.
The tutorial http://download.oracle.com/javase/tutorial/uiswing/components/toolbar.html gives examples of how to add buttons. Suggest you get this running and working in your environment.You should then be ab le to extend this by analogy to your own compponents.
精彩评论