代码之家  ›  专栏  ›  技术社区  ›  rjmunro

具有动态字段的Java类

  •  6
  • rjmunro  · 技术社区  · 6 年前

    我正在寻找构建动态Java类的巧妙方法,也就是可以在运行时添加/删除字段的类。使用场景:我有一个编辑器,用户应该可以在运行时向模型添加字段,甚至可以在运行时创建整个模型。

    一些设计目标:

    • 如果可能,对于在动态字段上工作的自定义代码,可以使用不带强制转换的类型安全(该代码将来自以不可预见的方式扩展模型的插件)。
    • 性能好(你能打败 HashMap ?可能在安装过程中使用数组并为字段分配索引?)
    • 字段“重用”(即,如果在多个地方使用同一类型的字段,应该可以定义一次,然后重用它)。
    • 依赖于其他字段值的计算字段
    • 当字段改变值时,应该发送信号(不一定通过beans api)
    • “自动”父子关系(将子对象添加到父对象时,子对象中的父指针应设置为“自由”)。
    • 容易理解
    • 易于使用

    注意,这是一个“跳出圈子思考”的问题。我将在下面发布一个示例,让您有心情:-)

    5 回复  |  直到 13 年前
        1
  •  2
  •   Stephen C    15 年前

    对于在动态字段上工作的自定义代码,如果可能,可以使用不带强制转换的类型安全(该代码将来自以不可预见的方式扩展模型的插件)

    阿飞,这是不可能的。如果使用静态类型,则只能在不使用类型转换的情况下获得类型安全性。静态类型表示在编译时已知的方法签名(在类或接口中)。

    你所能做的就是有一个接口,上面有很多方法,比如 String getStringValue(String field) , int getIntValue(String field) 等等。当然,您只能对预先确定的类型集执行此操作。类型不在该集合中的任何字段都需要类型转换。

        2
  •  2
  •   rjmunro    15 年前

    显而易见的答案是使用 HashMap (或) LinkedHashMap 如果你关心字段的顺序)。然后,可以通过 get(String name) 和A set(String name, Object value) 方法。

    此代码可以在公共基类中实现。因为只有几个方法,所以如果需要扩展其他方法,使用委托也很简单。

    为了避免选角问题,可以使用 type-safe object map :

        TypedMap map = new TypedMap();
    
        String expected = "Hallo";
        map.set( KEY1, expected );
        String value = map.get( KEY1 ); // Look Ma, no cast!
        assertEquals( expected, value );
    
        List<String> list = new ArrayList<String> ();
        map.set( KEY2, list );
        List<String> valueList = map.get( KEY2 ); // Even with generics
        assertEquals( list, valueList );
    

    这里的技巧是包含类型信息的密钥:

    TypedMapKey<String> KEY1 = new TypedMapKey<String>( "key1" );
    TypedMapKey<List<String>> KEY2 = new TypedMapKey<List<String>>( "key2" );
    

    表演会很好的。

    字段重用是通过使用相同的值类型,或者通过使用附加功能扩展类型安全对象映射的键类。

    计算字段可以用存储 Future 进行计算的实例。

    由于所有的操作都只发生在两个(或至少几个)方法中,所以发送信号很简单,可以按您喜欢的任何方式进行。

    要实现自动父/子处理,请在子对象的“set parent”信号上安装一个信号侦听器,然后将子对象添加到新父对象(必要时将其从旧父对象中移除)。

    由于不使用框架,也不需要技巧,因此生成的代码应该非常干净且易于理解。不使用字符串作为键还有一个好处,就是人们不会在代码中乱扔字符串文本。

        3
  •  1
  •   bcook8033    15 年前

    所以基本上你想创建一种新的对象模型,它有更多的动态属性,有点像动态语言?

    可能值得查看的源代码 Rhino (即用java实现的javascript),在用java实现动态类型系统方面也面临着类似的挑战。

    从我的头顶上,我怀疑您会发现内部哈希映射最终最适合您的目的。

    我写了一个小游戏( Tyrant - GPL source available )使用类似的具有hashmaps特性的动态对象模型,效果很好,性能也不是问题。我在get和set方法中使用了一些技巧来允许动态属性修饰符,我相信您可以做同样的事情来实现您的信号和父/子关系等。

    [编辑]请参见 source of BaseObject 如何实施。

        4
  •  1
  •   MaSEL    14 年前

    您可以使用字节码操作库。这种方法的缺点是需要创建自己的类加载器来动态加载类中的更改。

        5
  •  1
  •   Osw    14 年前

    我做的几乎一样,它是纯Java解决方案:

    1. 用户生成自己的模型,这些模型存储为jaxb模式。
    2. 模式是在Java类中即时编译并存储在 用户罐
    3. 所有的类都被迫扩展一个“根”类,在这个类中你可以放置你想要的所有额外功能。
    4. 使用“模型更改”实现适当的类加载器 听众。

    说到性能(这对我来说很重要),你很难胜过这个解决方案。可重用性与xml文档相同。