我们如何检查对象值是否与Java中的基本类型字段兼容

时间:2014-03-19 13:45:12

标签: java reflection

我想开发一个bindTo实用程序方法,用于初始化对象的所有字段(即target),其中包含Map<String, Object>中包含的所有兼容值(其中键是该字段的名称)。 请注意f表示target对象中的字段,vals表示包含初始值的Map,因此我必须:

  1. 检查地图vals是否包含密钥等于字段名称的条目。
  2. 如果该条目存在,那么我必须检查其值是否与字段的类型兼容。
  3. 如果是,则必须将该值设置为f对象中的字段target
  4. 这对应于以下代码:

    /*
     * 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())

    那么,你有什么建议用原始类型字段来抑制这种限制吗?

2 个答案:

答案 0 :(得分:0)

如果目标字段是基本类型,则可以通过反射获取其默认值,反射又将在包装器对象中加载。从这个对象,您可以获得相应的包装类型。因此,您可以替换以下代码行:

Class<?> fType = f.getType();

使用:

Class<?> fType = f.getType();
if(fType.isPrimitive()){
  fType = f.get(target).getClass();
}

答案 1 :(得分:0)

您可以使用辅助服务来获取基元的相应包装类型,例如下面提供的toWrapper类的WrapperUtilites方法。所以不要写:

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;
      }
}