通过反射比较两个相同类型的对象中的值是否相同

今天写代码的时候有这样一个需求:

需要验证两个相同类型的不同对象中的属性值是否相同。

传统方式是分别读取两个对象中的属性值,对其进行一一比对,不停if-else。

但是如果有上百个属性值难道你也要去读取上百次,然后写上百个if-else嘛?!

so……用反射吧!

利用语言的反射机制自动遍历对象中的所有属性字段以及属性值,并比较其是否相同。

先上C#的核心代码(emmm……对,后来我又写了个Java版代码)

/// <summary>
/// 判断两个相同类型的对象的属性值是否相等
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj1"></param>
/// <param name="obj2"></param>
/// <returns></returns>
private static bool CompareProperties<T>(T obj1, T obj2)
{
    //为空判断
    if (obj1 == null && obj2 == null)
    {
        return true;
    }
    else if (obj1 == null || obj2 == null)
    {
        return false;
    }

    PropertyInfo[] properties = obj1.GetType().GetProperties();
    foreach (var po in properties)
    {
        if (!po.GetValue(obj1, null).Equals(po.GetValue(obj2, null)))
        {
            return false;
        }
    }

    return true;
}

C#版完整demo代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace CommandLineTest
{
    class Program
    {
        static void Main(string[] args)
        {
            User user1 = new User
            {
                Age = 20,
                Name = "Young",
                BirthDay = DateTime.Now,
                Height = 1.7M
            };

            User user2 = new User
            {
                Age = 20,
                Name = "Young",
                BirthDay = DateTime.Now,
                Height = 1.7M
            };

            if (CompareProperties(user1, user2))
            {
                Console.WriteLine("对象属性值相同。");
            }
            else
            {
                Console.WriteLine("对象属性值不同!");
            }

            Console.ReadLine();
        }

        /// <summary>
        /// 判断两个相同类型的对象的属性值是否相等
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj1"></param>
        /// <param name="obj2"></param>
        /// <returns></returns>
        private static bool CompareProperties<T>(T obj1, T obj2)
        {
            //为空判断
            if (obj1 == null && obj2 == null)
            {
                return true;
            }
            else if (obj1 == null || obj2 == null)
            {
                return false;
            }

            PropertyInfo[] properties = obj1.GetType().GetProperties();
            foreach (var po in properties)
            {
                if (!po.GetValue(obj1, null).Equals(po.GetValue(obj2, null)))
                {
                    return false;
                }
            }

            return true;
        }
    }

    class User
    {
        /// <summary>
        /// 年龄
        /// </summary>
        public int Age { get; set; }

        /// <summary>
        /// 姓名
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 生日
        /// </summary>
        public DateTime BirthDay { get; set; }

        /// <summary>
        /// 身高
        /// </summary>
        public decimal Height { get; set; }
    }
}

下面是Java版本的核心代码:

/**
 * 判断两个相同类型的对象的属性值是否相等
 * @param obj1
 * @param obj2
 * @return
 * @throws IllegalAccessException
 * @throws IntrospectionException
 * @throws InvocationTargetException
 */
private static boolean CompareProperties(Object obj1, Object obj2) throws IllegalAccessException, IntrospectionException, InvocationTargetException {
    //为空判断
    if (obj1 == null && obj2 == null) {
        return true;
    } else if (obj1 == null || obj2 == null) {
        return false;
    }

    Class<?> classType = obj1.getClass();
    //如果传入的类型不一样则直接返回false
    //C#中通过CompareProperties<T>中的<T>可以限定传入的类型必须一致,所以不需要该判断
    if (classType != obj2.getClass()) {
        return false;
    }

    Field[] fields = obj1.getClass().getDeclaredFields();//获得所有字段
    for (Field field : fields) {
        PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), classType);//获得类中字段的属性描述
        Method getMethod = propertyDescriptor.getReadMethod();//从属性描述中获得字段的get方法
        //通过getMethod.invoke(obj)方法获得obj对象中该字段get方法返回的值
        if (!getMethod.invoke(obj1).equals(getMethod.invoke(obj2))) {
            return false;
        }
    }

    return true;
}

Java版完整demo代码如下:

package com.company;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Scanner;

public class CompareProperties {
    public static void main(String[] args) throws IllegalAccessException, IntrospectionException, InvocationTargetException {
        User user1 = new User();
        user1.setAge(20);
        user1.setName("Young");
        user1.setBirthday(new Date());
        user1.setHeight(1.7);

        User user2 = new User();
        user2.setAge(20);
        user2.setName("Young");
        user2.setBirthday(new Date());
        user2.setHeight(1.7);

        if (CompareProperties(user1, user2)) {
            System.out.println("对象属性值相同。");
        } else {
            System.out.println("对象属性值不同!");
        }

        Scanner in = new Scanner(System.in);
        String pause = in.nextLine();
    }

    /**
     * 判断两个相同类型的对象的属性值是否相等
     * @param obj1
     * @param obj2
     * @return
     * @throws IllegalAccessException
     * @throws IntrospectionException
     * @throws InvocationTargetException
     */
    private static boolean CompareProperties(Object obj1, Object obj2) throws IllegalAccessException, IntrospectionException, InvocationTargetException {
        //为空判断
        if (obj1 == null && obj2 == null) {
            return true;
        } else if (obj1 == null || obj2 == null) {
            return false;
        }

        Class<?> classType = obj1.getClass();
        //如果传入的类型不一样则直接返回false
        //C#中通过CompareProperties<T>中的<T>可以限定传入的类型必须一致,所以不需要该判断
        if (classType != obj2.getClass()) {
            return false;
        }

        Field[] fields = obj1.getClass().getDeclaredFields();//获得所有字段
        for (Field field : fields) {
            PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), classType);//获得类中字段的属性描述
            Method getMethod = propertyDescriptor.getReadMethod();//从属性描述中获得字段的get方法
            //通过getMethod.invoke(obj)方法获得obj对象中该字段get方法返回的值
            if (!getMethod.invoke(obj1).equals(getMethod.invoke(obj2))) {
                return false;
            }
        }

        return true;
    }
}

class User {
    //年龄
    private int Age;

    //姓名
    private String Name;

    //生日
    private Date Birthday;

    //身高
    private double Height;

    public int getAge() {
        return Age;
    }

    public void setAge(int age) {
        Age = age;
    }

    public String getName() {
        return Name;
    }

    public void setName(String name) {
        Name = name;
    }

    public Date getBirthday() {
        return Birthday;
    }

    public void setBirthday(Date birthday) {
        Birthday = birthday;
    }

    public double getHeight() {
        return Height;
    }

    public void setHeight(double height) {
        Height = height;
    }
}

写下来最大的感触是:Java比C#繁琐了很多

原文地址:https://www.cnblogs.com/chenyangsocool/p/9183617.html