common-lang 之 CompareToBuilder

public static int reflectionCompare(Object lhs,
                                    Object rhs)

官方描述:通过反射比较两个对象

Compares two Objects via reflection


Static fields will not be compared
Transient members will be not be compared, as they are likely derived fields
Superclass fields will be compared
If both lhs and rhs are null, they are considered equal

其中静态字段不能比较,Transient成员也不能比较,超类字段会比较

当返回值为0时,表示两个对象字段信息相同,否则不同

例如:

		User user1=new User();
		user1.setAge(18).setGender("male");
		User user2=new User();
		user2.setAge(18).setGender("male");
		int result= CompareToBuilder.reflectionCompare(user1, user2);
		System.out.println(result);

返回结果:

0

源码跟进:

step 1:

 public static int reflectionCompare(
        Object lhs, 
        Object rhs, 
        boolean compareTransients, 
        Class reflectUpToClass, 
        String[] excludeFields) {

        if (lhs == rhs) {
            return 0;
        }
        //不能为空
        if (lhs == null || rhs == null) {
            throw new NullPointerException();
        }
        Class lhsClazz = lhs.getClass();
        //判断rhs是否是该Class
        if (!lhsClazz.isInstance(rhs)) {
            throw new ClassCastException();
        }
        CompareToBuilder compareToBuilder = new CompareToBuilder();
        //step 2
        reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder, compareTransients, excludeFields);
        while (lhsClazz.getSuperclass() != null && lhsClazz != reflectUpToClass) {
            //比较超类
            lhsClazz = lhsClazz.getSuperclass();
            reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder, compareTransients, excludeFields);
        }
        return compareToBuilder.toComparison();
    }

step 2:

 

 

private static void reflectionAppend(
        Object lhs,
        Object rhs,
        Class clazz,
        CompareToBuilder builder,
        boolean useTransients,
        String[] excludeFields) {
        //获取该类所有申明的字段,不包括父类申明的字段
        Field[] fields = clazz.getDeclaredFields();
        //放开java权限控制,以使得能访问得到字段
        AccessibleObject.setAccessible(fields, true);
        //comparison 检查比较状态,空构造函数new的对象,默认为0
        for (int i = 0; i < fields.length && builder.comparison == 0; i++) {
            Field f = fields[i];
            //contains 检查是否在指定数组中,传入为空,去非值,true
             //indexOf 检查字段名,注:如果字段名存在美元符号$,则无法进入比较,即setter值不同            也会返回0
            //isTransient 获取字段修饰符
            //     -- isTransient 是否为 Transient
            //     -- isStatic     是否为 static
            if (!ArrayUtils.contains(excludeFields, f.getName())
                && (f.getName().indexOf('$') == -1)
                && (useTransients || !Modifier.isTransient(f.isTransient()))
                && (!Modifier.isStatic(f.getModifiers()))) {
                try {
                    //step 3
                    builder.append(f.get(lhs), f.get(rhs));
                } catch (IllegalAccessException e) {
                    // This can't happen. Would get a Security exception instead.
                    // Throw a runtime exception in case the impossible happens.
                    throw new InternalError("Unexpected IllegalAccessException");
                }
            }
        }
    }

 

step 3:

public CompareToBuilder append(Object lhs, Object rhs, Comparator comparator) {
    //comparator 传入参数为null
        
        //检查比较状态
        if (comparison != 0) {
            return this;
        }
        //判断值是否相等,null也相等
        if (lhs == rhs) {
            return this;
        }
        if (lhs == null) {
            comparison = -1;
            return this;
        }
        if (rhs == null) {
            comparison = +1;
            return this;
        }
        //是否为数组
        if (lhs.getClass().isArray()) {
            // switch on type of array, to dispatch to the correct handler
            // handles multi dimensional arrays
            // throws a ClassCastException if rhs is not the correct array type
            //分支选择
            if (lhs instanceof long[]) {//当为 long数组
                //step 4
                append((long[]) lhs, (long[]) rhs);
            } else if (lhs instanceof int[]) {
                append((int[]) lhs, (int[]) rhs);
            } else if (lhs instanceof short[]) {
                append((short[]) lhs, (short[]) rhs);
            } else if (lhs instanceof char[]) {
                append((char[]) lhs, (char[]) rhs);
            } else if (lhs instanceof byte[]) {
                append((byte[]) lhs, (byte[]) rhs);
            } else if (lhs instanceof double[]) {
                append((double[]) lhs, (double[]) rhs);
            } else if (lhs instanceof float[]) {
                append((float[]) lhs, (float[]) rhs);
            } else if (lhs instanceof boolean[]) {
                append((boolean[]) lhs, (boolean[]) rhs);
            } else {
                // not an array of primitives
                // throws a ClassCastException if rhs is not an array
                append((Object[]) lhs, (Object[]) rhs, comparator);
            }
        } else {
            // the simple case, not an array, just test the element
            if (comparator == null) {
                comparison = ((Comparable) lhs).compareTo(rhs);
            } else {
                comparison = comparator.compare(lhs, rhs);
            }
        }
        return this;
    }

 

 

step 4

public CompareToBuilder append(long[] lhs, long[] rhs) {
        if (comparison != 0) {
            return this;
        }
        if (lhs == rhs) {
            return this;
        }
        if (lhs == null) {
            comparison = -1;
            return this;
        }
        if (rhs == null) {
            comparison = +1;
            return this;
        }
        if (lhs.length != rhs.length) {
            comparison = (lhs.length < rhs.length) ? -1 : +1;
            return this;
        }
        
        for (int i = 0; i < lhs.length && comparison == 0; i++) {
            //step 5        
            append(lhs[i], rhs[i]);
        }
       

 

step 5:

public CompareToBuilder append(long lhs, long rhs) {
        if (comparison != 0) {
            return this;
        }
        //三目运算
        comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
        return this;
    }

 

 

 

中文简介: commons-lang.jar、Apache Commons包中的一个,包含了一些数据类型工具类,是java.lang.*的扩展。必须使用的jar包。 Jar文件包含的类: META-INF/MANIFEST.MFMETA-INF/LICENSE.txtMETA-INF/NOTICE.txtorg.apache.commons.lang.ArrayUtils.class org.apache.commons.lang.BitField.class org.apache.commons.lang.BooleanUtils.class org.apache.commons.lang.CharEncoding.class org.apache.commons.lang.CharRange.class org.apache.commons.lang.CharSet.class org.apache.commons.lang.CharSetUtils.class org.apache.commons.lang.CharUtils.class org.apache.commons.lang.ClassUtils.class org.apache.commons.lang.Entities$ArrayEntityMap.class org.apache.commons.lang.Entities$BinaryEntityMap.class org.apache.commons.lang.Entities$EntityMap.class org.apache.commons.lang.Entities$HashEntityMap.class org.apache.commons.lang.Entities$LookupEntityMap.class org.apache.commons.lang.Entities$MapIntMap.class org.apache.commons.lang.Entities$PrimitiveEntityMap.class org.apache.commons.lang.Entities$TreeEntityMap.class org.apache.commons.lang.Entities.class org.apache.commons.lang.IllegalClassException.class org.apache.commons.lang.IncompleteArgumentException.class org.apache.commons.lang.IntHashMap$Entry.class org.apache.commons.lang.IntHashMap.class org.apache.commons.lang.LocaleUtils.class org.apache.commons.lang.NotImplementedException.class org.apache.commons.lang.NullArgumentException.class org.apache.commons.lang.NumberRange.class org.apache.commons.lang.NumberUtils.class org.apache.commons.lang.ObjectUtils$Null.class org.apache.commons.lang.ObjectUtils.class org.apache.commons.lang.RandomStringUtils.class org.apache.commons.lang.SerializationException.class org.apache.commons.lang.SerializationUtils.class org.apache.commons.lang.StringEscapeUtils.class org.apache.commons.lang.StringUtils.class org.apache.commons.lang.SystemUtils.class org.apache.commons.lang.UnhandledException.class org.apache.commons.lang.Validate.class org.apache.commons.lang.WordUtils.class org.apache.commons.lang.builder.CompareToBuilder.class org.apache.commons.lang.builder.EqualsBuilder.class org.apache.commons.lang.builder.HashCodeBuilder.class org.apache.commons.lang.builder.ReflectionToStringBuilder$1.class org.apache.commons.lang.builder.ReflectionToStringBuilder.class org.apache.commons.lang.builder.StandardToStringStyle.class org.apache.commons.lang.builder.ToStringBuilder.class org.apache.commons.lang.builder.ToStringStyle$DefaultToStringStyle.class org.apache.commons.lang.builder.ToStringStyle$MultiLineToStringStyle.class org.apache.commons.lang.builder.ToStringStyle$NoFieldNameToStringStyle.class org.apache.commons.lang.builder.ToStringStyle$ShortPrefixToStringStyle.class org.apache.commons.lang.builder.ToStringStyle$SimpleToStringStyle.class org.apache.commons.lang.builder.ToStringStyle.class org.apache.commons.lang.enum.Enum$Entry.class org.apache.commons.lang.enum.Enum.class org.apache.commons.lang.enum.EnumUtils.class org.apache.commons.lang.enum.ValuedEnum.class org.apache.commons.lang.enums.Enum$Entry.class org.apache.commons.lang.enums.Enum.class org.apache.commons.lang.enums.EnumUtils.class org.apache.commons.lang.enums.ValuedEnum.class org.apache.commons.lang.exception.ExceptionUtils.class org.apache.commons.lang.exception.Nestable.class org.apache.commons.lang.exception.NestableDelegate.class org.apache.commons.lang.exception.NestableError.class org.apache.commons.lang.exception.NestableException.class org.apache.commons.lang.exception.NestableRuntimeException.class org.apache.commons.lang.math.DoubleRange.class org.apache.commons.lang.math.FloatRange.class org.apache.commons.lang.math.Fraction.class org.apache.commons.lang.math.IntRange.class org.apache.commons.lang.math.JVMRandom.class org.apache.commons.lang.math.LongRange.class org.apache.commons.lang.math.NumberRange.class org.apache.commons.lang.math.NumberUtils.class org.apache.commons.lang.math.RandomUtils.class org.apache.commons.lang.math.Range.class org.apache.commons.lang.mutable.Mutable.class org.apache.commons.lang.mutable.MutableBoolean.class org.apache.commons.lang.mutable.MutableByte.class org.apache.commons.lang.mutable.MutableDouble.class org.apache.commons.lang.mutable.MutableFloat.class org.apache.commons.lang.mutable.MutableInt.class org.apache.commons.lang.mutable.MutableLong.class org.apache.commons.lang.mutable.MutableObject.class org.apache.commons.lang.mutable.MutableShort.class org.apache.commons.lang.text.CompositeFormat.class org.apache.commons.lang.text.StrBuilder$StrBuilderReader.class org.apache.commons.lang.text.StrBuilder$StrBuilderTokenizer.class org.apache.commons.lang.text.StrBuilder$StrBuilderWriter.class org.apache.commons.lang.text.StrBuilder.class org.apache.commons.lang.text.StrLookup$MapStrLookup.class org.apache.commons.lang.text.StrLookup.class org.apache.commons.lang.text.StrMatcher$CharMatcher.class org.apache.commons.lang.text.StrMatcher$CharSetMatcher.class org.apache.commons.lang.text.StrMatcher$NoMatcher.class org.apache.commons.lang.text.StrMatcher$StringMatcher.class org.apache.commons.lang.text.StrMatcher$TrimMatcher.class org.apache.commons.lang.text.StrMatcher.class org.apache.commons.lang.text.StrSubstitutor.class org.apache.commons.lang.text.StrTokenizer.class org.apache.commons.lang.time.DateFormatUtils.class org.apache.commons.lang.time.DateUtils$DateIterator.class org.apache.commons.lang.time.DateUtils.class org.apache.commons.lang.time.DurationFormatUtils$Token.class org.apache.commons.lang.time.DurationFormatUtils.class org.apache.commons.lang.time.FastDateFormat$CharacterLiteral.class org.apache.commons.lang.time.FastDateFormat$NumberRule.class org.apache.commons.lang.time.FastDateFormat$PaddedNumberField.class org.apache.commons.lang.time.FastDateFormat$Pair.class org.apache.commons.lang.time.FastDateFormat$Rule.class org.apache.commons.lang.time.FastDateFormat$StringLiteral.class org.apache.commons.lang.time.FastDateFormat$TextField.class org.apache.commons.lang.time.FastDateFormat$TimeZoneDisplayKey.class org.apache.commons.lang.time.FastDateFormat$TimeZoneNameRule.class org.apache.commons.lang.time.FastDateFormat$TimeZoneNumberRule.class org.apache.commons.lang.time.FastDateFormat$TwelveHourField.class org.apache.commons.lang.time.FastDateFormat$TwentyFourHourField.class org.apache.commons.lang.time.FastDateFormat$TwoDigitMonthField.class org.apache.commons.lang.time.FastDateFormat$TwoDigitNumberField.class org.apache.commons.lang.time.FastDateFormat$TwoDigitYearField.class org.apache.commons.lang.time.FastDateFormat$UnpaddedMonthField.class org.apache.commons.lang.time.FastDateFormat$UnpaddedNumberField.class org.apache.commons.lang.time.FastDateFormat.class org.apache.commons.lang.time.StopWatch.class
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

盒曰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值