我想开发一个bindTo
实用程序方法,该方法初始化对象(即target
)的所有字段,其中包含Map<String, Object>
(其中关键是字段的名称)中的所有兼容值。考虑f
代表target
对象中的一个字段,vals
是包含初始化值的Map
,因此我必须:
- 检查映射
vals
是否包含一个键等于字段名的条目。 - 如果该条目存在,那么我必须检查其值是否与字段的类型兼容。
- 如果是,那么我必须将该值设置为
target
对象中的f
字段。
对应以下代码:
/*
* 1. checks if the map `vals` contains an entry with a key equals to the field name:
*/
String fName = f.getName();
if(vals.containsKey(fName)){
/*
* 2. if that entry exists, then checks if its value is compatible with the field’s type:
*/
Class<?> fType = f.getType();
Object fValue = vals.get(fName);
if(fType.isAssignableFrom(fValue.getClass())){
/*
* 3. and if it is, then set that value to the field `f` in the `target` object:
*/
f.setAccessible(true);
f.set(target, fValue);
}
}
然而,当我们有基本类型字段时,这种方法不起作用,因为包装器类型与相应的基本类型不兼容。例如,Integer
类型与int
类型不兼容,因此不满足条件:fType.isAssignableFrom(fValue.getClass())
那么,你有什么建议来抑制这个限制的基本类型字段吗?
如果目标字段是一个基本类型,那么您可以通过反射获得它的默认值,该值反过来将被封装在包装器对象中。从这个对象中可以得到相应的包装器类型。因此,您可以替换以下代码行:
Class<?> fType = f.getType();
:
Class<?> fType = f.getType();
if(fType.isPrimitive()){
fType = f.get(target).getClass();
}
您可以使用辅助服务来获取原语的相应包装类型,例如下面提供的WrapperUtilites
类的toWrapper
方法。所以我们不写
Class<?> fType = f.getType();
你可以写:
Class<?> fType = WrapperUtilites.toWrapper(f.getType());
WrapperUtilites
可以写为:
class WrapperUtilites{
final static Map<Class<?>, Class<?>> wrappers = new HashMap<>();
static{
wrappers.put(boolean.class, Boolean.class);
wrappers.put(short.class, Short.class);
wrappers.put(int.class, Integer.class);
…
// do this for all primitive types
}
public static Class<?> toWrapper(Class<?> c){
return c.isPrimitive()? wrappers.get(c) : c;
}
}