How do I cast a HashMap to a concrete class?
I have a class, lets call it Fruit, and I have a HashMap. I want to be able to initialize a new instance of Fruit, but set to the values in HashMap. So for example:
Map<String, String> map = new HashMap<String, String>();
开发者_开发问答map.put("name", "Banana");
map.put("color", "Yellow");
Then I want to be initialize a new Fruit instance like so:
Fruit myFruit = new Fruit(map);
or
Fruit myFruit = (Fruit)map;
Is this possible in Java, by means of iterating the Map?
The second is not possible because a HashMap
is not a Fruit
. You could do the first by providing a constructor that takes a Map<String, String>
argument.
public Fruit(Map<String, String> map) {
this.name = map.get("name");
this.color = map.get("color");
}
It seems like you can use reflection for this
Fruit f = new Fruit();
Class aClass = f.getClass();
for(Field field : aClass.getFields()){
if(map.containsKey(field.getName())){
field.set(f,map.get(field.getName()));
}
}
Little old but:
import com.fasterxml.jackson.databind.ObjectMapper;
...
final ObjectMapper mapper = new ObjectMapper();
final Map myObjectMapped = new HashMap();
//fill map
final Class clazz = Class.forName(MyClassToBeConverted.class.getName());
final MyClassToBeConverted convertedObj = (MyClassToBeConverted) mapper.convertValue(myObjectMapped, clazz);
...
Yes, it's possible. But you'd have to write a constructor for Fruit that knows how to pull values -- and which values -- from the map.
public Fruit(Map params) {
this.setColor(map.get("color"));
this.setName(map.get("name"));
}
I have fixed Anni's solution, now it supports inheritance, and static and final fields. By the way, I have not checked for type mismatches.
public static void populateBean(Object bean, Map<String, Object> properties) throws Exception {
Class<?> clazz = bean.getClass();
while(clazz != null) {
for (Field field : clazz.getDeclaredFields()) {
int modifiers = field.getModifiers();
if (!Modifier.isStatic(modifier) && !Modifier.isFinal(modifier)) {
if (map.containsKey(field.getName())) {
field.accessible(true);
field.set(bean, map.get(field.getName()));
}
}
}
clazz = clazz.getSuperclass();
}
}
By the way Apache BeanUtils DynaBeans almost does what you want, as far as I remember it supports Java Beans Introspection.
Maybe it could be a little slower in comparison to other solutions, but for not demanding purposes, my code works very well for me (And it is very simple and clean):
public class Utils {
static Object parseHashMapToObject(HashMap map, Class cls) {
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
String jsonString = gson.toJson(map);
return gson.fromJson(jsonString, cls);
}
}
Gson Github: https://github.com/google/gson
You would traverse the map in your constructor and assign the values. If there's an actual library for doing this(almost like a Bean), then I've never heard of it.
Casting of a HashMap to a fruit wouldn't be possible.
The second is not possible but you can create a class that will take a Map as a constructor parameter.
class Fruit{
private Map<String, String> fruitMap;
Fruit(Map<String, String> map){
}
}
Assuming the keys in map
correspond to setter methods in the Fruit
class, you could use one of Apache bean's utilities like PropertyUtils.
final Fruit f = new Fruit();
for(String key : map.keySet()) {
PropertyUtils.setProperty(fruit, key, map.get(key));
}
For very complicated cases of this you might want to take a look at Dozer. We use Dozer to map very large Maps to very large objects.
精彩评论