一、操作环境
jdk:1.8
hutools:5.7.17
二、问题点
在使用BeanUtil.copyProperties进行对象拷贝时,A类定义一个String类型名称为C的字段,B类定义一个BigDecimal类型名称也为C的字段,将A类对象拷贝给B,当A类对象中的C字段属性值为一个空字符串时,B类对象的C字段属性值为0。
三、原因分析
这里不用实际的业务代码,以自己的测试代码为例
1、源类
package com.example20.copy;
import lombok.Data;
/**
* 简单描述该类
*
* @author LiuZhuzheng
* @date 2023/8/15 11:20
*/
@Data
public class Source {
private String price;
private Integer num;
}
2、目标类
package com.example20.copy;
import lombok.Data;
import java.math.BigDecimal;
/**
* 简单描述该类
*
* @author LiuZhuzheng
* @date 2023/8/15 11:20
*/
@Data
public class Target {
private BigDecimal price;
private Long num;
}
3、测试入口
package com.example20.copy;
import cn.hutool.core.bean.BeanUtil;
/**
* 简单描述该类
*
* @author LiuZhuzheng
* @date 2023/8/15 11:20
*/
public class CopyTest {
public static void main(String[] args) {
Source source = new Source();
source.setPrice("");
source.setNum(2);
Target target = BeanUtil.copyProperties(source, Target.class);
System.out.println(target.getPrice());
System.out.println(target.getNum());
}
}
4、debug分析
首先直接进入copyProperties方法,往下走会走到一个copy方法,
进入其中,这里不是map相关拷贝,会走最下面的beanToBean
接着来到valueProviderToBean
进去,这里就是拷贝方法的主题逻辑地方,首先会判断 源对象不为空再进行拷贝,接下来的一堆拷贝参数的处理,这里我进行拷贝的时候没有传CopyOptions相关参数,因此会跳过,到下面就是遍历目标对象的属性值,先判断源对象是否有相同的属性字段名称,存在再调用value方法获取到相应的值并赋值给目标对象
之后进入value方法
选择BeanValueProvider的实现
继续往下走进入getValue方法
这里不再关心getValue方法的返回值,它会返回源对象的空字符串,接着看下面的数据转换,
进入convert方法内部,这里用到的时Number的转换器
继续进入Number的convert 内,首先进入的时抽象基本类AbstractConverter的convert方法,
这里进行一些空值判断,随后进入NumberConverter的convertInternal,其调用自身的convert,
判断目标对象的字段类型为BigDecimal,进入toBigDecimal方法
源字段类型为String,因此进入NumberUtil.toBigDecimal
可以看到,在此处,当源对象为空字符串时,目标对象的会赋值为BigDecimal.ZERO。