比较不同对象中字段的内容
简介:项目中可能出现比较不同的对象中的值的情况,可以使用反射去拿值进行比较
我自己写了一个方法,可能效率不高,但通过反射思想能实现该需求,
***但我的代码还有缺陷:对空指针情况没有被做处理!此代码只为提供思路做参考!***代码如下:
实体类P1
public class P1 implements Serializable {
private static final long serialVersionUID=1L;
private Integer id;
private String name;
private Integer num;
private String homeAddress;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getNum() {
return num;
}
public void setNum(Integer num) {
this.num = num;
}
public String getHomeAddress() {
return homeAddress;
}
public void setHomeAddress(String homeAddress) {
this.homeAddress = homeAddress;
}
public P1(Integer id, String name, Integer num, String homeAddress) {
this.id = id;
this.name = name;
this.num = num;
this.homeAddress = homeAddress;
}
}
实体类P2
public class P2 implements Serializable {
private static final long serialVersionUID=1L;
private Integer ids;
private String name;
private Integer num;
private String home;
public Integer getIds() {
return ids;
}
public void setIds(Integer ids) {
this.ids = ids;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getNum() {
return num;
}
public void setNum(Integer num) {
this.num = num;
}
public String getHome() {
return home;
}
public void setHome(String home) {
this.home = home;
}
public P2(Integer ids, String name, Integer num, String home) {
this.ids = ids;
this.name = name;
this.num = num;
this.home = home;
}
}
Different类
public class Different implements Serializable {
private static final long serialVersionUID=1L;
private String fieldName;
private String contentHead;
private String contentEnd;
public String getFieldName() {
return fieldName;
}
public void setFieldName(String fieldName) {
this.fieldName = fieldName;
}
public String getContentHead() {
return contentHead;
}
public void setContentHead(String contentHead) {
this.contentHead = contentHead;
}
public String getContentEnd() {
return contentEnd;
}
public void setContentEnd(String contentEnd) {
this.contentEnd = contentEnd;
}
@Override
public String toString() {
return "Different{" +
"fieldName='" + fieldName + '\'' +
", contentHead='" + contentHead + '\'' +
", contentEnd='" + contentEnd + '\'' +
'}';
}
}
比较工具类
public class Test5 {
public static List differentMethed(Object head, Object end) {
try {
//装head参数的对象成员变量信息 getDeclaredFields可拿全部信息,getFields只能拿public的
Field[] fieldsHead = head.getClass().getDeclaredFields();
//装end参数的对象成员变量信息
Field[] fieldsEnd = end.getClass().getDeclaredFields();
//存不一样字段名和值的容器
LinkedList<Different> linkedListDifferent = new LinkedList();
//将反射拿到的head成员变量信息写入
for (Field fH : fieldsHead
) {
for (Field fE : fieldsEnd
) {
//开启获得私有权限属性能力
fH.setAccessible(true);
fE.setAccessible(true);
//字段名和类型一样
if (fH.getName().equals(fE.getName())
&& fH.getType().equals(fE.getType())
) {
//情况一:值为空
if(StringUtils.isBlank(fH.get(head).toString())
&& StringUtils.isBlank(fE.get(end).toString())){
}
//情况二:值不空
if(StringUtils.isNotBlank(fH.get(end).toString())
&& StringUtils.isNotBlank(fE.get(end).toString())){
//值不一样
if(!fH.get(head).equals(fH.get(end))){
//实体类
Different different = new Different();
different.setContentHead(fH.get(head).toString());
different.setContentEnd(fE.get(end).toString());
different.setFieldName(fH.getName());
linkedListDifferent.add(different);
continue;
}
}
//某一个值为空
if(StringUtils.isBlank(fH.get(head).toString())
|| StringUtils.isBlank(fE.get(end).toString())) {
//实体类
Different different = new Different();
different.setContentHead(fH.get(head).toString());
different.setContentEnd(fE.get(end).toString());
different.setFieldName(fH.getName());
linkedListDifferent.add(different);
continue;
}
}
}
}
return linkedListDifferent;
}catch (Exception e){
return null;
}
}
}
测试类
public class Test6 {
public static void main(String[] args) {
P1 p1=new P1(11,"AAAA",100,"上");
P2 p2=new P2(12,"BBB",100,"下");
List<Different> differents=Test5.differentMethed(p1,p2);
for (Different d:differents
) {
System.out.println(d.toString());
}
}
}
结果:
后续补充:
之前写的代码有缺陷:当我只想比较两个对象中指定的属性进行内容比较,就无法实现。之后了解到反射可以拿到注解对象!那我可以在需要比较的属性上弄个注解,当作标志,然后就可以通过有无该指定注解来锁定是哪个属性需要进行内容的比较。
注意:这里的注解可以用自己定义的,也可以使用已经存在的注解,下面我自己实现该思路,使用springboot项目框架中@JsonProperty注解作为标志;
测试的比较类
//Aentity类
@Component
public class Aentity implements Serializable {
private static final long serialVersionUID=1L;
@JsonProperty(value = "name")
private String nameA;
@JsonProperty(value = "age")
private Integer ageA;
@Property(name = "11111")
private String addressA;
public String getNameA() {
return nameA;
}
public void setNameA(String nameA) {
this.nameA = nameA;
}
public Integer getAgeA() {
return ageA;
}
public void setAgeA(Integer ageA) {
this.ageA = ageA;
}
public String getAddressA() {
return addressA;
}
public void setAddressA(String addressA) {
this.addressA = addressA;
}
}
//Bentity类
@Component
public class Bentity implements Serializable {
private static final long serialVersionUID=1L;
@JsonProperty(value = "name")
private String nameB;
@JsonProperty(value = "age")
private Integer ageB;
@Property(name = "11111")
private String addressB;
//测试多余属性
private String email;
public String getNameB() {
return nameB;
}
public void setNameB(String nameB) {
this.nameB = nameB;
}
public Integer getAgeB() {
return ageB;
}
public void setAgeB(Integer ageB) {
this.ageB = ageB;
}
public String getAddressB() {
return addressB;
}
public void setAddressB(String addressB) {
this.addressB = addressB;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
Dffrence类
@Component
public class Dffrence {
//第一个对象中属性名
private String headName;
//第一个对象中属性值
private Object headValue;
//第二个对象中属性名
private String endName;
//第二个对象中属性名
private Object endValue;
//比较的属性别名
private String name;
public Object getHeadValue() {
return headValue;
}
public void setHeadValue(Object headValue) {
this.headValue = headValue;
}
public String getEndName() {
return endName;
}
public void setEndName(String endName) {
this.endName = endName;
}
public Object getEndValue() {
return endValue;
}
public void setEndValue(Object endValue) {
this.endValue = endValue;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getHeadName() {
return headName;
}
public void setHeadName(String headName) {
this.headName = headName;
}
@Override
public String toString() {
return "Dffrence{" +
"headName='" + headName + '\'' +
", headValue=" + headValue +
", endName='" + endName + '\'' +
", endValue=" + endValue +
", name='" + name + '\'' +
'}';
}
}
测试工具类
@Component
public class TestAB {
public static List<Dffrence> dffrence(Object a,Object b) {
//装不同属性信息容器
ArrayList<Dffrence> list = new ArrayList<Dffrence>();
try {
//拿到A的所有属性
Field[] fieldsA = a.getClass().getDeclaredFields();
//拿到B的所有属性
Field[] fieldsB = b.getClass().getDeclaredFields();
for (Field fa : fieldsA
) {
//开启获取私有属性权限
fa.setAccessible(true);
//获取A中有@JsonProperty注解的属性
JsonProperty jsonPropertyA = fa.getAnnotation(JsonProperty.class);
//有注解,其对象必不为空
if (jsonPropertyA == null) {
continue;
}
//有该注解,就参与比较
for (Field fb : fieldsB
) {
//开启获取私有属性权限
fb.setAccessible(true);
//获取B中有@JsonProperty注解的属性
JsonProperty jsonPropertyB = fb.getAnnotation(JsonProperty.class);
//有注解,其对象必不为空
if (jsonPropertyB == null) {
continue;
}
//有注解,进一步比较是否是同一属性别名(就是JsonProperty注解中的value的值)
if (!jsonPropertyA.value().equals(jsonPropertyB.value())
|| StringUtils.isBlank(jsonPropertyA.value())
|| StringUtils.isBlank(jsonPropertyB.value())
) {
//属性别名不一样,表示虽然这个写属性需要比较,但他们彼此不是比较对手
//或者有属性别名缺失,不比较
continue;
}
//这里存在可能不同类间比较的属性数据类型不一样,这里统一全部转成字符串比较
Dffrence dffrence = new Dffrence();
//拿到比较的属性别名
dffrence.setName(jsonPropertyA.value());
//对该属性类型转化为String,并比较内容
String contentA = fa.get(a).toString();
String contentB = fb.get(b).toString();
//比较内容是否一样,一样就不写入,某一个为空,直接写入
if ((contentA != null && contentB == null) || (contentA == null && contentB != null)) {
//拿到比较的属性别名
dffrence.setName(jsonPropertyA.value());
dffrence.setHeadName(fa.getName());
dffrence.setEndName(fb.getName());
dffrence.setHeadValue(contentA);
dffrence.setEndValue(contentB);
list.add(dffrence);
//进入下个属性比较
break;
}
if (StringUtils.isNotBlank(contentA)
&& StringUtils.isNotBlank(contentB)
&&!contentA.equals(contentB)) {
dffrence.setName(jsonPropertyA.value());
dffrence.setHeadName(fa.getName());
dffrence.setEndName(fb.getName());
dffrence.setHeadValue(contentA);
dffrence.setEndValue(contentB);
list.add(dffrence);
//进入下个属性比较
break;
}
}
}
return list;
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return list;
}
}
测试类
public class Test {
public static void main(String[] args) {
Aentity a=new Aentity();
a.setNameA("aaa");
a.setAgeA(18);
a.setAddressA("这是A");
Bentity b=new Bentity();
b.setNameB("bbb");
b.setAgeB(18);
b.setAddressB("这是B");
b.setEmail("1234567890");
List<Dffrence> list= new ArrayList<>();
list=TestAB.dffrence(a,b);
for (Dffrence d:list
) {
System.out.println(d.toString());
}
}
}
运行结果:
结语:反射有很多功能,值得花时间去探索