Slytael
Slytael

Reputation: 113

Object with dynamic fields / Hashmap with different values in Java

We are doing some knowledge discovery in Databases in Java.

We have different databases we know nothing about.

An example scenario: We want to check if an entity has the property name and rename it. In python / js / dynamic languages that would be trivial:

if Object.hasKey(name) => Object.name = "Jordan"

Is there a way to store and manipulate generic objects at all in java? Obviously classes are out of the way, since we don't know the object structure. Hashmaps also don't cut it, because the object can have all SQL types as property-types, and Hashmaps are limited to homogeneous fields.

Upvotes: 1

Views: 3485

Answers (3)

talex
talex

Reputation: 20542

You can use hashmap anyway.

Map<Strung, Object> map = new Hashmap<>();
map.put("name", new Integer());
map.put("another name", new String());

String value = (String)map.get("another name");
String value = (String)map.get("name"); // You get error here because integer type stored in map.
// check with 'instanceof' for type if necessary

All works fine

Upvotes: 2

Ian2thedv
Ian2thedv

Reputation: 2701

You can use reflection to change private fields of an object.

Say we have a Human object, with a name field:

public static class Human {
    private String name;

    public Human(String name) {
        this.name = name;
    }

    public String toString() {
        return new StringBuilder("Name: ").append(this.name).toString();
    }
}

Like the some of the other answers suggested, you can use a HashMap<String, Object> to store any object. You simply iterate through the map and pass the each object to the following method:

public static void changeName(Object obj, String newName) throws IllegalArgumentException, IllegalAccessException {
    for (Field f:obj.getClass().getDeclaredFields()) {
        if (f.getName().toLowerCase().equals("name")) {
            f.setAccessible(true);
            f.set(obj, newName);
            f.setAccessible(false);
        }
    }
}

This method retrieve all fields of the object and compare the field name to "name". If a field is identified, it will change accessibility (in case of private fields) and change the field value to newName.

Human me = new Human("Ian");
System.out.println(me);
changeName(me, "Jan");
System.out.println(me);

Output:

Name: Ian
Name: Jan

Upvotes: 1

Ernest Sadykov
Ernest Sadykov

Reputation: 831

In addition to @dotvav comment, take a look at Apache Commons BeanUtils, which simplifies working with reflection.

Example:

Map<String, String> props = BeanUtils.describe(someObject);
if (props.containsKey("name")) {
    BeanUtils.setProperty(someObject, "name", "value");
}

Upvotes: 1

Related Questions