java反射机制的应用(问题记录)

        今天在写一个添加平台接口的时候,用到了java反射机制,场景是在Linux服务器上有一个保存方法接口(save),如下所示

@Transactional
@Override
public Integer save(Long modelId,String sysCode,String userId,Object object) {
    Field[] fields = object.getClass().getDeclaredFields();
    int num = 0 ;
    for(Field field: fields){
        logger.info("当前的反射字段是:"+field);
    }
    for (Field field:fields) {
        ModelProperty modelProperty = new ModelProperty();
        modelProperty.setModelProName(field.getName());
        List modelProperties = modelPropertyDao.getByCondition(modelProperty);
        InstanceData instanceData = new InstanceData();
        if (modelProperties==null || modelProperties.size()==0){
            modelProperty.setCreateTime(new Date());
            modelProperty.setModelId(modelId);
            modelProperty.setModifyTime(new Date());
            modelProperty.setCreator(userId);
            modelProperty.setPropertyType(field.getType().toString());
            modelPropertyDao.save(modelProperty);
            instanceData.setModelProId(modelProperty.getModelProId());
        }else{
            instanceData.setModelProId(modelProperties.get(0).getModelProId());
        }
        instanceData.setSyscode(sysCode);
        instanceData.setModelId(modelId);
        instanceData.setCreateTime(new Date());
        instanceData.setModifyTime(new Date());
        instanceData.setCreator(userId);
        Object result = getFieldValueByName(field.getName(),object);
        if (result != null)
            instanceData.setInstanceValue(result.toString());
        num += instanceDataDao.save(instanceData);
    }
    return num;
}
private Object getFieldValueByName(String fieldName, Object o) {
    try {
        String firstLetter = fieldName.substring(0, 1).toUpperCase();
        String getter = "get" + firstLetter + fieldName.substring(1);
        Method method = o.getClass().getMethod(getter, new Class[] {});
        Object value = method.invoke(o, new Object[] {});
        logger.info("获取到的值是:"+value);
        return value;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

   客户端调用服务器的这个接口,我开始传的是addPlatInfo.getClass,结果就是死活没有我定义的属性,都是些不认识的属性,这个问题纠结了很长时间。

@Override
public ResultMap addPlatform(String platformName, String platformImg, String platformIntroduce, String[] goodFields,String userId) {
    AddPlatInfo addPlatInfo = new AddPlatInfo();
    addPlatInfo.setPlatName(platformName);
    addPlatInfo.setImgUrl(platformImg);
    addPlatInfo.setPlatIntroduction(platformIntroduce);
    addPlatInfo.setExpertArea(getExpertArea(goodFields));

    //test(addPlatInfo,userId);

    try {
        int result = instanceDataApi.save(SystemConstant.MODELID,SystemConstant.SYSCODE,userId,addPlatInfo);
        if(result == 0){
            return dealError(new ResultMap(),"添加平台失败!");
        }
        return dealOk(new ResultMap(),"添加平台成功!");
    } catch (Exception e) {
        e.printStackTrace();
        return dealError(new ResultMap(),"添加平台失败!");
    }
}
    后来请教别人才知道调用的时候不能用addPlatInfo.getClass()作为参数,下面我把追踪的数据贴出来。
1.刚定义完addPlatInfo时查看对象,如下图所示。

2.addPlatInfo.getClass()所得到的类的属性如下图所示,发现都是些父级类的属性,没有我们定义的那四个属性。

3.addPlatInfo.getClass().getClass()所得到的类的属性如下所示,这时我们看到的属性跟第2步看到的属性一样,只是属性值不一样。

     看完了类,下面再看下反射得到的fields。代码如下:
Object obj = addPlatInfo;
Field[] fields = obj.getClass().getDeclaredFields();
获取到的fields如下图所示:

再多调一次getClass()

Field[] fieldss = obj.getClass().getClass().getDeclaredFields();
这时再看看fieldss,发现这时获取的字段已经不是我们想要的字段了,因此,客户端在传参数是一定是直接传对象本身,不能传addPlatInfo.getClass()!!!
   另外,需要说明的是,反射的对象只有在本工程下可以被识别,如果从客户端传递对象到服务端,服务端要想反射获取值的话,必须也知道这个对象才行!(当然,可以把这个对象放到一个公共的Jar包中,然后客户端和服务端都引用这个jar包也可以)

 

你可能感兴趣的:(Java)