今天写代码的时候有这样一个需求:
需要验证两个相同类型的不同对象中的属性值是否相同。
传统方式是分别读取两个对象中的属性值,对其进行一一比对,不停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#繁琐了很多