如何在java程序中从非runnable JAR中调用一个类?

时间:2014-07-25 21:14:52

标签: java jar javafx

考虑一下 - 我有一个名为“TestApplication”的简单一类应用程序(源代码如下):

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class TestApplication extends Application {

    public Parent createContent() {

        /*layout*/
        BorderPane layout = new BorderPane();

        /*layout -> center*/
        Button button = new Button("Run JAR");
        button.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent ae) {
                // Call TestJar.class from TestJar.jar
            }
        });

        /*add item to the layout*/
        layout.setCenter(button);
        return layout;
    }

    @Override
    public void start(Stage stage) throws Exception {
        stage.setScene(new Scene(createContent()));
        stage.setWidth(200);
        stage.setHeight(200);
        stage.show();
    }

    public static void main(String args[]) {
        launch(args);
    }
}

现在,在我的button.setOnAction()方法中,我想调用一个“TestJar.class”(扩展javafx.stage.Stage),这是唯一一个不可运行的“TestJar.jar”存档类。但问题是,我希望能够从“TestApplication”级别调用“TestJar.class”而无需事先将代码添加到代码中。例如,我有一个应用程序,我提供了jar位置和有关此jar中类的名称的信息,应该调用它。下面的“TestJar.java”类的代码:

import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class TestJar extends Stage {

    public TestJar() {
        super();
        BorderPane layout = new BorderPane();
        Label label = new Label("This is test");
        layout.setCenter(label);
        Scene scene = new Scene(layout, 200, 200);
        this.setScene(scene);
        this.show();
    }
}

另外JAR文件的结构:

<archive = TestJar.jar>
    <folder = META-INF>
        <file = MANIFEST.MF>
            Manifest-Version: 1.0
        </file>
    </folder>
    <file = .classpath>
        <?xml version="1.0" encoding="UTF-8"?>
        <classpath>
            <classpathentry kind="src" path="src"/>
            <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
            <classpathentry kind="output" path="bin"/>
        </classpath>
    </file>
    <file = .project>
        <?xml version="1.0" encoding="UTF-8"?>
        <projectDescription>
            <name>TestJar</name>
            <comment></comment>
            <projects>
            </projects>
            <buildSpec>
                <buildCommand>
                    <name>org.eclipse.jdt.core.javabuilder</name>
                    <arguments>
                    </arguments>
                </buildCommand>
            </buildSpec>
            <natures>
                <nature>org.eclipse.jdt.core.javanature</nature>
            </natures>
        </projectDescription>   
    </file>
    <file = TestJar.class></file>
</archive>

有什么方法可以从我的“TestApplication”类中调用“TestJar”类吗?

更新2014/07/26,上午11:37

我使用@Allain Lalonde在How should I load Jars dynamically at runtime?中编写的名为 ClassPathHack

的示例

接下来,我将他的解决方案与@Doswell在本主题中提出的建议合并,看起来像这样:

button.setOnAction(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent ae) {
        try {
            ClassPathHack.addFile("C:/Users/John Smith/Desktop/TestJar.jar");

            Class<?> clazz = Class.forName("TestJar");
            Stage testJar = (Stage) clazz.newInstance();

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } 
    }
})

一切都很完美。谢谢!

2 个答案:

答案 0 :(得分:2)

如果要从jar运行的类扩展/实现您在代码中已知的内容,则可以使用反射来加载类,但是可以使用它,就像它所知道的那样,即javafx.stage.Stage vs TestJar。

如果JAR已经在类路径中,您可以这样做;

Class<?> clazz = Class.forName("TestJar");
Stage testJar = (Stage)clazz.newInstance();

如果类路径上没有JAR,但确实有jar的路径,那么可以按照How should I load a jar进行操作 然后按上面加载类

答案 1 :(得分:0)

Classloader / security / correct-environment / correct-context关注:

  1. TestJar.jar放在您的应用程序的类路径
  2. 上 来自您的应用程序的
  3. ,请调用

    /*TestJar ignored =*/ new TestJar();