对象拷贝后验证属性一致的核心是比内容而非引用,需避免==、重写equals与hashcode、用objects.equals处理null及包装类型,反射或json序列化可作通用方案,集合校验须逐元素比对。

对象拷贝后验证属性是否一致,核心是比内容、不比引用。直接用 == 肯定不行——它只看是不是同一个内存地址;而拷贝后的对象必然地址不同,即使所有字段一模一样也会返回 false。关键在于逐字段比值,并妥善处理 null、包装类型、集合、嵌套对象等边界情况。
重写 equals 方法(推荐用于固定类)
这是最规范、可复用的方式,尤其适合你控制源码的实体类(如 Person、User):
- 在类中覆盖
equals(Object obj),先判空和类型,再逐个比较字段值 - 务必同时重写
hashCode(),否则放进HashSet或作为HashMap键时行为异常 - 字符串用
Objects.equals(a, b),自动处理null;基本类型用==;包装类型也用Objects.equals
用反射通用比对(适合临时校验或不确定类型)
当面对多个不同类、或无法修改源码时,可用反射遍历所有声明字段做值比对:
- 获取两个对象的
Class,检查字段数量和名称是否一致(注意:仅靠下标顺序匹配有风险,建议按字段名排序后比) - 对每个同名字段,设为
accessible = true,读取值后用Objects.equals比较 - 特别注意:数组、集合、嵌套对象需递归比较,或转为 JSON 字符串再比(简单但有性能和精度代价)
转 JSON 字符串比对(快但有局限)
适用于调试、测试或结构简单、无敏感字段的场景:
- 用
ObjectMapper(Jackson)或Gson将两个对象序列化为字符串,再用.equals()比较 - 优点:代码极简,天然跳过引用问题,支持嵌套和集合
- 缺点:忽略字段顺序(取决于序列化器配置)、丢失类型信息(如
int和Integer可能表现一致)、不处理 transient 字段、可能因时间戳/随机值导致误判
集合中多个对象批量校验一致性
如果拷贝的是一个列表(比如 List<user></user>),要确认“所有元素属性完全一致”,不能只比首尾:
- 先确保集合大小相同
- 按索引一一配对,调用上述任一方式(如
user1.equals(user2))校验每对 - 或者用 Stream:
list1.size() == list2.size() && IntStream.range(0, list1.size()).allMatch(i -> list1.get(i).equals(list2.get(i)))











