问题 Java元编程


我正在使用Java开发我的第一个真正的项目。虽然我对动态语言有更多的经验,但我开始对这门语言感到满意。

我有一个类似于以下的类:

class Single
{
    public void doActionA() {}
    public void doActionB() {}
    public void doActionC() {}
}

然后我有一个 SingleList 充当这些类的集合的类(具体来说,它用于2D Sprite库,“actions”是各种变换:旋转,剪切,缩放等)。我希望能够做到以下几点:

class SingleList
{
    public void doActionA() {
        for (Single s : _innerList) {
            s.doActionA();
        }
    }

    ... etc ...
}

有没有办法简单地将方法(或已知的方法列表)推迟到内部列表的每个成员?无需专门列出每个方法,然后循环每个内部成员并手动应用它?

为了使事情变得更难,方法是不同的arity,但都是返回类型“void”。


12229
2018-01-15 07:03


起源

我想你可以看看Java反射,它允许你在运行时调用方法。 - Alvin
但我仍然需要在SingleList类中生成所有方法存根。我正在寻找一个可以作为一个全能调用方法的解决方案。就像在PHP或python getattr中调用一样。 - efritz
哦,你不需要执行,使用反射你可以做SingleList.get(“someAttr”),然后反射将为你调用方法getSomeAttr()。你可以谷歌“org.springframework.beans.BeanUtils”,它有点做你想要的。如果没有人打败我,我会写一个例子作为正式答案哈哈。 - Alvin
阿尔文的建议会起作用,但变化多端的东西会使事情变得有些混乱。您可以考虑遵循“命令模式”;也就是说,使用公共抽象基类使每个操作成为不同的类。每个操作类都将操作的参数作为字段,这些将由构造函数填充。抽象基类可以声明 apply( Single ),但也定义 applyToAll( SingleList ) 甚至 applyToAll( Collection<Single> )。这应该足以让您入门;如果您需要更多帮助,请再次发帖 - Dawood ibn Kareem
访客模式应该帮助你。 - mike


答案:


不幸的是,Java并不容易在运行时支持类创建,这正是您所需要的: SingleList 需要使用必要的存根方法自动更新以匹配 Single 类。

我可以想到以下方法来解决这个问题:

  1. 使用 Java反射

    • 优点:
      • 它随时可用Java语言提供,您可以轻松找到文档和示例。
    • 缺点:
      • SingleList 上课不兼容 Single 类接口了。
      • Java编译器和任何IDE通常无法帮助通过反射调用的方法 - 编译器捕获的错误通常会转换为运行时异常。
      • 根据您的使用情况,您可能还会看到明显的性能下降。
  2. 使用构建系统以及某种源代码生成器来自动创建 SingleList.java 文件。

    • 优点:
      • 一旦你设置它,你将不再需要处理它。
    • 缺点:
      • 设置它有一定的难度。
      • 你必须单独确保 SingleList 在任何JVM中加载的类 - 或者您的IDE,就此而言 - 实际上与加载的匹配 Single 类。
  3. 手动解决此问题 - 创建界面(例如 SingleInterface或者两个类使用的基本抽象类应该有帮助,因为任何体面的IDE都会指出未实现的方法。适当的类架构可以最大限度地减少重复的代码,您的IDE可以帮助生成样板部件。

    • 优点:
      • 没有设置曲线可以克服。
      • 您的IDE将始终看到正确的类集。
      • 之后通常会改进类体系结构。
    • 缺点:
      • 一切都是手动的。
  4. 使用字节码生成库,如 了Javassist 要么 BCEL 动态生成/修改 SingleList 即时上课。

    • 优点:
      • 这种方法非常强大,可以长期节省大量时间。
    • 缺点:
      • 通常使用字节码生成库  琐事和  对于胆小的人。
      • 根据您编写代码的方式,您可能还会遇到IDE及其动态类处理问题。

11
2018-01-15 09:45



看起来手动方法是要走的路。如果我添加更多转换,我只需要确保接口保持最新状态。 - efritz