如何在java中动态创建一个类

时间:2011-01-25 14:41:23

标签: java reflection activerecord

我不知道这是否可行。无论如何,这是我的问题: 我想创建一个具有数据库表模式的类,例如假设我有一个像

这样的表
id - unsigned int 
username - varchar(128)
password - varchar(128)

我们假设我可以从我的数据库中查询这些数据。我想要做的是动态创建(当然,实例化)一个看起来像这样的Java类:

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

(实际上我的桌子是ActiveRecord

你可以帮我开始吗? TNKS

11 个答案:

答案 0 :(得分:19)

您将使用动态创建并实例化的类(您的其他代码都不知道)做什么

对于像Java这样的静态类型语言,拥有这样的类是没有意义的。另一方面,像Hibernate这样的大多数OR Mappers都带有允许您从数据库模式静态生成类的工具。

答案 1 :(得分:17)

从技术上讲,你可以通过字节码操作库 - CGLIB,javassist,asm,bcel等。

然而,这不是Java的“哲学”。 Java是静态类型的,因此您最好在运行时之前创建类。

查看{ORM的hibernate / eclipseLink - 一种将表映射到对象的方法。

答案 2 :(得分:6)

我认为你想要的是java.lang.reflect.Proxy及相关课程提供的设施。

答案 3 :(得分:4)

This是一篇很好的文章,但你确定你需要真正创建一个新类吗?也许你可以使用Map?

答案 4 :(得分:1)

与@Bozho状态一样,Java是一种静态类型语言,在运行时生成类只会导致混乱。

在我们的世界中,在构建时生成类更方便,也就是说在编译期间。使用Hibernate reverse engineering,您可以在构建时从数据库模式构建Java类,并在应用程序中部署这些类,从而为您提供真实的Java代码,并保证您的代码将被绑定到您的数据库架构

答案 5 :(得分:1)

The Article关于“新”编译器API和JavaCompiler的java文档显示了如何从String对象编译java源代码的方法。 (我不知道我们是否可以编译输出流并将类文件加载到内存中......)

您可以稍后使用URLClassLoader加载类文件并创建实例(reclection / invocation API)

答案 6 :(得分:0)

是的,可以在运行时编译类。我之前在遗传算法研究中做过。它可以使用编译器的内置接口。 Java World上的一篇文章介绍了基本方法:http://www.javaworld.com/javaworld/jw-06-2006/jw-0612-dynamic.html?page=3

答案 7 :(得分:0)

您可以生成Java源文本并使用javax.tools包进行编译,并使用类加载器加载它。谷歌搜索提供了一些如何做到的例子,但我从未尝试过这样的事情,所以我不知道你可能会遇到什么问题。显然,Java并不是为这些东西设计的。

答案 8 :(得分:0)

我认为最终目标是使用类似ActiveRecord的代码来编写数据库访问。如果是这种情况,您可以查看ActiveRecord的Java实现: http://code.google.com/p/activejdbc/

欢呼声,

伊戈尔

答案 9 :(得分:0)

这是一个很好的基于CGLib的解决方案:

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

答案 10 :(得分:0)

旧问题,如果有可能,你应该避免在运行时生成类,但有时你必须这样做。所以你可以使用Javassist,这里是例子......

我在这里创建了一个小例子:http://hrabosch.com/2018/04/08/generate-class-during-runtime-with-javassist/

但这是重点:

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

所以我做了...通过Javassist我在ClassPool中创建了一个类。我还在这个类中添加了一个方法,并通过反射调用它。

希望它有所帮助。

  

请记住要在生成的类中使用的任何内容   不是导入,因此您必须使用完全限定名称。