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;
}