具有动态字段的Java类

Aar*_*lla 6 java field dynamic

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

一些设计目标:

  • 如果可能的话,在没有强制转换的情况下键入safe,以用于动态字段的自定义代码(该代码将来自以不可预见的方式扩展模型的插件).
  • 性能良好(你能打败HashMap吗?也许在设置过程中使用数组并为字段分配索引?)
  • 字段"重用"(即如果您在多个位置使用相同类型的字段,则应该可以将其定义一次然后重复使用).
  • 计算字段取决于其他字段的值
  • 当字段更改值时(不一定通过Beans API),应发送信号
  • "自动"父子关系(当您将子项添加到父项时,子项中的父指针应设置为"free").
  • 容易明白
  • 使用方便

请注意,这是一个"圈外思考"的问题.我将在下面发布一个例子让你心情愉快:-)

Aar*_*lla 2

显而易见的答案是使用 a (如果您关心字段的顺序,则使用HashMapa )。LinkedHashMap然后,您可以通过get(String name)set(String name, Object value)方法添加动态字段。

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

为了避免转换问题,您可以使用类型安全的对象映射

    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 );
Run Code Online (Sandbox Code Playgroud)

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

TypedMapKey<String> KEY1 = new TypedMapKey<String>( "key1" );
TypedMapKey<List<String>> KEY2 = new TypedMapKey<List<String>>( "key2" );
Run Code Online (Sandbox Code Playgroud)

表现会很OK。

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

Future计算字段可以使用存储执行计算的实例的第二个映射来实现。

由于所有操作仅通过两种(或至少几种)方法进行,因此发送信号很简单,并且可以按照您喜欢的任何方式完成。

要实现自动父/子处理,请在子项的“设置父项”信号上安装一个信号侦听器,然后将子项添加到新父项(如有必要,将其从旧父项中删除)。

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

  • @Aaron:你的地图不是类型安全的,你只是通过使用未经检查的强制转换来愚弄编译器。例如,如果您声明 TypedMapKey&lt;List&lt;String&gt;&gt; KEY2 = new TypedMapKey&lt;List&lt;String&gt;&gt;( "key1" );`,代码将编译,但您将收到运行时类转换异常。 (2认同)