Java classes with dynamic fields

后端 未结 5 723
孤独总比滥情好
孤独总比滥情好 2021-02-06 10:55

I\'m looking for clever ways to build dynamic Java classes, that is classes where you can add/remove fields at runtime. Usage scenario: I have an editor where users should be ab

相关标签:
5条回答
  • 2021-02-06 11:05

    I do almost the same, it's pure Java solution:

    1. Users generate their own models, which are stored as JAXB schema.
    2. Schema is compiled in Java classes on the fly and stored in user jars
    3. All classes are forced to extend one "root" class, where you could put every extra functionality you want.
    4. Appropriate classloaders are implemented with "model change" listeners.

    Speaking of performance (which is important in my case), you can hardly beat this solution. Reusability is the same of XML document.

    0 讨论(0)
  • 2021-02-06 11:09

    The obvious answer is to use a HashMap (or a LinkedHashMap if you care for the order of fields). Then, you can add dynamic fields via a get(String name) and a set(String name, Object value) method.

    This code can be implemented in a common base class. Since there are only a few methods, it's also simple to use delegation if you need to extend something else.

    To avoid the casting issue, you can use a 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 );
    

    The trick here is the key which contains the type information:

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

    The performance will be OK.

    Field reuse is by using the same value type or by extending the key class of the type-safe object map with additional functionality.

    Calculated fields could be implemented with a second map that stores Future instances which do the calculation.

    Since all the manipulation happens in just two (or at least a few) methods, sending signals is simple and can be done any way you like.

    To implement automatic parent/child handling, install a signal listener on the "set parent" signal of the child and then add the child to the new parent (and remove it from the old one if necessary).

    Since no framework is used and no tricks are necessary, the resulting code should be pretty clean and easy to understand. Not using String as keys has the additional benefit that people won't litter the code with string literals.

    0 讨论(0)
  • So basically you're trying to create a new kind of object model with more dynamic properties, a bit like a dynamic language?

    Might be worth looking at the source code for Rhino (i.e. Javascript implemented in Java), which faces a similar challenge of implementing a dynamic type system in Java.

    Off the top of my head, I suspect you will find that internal HashMaps ultimately work best for your purposes.

    I wrote a little game (Tyrant - GPL source available) using a similar sort of dynamic object model featuring HashMaps, it worked great and performance was not an issue. I used a few tricks in the get and set methods to allow dynamic property modifiers, I'm sure you could do the same kind of thing to implement your signals and parent/child relations etc.

    [EDIT] See the source of BaseObject how it is implemented.

    0 讨论(0)
  • 2021-02-06 11:18

    Type safe without casts if possible for custom code that works on the dynamic fields (that code would come from plugins which extend the model in unforeseen ways)

    AFAIK, this is not possible. You can only get type-safety without type casts if you use static typing. Static typing means method signatures (in classes or interfaces) that are known at compile time.

    The best you can do is have an interface with a bunch of methods like String getStringValue(String field), int getIntValue(String field) and so on. And of course you can only do that for a predetermined set of types. Any field whose type is not in that set will require a typecast.

    0 讨论(0)
  • 2021-02-06 11:28

    You can use the bytecode manipulation libraries for it. Shortcoming of this approach is that you need to do create own classloader to load changes in classes dynamically.

    0 讨论(0)
提交回复
热议问题