在Java中如何比较两个对象浅析
itnanba · 99浏览 · 发布于2021-11-25 +关注

在工作中我们经常会遇到这样的需求——比较两个对象是否相等,如果不相等的话,取出不相等的字段,这篇文章主要给大家介绍了关于在Java中如何比较两个对象的相关资料,需要的朋友可以参考下

Common Lang 中的 Builder 包内提供了一个 DiffBuilder 类,可以比较两个对象,并返回不同的部分。

  1. 首先在要比较对象的类中实现 Diffable 接口,然后实现 DiffResult diff(T obj)  方法。

  2. 在DiffResult diff(T obj)  方法中,新建一个 DiffBuilder 对象,把需要比较的类属性一一放入 DiffBuilder 中。

DiffBuilder 的构造函数有三个入参,lhs 是当前对象,rhs 是要比较的对象,style 是比较结果输出的格式。

DiffBuilder(final T lhs, final T rhs,
        final ToStringStyle style)


假设有一个 Person 类定义了三个属性 name、age 和 smoker。以下是使用不同的 ToStringStyle 所对应的输出内容。 

ToStringStyle 说明 输出
SHORT_PREFIX_STYLE 简短 Person[name=deniro,smoker=false] differs from Person[name=jack,smoker=true]
DEFAULT_STYLE 默认 org.apache.commons.lang3.builder.Person@9f70c54[name=deniro,smoker=false] differs from org.apache.commons.lang3.builder.Person@234bef66[name=jack,smoker=true]。
MULTI_LINE_STYLE 多行 org.apache.commons.lang3.builder.Person@9f70c54[
name=deniro
smoker=false
] differs from org.apache.commons.lang3.builder.Person@234bef66[
name=jack
smoker=true
]
NO_FIELD_NAMES_STYLE 不包含类属性名 org.apache.commons.lang3.builder.Person@9f70c54[deniro,false] differs from org.apache.commons.lang3.builder.Person@234bef66[jack,true]。
SIMPLE_STYLE 简洁 deniro,false differs from jack,true。
NO_CLASS_NAME_STYLE 不包含类名 [name=deniro,smoker=false] differs from [name=jack,smoker=true]。
JSON_STYLE JSON {"name":"deniro","smoker":false} differs from {"name":"jack","smoker":true}。

感觉 NO_CLASS_NAME_STYLE 与 JSON_STYLE 看的更清楚。

完整示例:

public class Person implements Diffable<Person> {
    private static final Logger log = LoggerFactory.getLogger(Person.class);
    String name;
    int age;
    boolean smoker;
    public DiffResult diff(Person obj) {
        // No need for null check, as NullPointerException correct if obj is null
        return new DiffBuilder(this, obj, ToStringStyle.SHORT_PREFIX_STYLE)
                .append("name", this.name, obj.name)
                .append("age", this.age, obj.age)
                .append("smoker", this.smoker, obj.smoker)
                .build();
    }
    public static void main(String[] args) {
        Person a = new Person();
        a.name = "deniro";
        a.age = 22;
        a.smoker = false;
        Person b = new Person();
        b.name = "jack";
        b.age = 22;
        b.smoker = true;
        DiffResult result = a.diff(b);
        log.info("result -> {}。", result);
    }
}


输出: 

result -> Person[name=deniro,smoker=false] differs from Person[name=jack,smoker=true]。

如果是个大类,那么需要很多个 append 方法把这个大类的属性放到 DiffBuilder 中,不太方便。可以写个程序生成 DiffBuilder 初始化代码,或者尝试用反射来优化这部分代码。

反射扩展:

(1)获取对象所属类的Class方法。

Class c = Class.forName("包.类名称");


(2)获得该类的所有Filed(不包括父类)。

Field[] fields = c.getDeclaredFields();


(3)将所有属性的访问权限设为true。 

因为JavaBean中所有的属性访问权限都是private,所以无法直接获得所有属性,因此我们必须获得其访问权限,通过下面的方法完成:

setAccessible(true);


(4)输出对象属性 

f.getField(对象名称);


(5)获取字段名 

fields[j].getName()


(6)获取字段值 

fields[j].get(obj)


参考资料 

commons.apache.org/proper/comm


 


相关推荐

PHP实现部分字符隐藏

沙雕mars · 972浏览 · 2019-04-28 09:47:56
Java中ArrayList和LinkedList区别

kenrry1992 · 432浏览 · 2019-05-08 21:14:54
Tomcat 下载及安装配置

manongba · 547浏览 · 2019-05-13 21:03:56
JAVA变量介绍

manongba · 601浏览 · 2019-05-13 21:05:52
什么是SpringBoot

iamitnan · 549浏览 · 2019-05-14 22:20:36
加载中

0评论

评论
分类专栏
小鸟云服务器
扫码进入手机网页