2014-07-25 5 views
0

Considérez ceci - je une simple application d'une classe appelée "TestApplication" (code source ci-dessous):Comment appeler une classe à partir d'un fichier JAR non exécutable dans un programme Java?

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); 
    } 
} 

Maintenant, dans sa méthode button.setOnAction() Je veux appeler un "TestJar.class" (étend JavaFX. stage.Stage), qui est la seule classe d'archive "TestJar.jar" non exécutable. Mais le problème est, je veux pouvoir appeler "TestJar.class" du niveau de "TestApplication" sans la possibilité préalable d'ajouter des importations au code. Par exemple j'ai une application, pour laquelle je fournis l'emplacement de jar et des informations sur le nom de la classe dans ce pot, qui devrait être appelé. Code de la classe "TestJar.java" ci-dessous:

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(); 
    } 
} 

et la structure additionaly du fichier 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> 

Est-il possible que je peux appeler cette classe "TestJar" de mon programmable « TestApplication "classe?

MISE À JOUR 26/07/2014, 11:37

Je l'ai utilisé l'exemple écrit par @Allain Lalonde dans How should I load Jars dynamically at runtime? appelé ClassPathHack

Ensuite, je l'ai fusionné sa solution suggestion faite dans ce sujet par @Doswell, qui ressemble à ceci:

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(); 
     } 
    } 
}) 

Tout fonctionne parfaitement. Je vous remercie!

+0

Ajouter à votre classpath et l'importer, puis le construire? Pas sûr de ce que vous demandez. –

+0

J'ai modifié ma question pour la rendre plus spécifique. – bluevoxel

Répondre

2

Si la classe que vous voulez lancer à partir du pot étend/implémente quelque chose que vous connaissez dans votre code déjà, vous pouvez utiliser re flection pour charger la classe mais travailler avec elle comme quoi vous le connaissez comme javafx.stage.Stage vs TestJar.

Si le JAR est déjà sur le chemin de classe, vous pouvez simplement le faire;

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

Si vous ne disposez pas du JAR sur le chemin de classe, mais ont le chemin du pot, vous pouvez suivre cette How should I load a jar Et puis charger la classe comme ci-dessus

0

Classloader/sécurité/correcte environnement/de corriger les problèmes au contexte de côté:

  1. mis TestJar.jar sur classpath
  2. de votre application à partir de votre application, appelez

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

Désolé, j'ai manqué votre clarification (l'aperçu échoue par moi). Donc, vous voulez charger TestJar à l'exécution? Si c'est le cas, vous pouvez utiliser java.lang.Class.forName ("TestJar") et java.class.Class.newInstance() pour instancier des classes en fonction de leur nom (en supposant que votre classloader puisse trouver la classe et vous accorde le privilège) – 0xb304

Questions connexes