web-dev-qa-db-fra.com

Comment créer une classe dynamiquement en Java

Je ne sais pas si c'est même possible. Quoi qu'il en soit, voici mon problème: Je veux créer une classe ayant un schéma de table de base de données, par exemple, supposons que j'ai une table comme 

id - unsigned int 
username - varchar(128)
password - varchar(128)

et supposons que je puisse interroger ces données de ma base de données. Ce que je veux faire, c'est créer dynamiquement (et, bien sûr, instancier) une classe Java qui devrait ressembler à ceci:

public class User{
    private unsigned int id;
    private String username;
    private String password;
}

(en fait une ActiveRecord pour ma table)

Pouvez-vous m'aider à commencer ceci? Tnks

22
ArtoAle

Que feriez-vous do avec une classe créée dynamiquement et instanciée dont aucun autre code ne dispose?

Pour un langage typé comme Java, il est peu logique d’avoir de telles classes. Par ailleurs, la plupart des OR Mappeurs comme Hibernate sont livrés avec des outils permettant de générer de manière statique des classes à partir d'un schéma de base de données.

19
Michael Borgwardt

Techniquement, vous pouvez, via une bibliothèque de manipulation de bytecode - CGLIB, javassist, asm, bcel et autres.

Cependant, ce n'est pas la "philosophie" de Java. Java est typé statiquement, il est donc préférable de créer les classes avant l'exécution.

Jetez un coup d'œil à hibernate / eclipseLink pour Java ORM - un moyen de mapper des tables sur des objets.

17
Bozho

Je pense que ce que vous voulez, c'est la fonctionnalité fournie par Java.lang.reflect.Proxy et les classes associées.

6
Pointy

Ceci est un bon article pour commencer, mais êtes-vous sûr de devoir créer une nouvelle classe? Peut-être pourriez-vous simplement utiliser une carte?

4
pablochan

Comme @Bozho, Java est un langage à typage statique pour lequel la génération de classes à l'exécution ne peut qu'engendrer un chaos.

Dans notre monde, il est beaucoup plus pratique de générer des classes au moment de la construction, c'est-à-dire lors de la compilation. Typiquement, en utilisant le reverse engineering Hibernate , vous pouvez construire vos classes Java à partir de votre schéma de base de données et déployer ces classes dans votre application, ce qui vous donne le code Java authentique à lire, avec la garantie que votre code sera lié à votre schéma de base de données

1
Riduidel

L'article relatif à la "nouvelle" API de compilation et au document Java relatif à JavaCompiler montre comment compiler le code source Java à partir d'objets String. (Je ne sais pas si nous pouvons compiler pour générer des flux et charger les fichiers de classe en mémoire ...)

Vous pouvez charger les fichiers de classe ultérieurement avec un URLClassLoader et créer des instances (API de reclection/invocation)

1
Andreas_D

Vous pouvez générer du texte source Java et utiliser le package javax.tools pour le compiler et un chargeur de classes pour le charger. Googler donne quelques exemples de la façon dont cela peut être fait, mais je n’ai jamais essayé une telle chose, alors je ne sais pas quels problèmes vous pourriez rencontrer. Clairement, Java n’était pas conçu pour de telles choses.

0
Sergei Tachenov

Je suppose que l'objectif final est d'avoir un code semblable à ActiveRecord pour écrire un accès à la base de données. Si tel est le cas, vous pouvez jeter un coup d'œil à l'implémentation Java d'ActiveRecord: http://code.google.com/p/activejdbc/

à votre santé,

igor

0
ipolevoy

Ancienne question et si cela est possible, vous devriez éviter de générer une classe pendant l'exécution, mais vous devez parfois le faire. Donc, vous pouvez utiliser Javassist et voici un exemple ...

J'ai créé un petit exemple ici: http://hrabosch.com/2018/04/08/generate-class-during-runtime-with-javassist/

Mais voici le point principal:

public static Class generateClass(String className, String methodName, String methodBody)
  throws CannotCompileException {
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.makeClass(className);
StringBuffer method = new StringBuffer();
method.append("public void ")
      .append(methodName)
      .append("() {")
      .append(methodBody)
      .append(";}");
cc.addMethod(CtMethod.make(method.toString(), cc));
return cc.toClass();
}

Donc, ce que j'ai fait ... J'ai créé un cours dans ClassPool via Javassist. De plus, j'ai ajouté une méthode dans cette classe et, par réflexion, je l'ai invoquée. 

J'espère que ça aide.

N'oubliez pas ce que vous voulez utiliser dans une classe générée, car NE SONT PAS des importations, vous devez donc utiliser des noms entièrement qualifiés.

0
Hrabosch

Oui, il est possible de compiler des classes au moment de l'exécution. Je l'ai déjà fait auparavant dans la recherche sur les algorithmes génétiques. Son possible en utilisant l'interface intégrée au compilateur. Un article sur Java World décrit l'approche de base: http://www.javaworld.com/javaworld/jw-06-2006/jw-0612-dynamic.html?page=3

0
troutinator

Voici une solution basée sur Nice CGLib:

http://code.google.com/p/cglib-wrappers/wiki/Wrappers

0
Ondra Žižka