自己实现了一个较实用的Pojo(实体)基类

自己实现了一个较实用的Pojo(实体)基类

也许你会觉得就单单重写了Object根类的equals、hashCode、toString这三个方法有什么意义?

实质上,如果你封装过泛型集合基类,并在泛型集合基类中玩过根据自定义属性排序的话,那么你会发现实现这样的一个Pojo基类很有必要!



package com.china.codingmouse.cmsdk4j.pojo;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Vector;

/**
* BasePojo Pojo(实体)基类
* @author CodingMouse
* @version 1.0.0.1 2009-4-10
*/
public class BasePojo implements Serializable {

private static final long serialVersionUID = -5520682886492533483L; // 版本序列号

/**
* 指示其他某个对象是否与此对象“相等”
*/
@Override
public boolean equals(Object obj) {
// 自身比较
if (obj == this) {
return true;
}
// 类型相同
if (obj.getClass() == this.getClass()) {
// 当前类反射方法组
Method[] thisMethodGroup = this.getClass().getMethods();

try {
// 遍历反射方法组并提取当前类属性的getter方法
for (Method method : thisMethodGroup) {
// 过滤与当前类属性无关的get方法
if (method.getName().startsWith("get")
&& !method.getName().equals("getClass")) {
// 将当前类属性的getter方法与比较类属性的getter方法值作比较
Method currentMethod = obj.getClass().getMethod(method.getName());
// 执行方法以获取返回值比较(关键点:注意参数不相同)
Object objReturnValue = currentMethod.invoke(obj);
Object thisReturnValue = method.invoke(this);
// 空值报异
/*if (objReturnValue == null) {
System.err.println("异常信息:类" + obj.getClass().getName()
+ "中的" + currentMethod.getName() + "方法为null值!无法进行对象比较!");
}
if (thisReturnValue == null) {
System.err.println("异常信息:类" + this.getClass().getName()
+ "中的" + method.getName() + "方法为null值!无法进行对象比较!");
}*/
// 返回值不相等则返回逻辑假
if (!objReturnValue.equals(thisReturnValue)) {
return false;
}
}
}
} catch (SecurityException ex) {
System.err.println("异常信息:参数错误,安全管理器检测到安全侵犯!\r\n" + ex.getMessage());
} catch (NoSuchMethodException ex) {
System.err.println("异常信息:参数错误,无法找到某一特定的方法!\r\n" + ex.getMessage());
} catch (IllegalArgumentException ex) {
System.err.println("异常信息:参数错误,向方法传递了一个不合法或不正确的参数!\r\n" + ex.getMessage());
} catch (IllegalAccessException ex) {
System.err.println("异常信息:参数错误,对象定义无法访问,无法反射性地创建一个实例!\r\n" + ex.getMessage());
} catch (InvocationTargetException ex) {
System.err.println("异常信息:参数错误,由调用方法或构造方法所抛出异常的经过检查的异常!\r\n" + ex.getMessage());
}
}

// 通过不相等比较则返回逻辑真
return true;

}

/**
* 返回该对象的哈希码值
*/
@Override
public int hashCode() {

// 生成简单的位运算hash散列码
String key = this.toString();
int prime = key.hashCode();
int hash = prime;
for (int i = 0; i < key.length(); i++) {
hash ^= (hash << 23 >> 17) ^ key.charAt(i) * 13131;
}
// 返回结果
return (hash % prime) * 33;

}

/**
* 返回该对象的字符串表示(类似数组的toString方法输出结果)
*/
@Override
public String toString() {

// 当前类反射方法组
Method[] methodGroup = this.getClass().getMethods();
// 保存内容
StringBuffer content = new StringBuffer("[");
// 保存属性的getter方法组
List<Method> getMethodGroup = new Vector<Method>();

try {
// 遍历反射方法组并提取属性的getter方法
for (Method method : methodGroup) {
// 过滤与属性无关的get方法
if (method.getName().startsWith("get")
&& !method.getName().equals("getClass")) {
// 保存属性的getter方法
getMethodGroup.add(method);
}
}
// 处理仅包含属性的getter方法
for (int i = 0; i < getMethodGroup.size(); i++) {
// 执行get方法并拼接获取到的返回值(如果底层方法返回类型为 void,则该调用返回 null)
content.append(getMethodGroup.get(i).invoke(this)
+ ((i < getMethodGroup.size() - 1) ? ",\u0020" : "]"));
}
} catch (IllegalAccessException ex) {
System.err.println("异常信息:参数错误,对象定义无法访问,无法反射性地创建一个实例!\r\n" + ex.getMessage());
} catch (IllegalArgumentException ex) {
System.err.println("异常信息:参数错误,向方法传递了一个不合法或不正确的参数!\r\n" + ex.getMessage());
} catch (InvocationTargetException ex) {
System.err.println("异常信息:参数错误,由调用方法或构造方法所抛出异常的经过检查的异常!\r\n" + ex.getMessage());
}

// 返回结果
return content.toString();

}

}




以下是此基类的一段测试代码:



package com.china.codingmouse.cmsdk4j.example.pojo;

import java.io.Serializable;
import java.sql.Timestamp;

import com.china.codingmouse.cmsdk4j.pojo.BasePojo;

/**
* UserPojo 用户信息实体类
* @author CodingMouse
* @version 1.0.0.1 2009-4-10
*/
public class UserPojo extends BasePojo implements Serializable {

private static final long serialVersionUID = -2214074259397104603L; // 版本序列号
private int id; // 用户ID
private String name; // 用户姓名
private boolean sex; // 用户性别
private int age; // 用户年龄
private String address; // 用户住址
private Timestamp regTime; // 用户注册时间

/**
* 默认构造器
*/
public UserPojo() {
super();
}
/**
* 参数化构造器
* @param id 用户ID
* @param name 用户姓名
* @param sex 用户性别
* @param age 用户年龄
* @param address 用户住址
* @param regTime 用户注册时间
*/
public UserPojo(int id, String name, boolean sex, int age, String address, Timestamp regTime) {
super();
this.setId(id);
this.setName(name);
this.setSex(sex);
this.setAge(age);
this.setAddress(address);
this.setRegTime(regTime);
}
/**
* 用户ID取值方法
* @return 用户ID
*/
public int getId() {
return id;
}
/**
* 用户ID赋值方法
* @param id 用户ID
*/
public void setId(int id) {
this.id = id;
}
/**
* 用户姓名取值方法
* @return 用户姓名
*/
public String getName() {
return name;
}
/**
* 用户姓名赋值方法
* @param name 用户姓名
*/
public void setName(String name) {
this.name = name;
}
/**
* 用户性别取值方法
* @return 用户性别
*/
public boolean getSex() {
return sex;
}
/**
* 用户性别赋值方法
* @param sex 用户性别
*/
public void setSex(boolean sex) {
this.sex = sex;
}
/**
* 用户年龄取值方法
* @return 用户年龄
*/
public int getAge() {
return age;
}
/**
* 用户年龄赋值方法
* @param age 用户年龄
*/
public void setAge(int age) {
this.age = age;
}
/**
* 用户住址取值方法
* @return 用户住址
*/
public String getAddress() {
return address;
}
/**
* 用户住址赋值方法
* @param address 用户住址
*/
public void setAddress(String address) {
this.address = address;
}
/**
* 用户注册时间取值方法
* @return 用户注册时间
*/
public Timestamp getRegTime() {
return regTime;
}
/**
* 用户注册时间赋值方法
* @param regTime 用户注册时间
*/
public void setRegTime(Timestamp regTime) {
this.regTime = regTime;
}

}






package com.china.codingmouse.cmsdk4j.example.pojo.test;

import java.sql.Timestamp;

import com.china.codingmouse.cmsdk4j.example.pojo.UserPojo;

/**
* 用户信息实体类Equals与HashCode方法测试类
* @author CodingMouse
* @version 1.0.0.1 2009-4-10
*/
public class UserPojoEqualsAndHashCodeTest {

/**
* 测试类主方法
* @param args
*/
public static void main(String[] args) {

UserPojo up1 = new UserPojo(3, "邓超", true, 25, "四川隆昌", new Timestamp(System.currentTimeMillis()));
UserPojo up2 = new UserPojo(3, "邓超", true, 25, "四川隆昌", new Timestamp(System.currentTimeMillis()));
System.out.println("User1的内容:" + up1);
System.out.println("User2的内容:" + up2);
System.err.println("User1的散列码:" + up1.hashCode());
System.err.println("User2的散列码:" +up2.hashCode());
System.out.println("测试User1与User2地址(==)相等:" + (up1 == up2));
System.out.println("测试User1与User2内容(equals)相等:" + up1.equals(up2));
UserPojo up3 = new UserPojo(6, "CodingMouse", false, 22, "中华人民共和国四川成都", new Timestamp(System.currentTimeMillis()));
UserPojo up4 = new UserPojo(13, "Michael Jackson", false, 53, "美利坚合众国纽约市唐人街", new Timestamp(System.currentTimeMillis()));
System.out.println("User3的内容:" + up3);
System.out.println("User4的内容:" + up4);
System.err.println("User3的散列码:" +up3.hashCode());
System.err.println("User4的散列码:" +up4.hashCode());
System.out.println("测试User3与User4地址(==)相等:" + (up3 == up4));
System.out.println("测试User3与User4内容(equals)相等:" + up3.equals(up4));

}

}




跑出来的结果:

---------------------------------------------------------------------

User1的内容:[true, 25, 2009-04-10 18:39:54.557, 四川隆昌, 邓超, 3]
User2的内容:[true, 25, 2009-04-10 18:39:54.557, 四川隆昌, 邓超, 3]
[color=red]User1的散列码:524379269
User2的散列码:524379269[/color]
测试User1与User2地址(==)相等:false
测试User1与User2内容(equals)相等:true
User3的内容:[false, 22, 2009-04-10 18:39:54.563, 中华人民共和国四川成都, CodingMouse, 6]
User4的内容:[false, 53, 2009-04-10 18:39:54.563, 美利坚合众国纽约市唐人街, Michael Jackson, 13]
[color=red]User3的散列码:-715569909
User4的散列码:956891732[/color]
测试User3与User4地址(==)相等:false
测试User3与User4内容(equals)相等:false

---------------------------------------------------------------------


重写equals与hashCode方法是从所周知的事情,所以不多作说明。

至于为什么我要重写toString方法,有两点理由:

1、作为hashCode生成算法的一部分,与其内容直接相关,有更好的散列效果。

2、便于获取其子类更详细的内容描述,便于调试,而不是得到诸如“java.lang.Object@757aef”这样让人难以理解的文字内容。


正在写一个泛型BasePojoCollection(实体集合基类),想达到在基类中实现反射性地对子类自定义属性排序的功能。有了这样一个BasePojo为基础,就可以较容易地实现了!当然,还需要为这个BasePojo实现Comparable接口。


原来没有看到过别人做这样的尝试,如果你有更好的思路,还烦请指正为感!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值