【问题标题】:Dynamically create classes in Java在 Java 中动态创建类
【发布时间】:2011-04-16 09:48:39
【问题描述】:

我想根据我的 XML 配置文件中定义的字段在 Java 中创建一个类:

例如:如果 XML 文件包含(语法已被恶意张贴):

<property name="agent_host"></property>
<property name="subsystem"></property>

然后它会在内部创建一个类事件,例如客户端可以实例化的 Event(String agentHost, String subSystem)。注意:客户端总是知道这个类将被称为“事件”,但不知道它需要传递多少个“强制参数”。

另一方面,如果我有一个 XML 文件:

<property name="agent_host"></property>

然后它将创建客户端可用于实例化的 Event(String eventHost)。

【问题讨论】:

  • 您想为静态编译生成代码(.java 文件)吗?还是要在运行时生成代码?
  • 代码(事件类)应该在运行时可用
  • 在这种情况下,该类的用户将如何实例化它(因为他们没有编译时引用)?你预计他们会使用反射吗?
  • 这会起作用..反射。但是他们已经知道他们需要创建一个 Event 类的实例。为方便起见,类Event构造函数所需的参数个数应该等于XML文件中属性字段的个数
  • 不,确切地说,他们已经知道他们需要创建一个命名“Event”类的实例,这完全不同。我倾向于同意以下@Bill 的观点,即这对您或您的消费者来说都不会是一次愉快的体验。您能否详细说明您认为动态生成此类而不是使用像地图这样的松散数据结构有什么优势?

标签: java class dynamic


【解决方案1】:

是的,您可以使用反射,但我想到的是使用可以添加属性的类。 想象一个类,它有一个封装的 HashMap,使用 String 作为键(用于属性名称)和属性的值,这样您就可以读取 XML 文件并为每个属性添加属性到类中。 对于这一行:

<property name="subsystem" type="String">value123</property>


GenericClass c = new GenericClass();
c.addAttribute("subsystem", new String("value123"));
//and you could implement a get and set methods like this:
public String getAttributeValue(String attributeName)
{
   return internalHashMap.get(attributeName).toString();
}

使用这个你也可以实现一个 setAttributeValue 我认为会很简单

【讨论】:

  • 为什么是hashMap?我也可以使用 LinkList 来做到这一点?
  • 请注意:setAttributeValue() 的简单实现可能会允许类的用户将值设置为 XML 中未定义的属性,从而创建它们。这可能是一个问题,具体取决于 OP 的需求。
  • 是的,我知道,所以你应该在尝试设置一个不存在的属性时抛出一个异常,我认为 IlegallArgumentException 就可以了......而且是一个 Hashmap,所以你可以使用 Map 属性名称它所具有的价值。您可以使用 LinkedList,但您必须创建一个封装属性名称和值的类。所以,使用 Hashmap,更简单
  • 非常感谢。我有一个类似的问题,并且即将过度设计。使用一些辅助方法扩展 Map 的简单类对我有用!
【解决方案2】:

这不是你真正想要的类,它是数据。为什么不使用哈希图?我真的不喜欢“Bean”风格的类——它们鼓励糟糕的编码(在生成的类中没有放置实际代码的地方,所以一切最终都被外部代码操纵)。

你可以从你的 XML 中加载一个 hashmap 并将它注入到一个真实的对象中——这样你就不必担心实际传递一个 hash,你传递的是一个带有真实业务方法和真实类型的真实对象安全性——只是碰巧在内部使用哈希图而不是成员变量来存储数据。

我做的远不止这些,但在某些时候你会意识到 Hibernate 会为你做你想做的一切。

【讨论】:

  • 如果值有不同的类型怎么办,比如说一些是整数,一些是字符串,一些是双精度。并且必须保留该类型信息。
  • 如果只是数据,不直接在代码中使用,那么类型不应该被语言强制,没有意义。如果您需要类型信息,则将其作为更多数据进行跟踪。如果您打算在代码中使用它,那么在我见过的每种情况下,使用 bean 模式都会导致错误的代码,您应该使用带注释的休眠对象——一个可以包含业务逻辑而不仅仅是 bean 的对象。
【解决方案3】:

我认为来自 Commons-BeanUtils 的 DynaBean 可能是您想要的。

DynaBean 是一个 Java 对象,它支持可以动态修改其名称和数据类型以及值的属性。 BeanUtils 包的其他组件将在最大程度上识别此类 bean 并将它们视为标准 JavaBeans,以便检索和设置属性值。

【讨论】:

    【解决方案4】:

    如果您真的对动态创建类感兴趣,请尝试字节码增强库,例如来自 Apache 的 BCEL

    【讨论】:

      猜你喜欢
      • 2011-04-05
      • 2016-10-24
      • 2017-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-29
      • 1970-01-01
      相关资源
      最近更新 更多