在我们的实际开发中,通常会认为两个对象的内容相等时,则两个对象相等,equals返回true。对象内容不同,则返回false。
可以总结为两种情况:
1、类未复写equals方法,则使用equals方法比较两个对象时,相当于==比较,即两个对象的地址是否相等。地址相等,返回true,地址不相等,返回false。
2、类复写equals方法,比较两个对象时,则走复写之后的判断方式。通常,我们会将equals复写成:当两个对象内容相同时,则equals返回true,内容不同时,返回false。
注意:用“==”比较的是引用的地址,用equals比较的就是值。Object类中的equals方法定义为判断两个对象的地址是否相等(可以理解成是否是同一个对象),地址相等则认为是对象相等。这也就意味着,我们新建的所有类如果没有复写equals方法,那么判断两个对象是否相等时就等同于“==”,也就是两个对象的地址是否相等。
问题:
1、假设对象的属性不定,那重写equals时肯定无法穷尽所以字段;
2、对象是第三方的引用,无法重写equals方法;
解决方式:
equals方法中使用反射获取所有字段的name和value,逐个对比;无法重写equal方法,就自己随便写一个,将要对比的对象作为入参丢进去;
参考代码1:比较
public StringBuilder compareContract(CreateContractSignInfoRequest sign, CreateContractSignInfoRequest existSign) {
StringBuilder stringBuilder = new StringBuilder();
try {
Field[] fields = getAllFields(sign);
for (int j = 0; j < fields.length; j++) {
fields[j].setAccessible(true);
// 字段值
if (!fields[j].get(sign).equals(fields[j].get(existSign))) {
stringBuilder.append(existSign.getUserName());
stringBuilder.append(fields[j].getName() + "、");
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return stringBuilder;
}
参考代码2:获取所有属性
/**
* 获取所有属性,包括父类
*
* @param object
* @return
*/
public Field[] getAllFields(Object object) {
Class clazz = object.getClass();
List<Field> fieldList = new ArrayList<>();
while (clazz != null) {
fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
clazz = clazz.getSuperclass();
}
Field[] fields = new Field[fieldList.size()];
fieldList.toArray(fields);
return fields;
}
反射扩展:
(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)
网友评论