77 votes

Comment compiler et instancier par programme une classe Java?

J'ai le nom de la classe stocké dans un fichier de propriétés. Je sais que le magasin de classes implémentera IDynamicLoad. Comment instancier la classe dynamiquement?

Maintenant j'ai

      Properties foo = new Properties();
    foo.load(new FileInputStream(new File("ClassName.properties")));
    String class_name = foo.getProperty("class","DefaultClass");
    //IDynamicLoad newClass = Class.forName(class_name).newInstance();
 

NewInstance ne charge-t-il que les fichiers .class compilés? Comment charger une classe Java non compilée?

156voto

BalusC Points 498232

Comment puis-je charger une Classe Java qui n'est pas compilé?

Vous avez besoin de le compiler en premier. Cela peut être fait par programmation avec la javax.les outils de l'API. Cela nécessite seulement le JDK installé sur la machine locale sur le dessus de la JRE.

Voici une base de lancement pour exemple (en laissant exception évidente de la manipulation de côté):

// Prepare source somehow.
String source = "package test; public class Test { static { System.out.println(\"hello\"); } public Test() { System.out.println(\"world\"); } }";

// Save source in .java file.
File root = new File("/java"); // On Windows running on C:\, this is C:\java.
File sourceFile = new File(root, "test/Test.java");
sourceFile.getParentFile().mkdirs();
new FileWriter(sourceFile).append(source).close();

// Compile source file.
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
compiler.run(null, null, null, sourceFile.getPath());

// Load and instantiate compiled class.
URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { root.toURI().toURL() });
Class<?> cls = Class.forName("test.Test", true, classLoader); // Should print "hello".
Object instance = cls.newInstance(); // Should print "world".
System.out.println(instance); // Should print "test.Test@hashcode".

Ce qui donne comme

hello
world
test.Test@ab853b

Autre utilisation serait plus facile si ces classes implements une certaine interface qui est déjà dans le classpath.

SomeInterface instance = (SomeInterface) cls.newInstance();

Sinon, vous devez faire appel à la Réflexion de l'API d'accès et d'invoquer l' (inconnu) les méthodes et les champs.


Cela dit, et sans lien avec le réel problème:

properties.load(new FileInputStream(new File("ClassName.properties")));

Laisser java.io.File s'appuyer sur le répertoire de travail courant est la recette pour la portabilité de la difficulté. Ne pas le faire. Mettre ce fichier dans le classpath et utiliser ClassLoader#getResourceAsStream() avec un classpath-chemin d'accès relatif.

properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("ClassName.properties"));

6voto

Sriram Srinivasan Points 430

Dans la même veine que BalusC de réponse, mais un peu plus automatique wrapper est ici, dans ce morceau de code à partir de mon kilim de distribution. https://github.com/kilim/kilim/blob/master/src/kilim/tools/Javac.java

Il prend une liste de chaînes de caractères contenant les sources Java, extraits de l'emballage et de la classe publique/les noms d'interface et crée le répertoire correspondant/hiérarchie des fichiers dans un répertoire tmp. Il exécute ensuite le compilateur java sur elle, et retourne une liste de nom,classfile paires (le ClassInfo structure).

Vous aider vous-même le code. Il est sous licence MIT.

5voto

Yishai Points 42417

Votre code commenté est correct si vous savez que la classe a un constructeur public no-arg. Vous devez simplement transtyper le résultat, car le compilateur ne peut pas savoir que la classe implémentera en fait IDynamicLoad . Alors:

    IDynamicLoad newClass = (IDynamicLoad) Class.forName(class_name).newInstance();
 

Bien sûr, la classe doit être compilée et sur le classpath pour que cela fonctionne.

Si vous cherchez à compiler de manière dynamique une classe à partir du code source, il s'agit d'une toute autre panoplie de poissons.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X