自己实现了一个较实用的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]
User1的散列码:524379269
User2的散列码:524379269
测试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]
User3的散列码:-715569909
User4的散列码:956891732
测试User3与User4地址(==)相等:false
测试User3与User4内容(equals)相等:false
---------------------------------------------------------------------
重写equals与hashCode方法是从所周知的事情,所以不多作说明。
至于为什么我要重写toString方法,有两点理由:
1、作为hashCode生成算法的一部分,与其内容直接相关,有更好的散列效果。
2、便于获取其子类更详细的内容描述,便于调试,而不是得到诸如“java.lang.Object@757aef”这样让人难以理解的文字内容。
正在写一个泛型BasePojoCollection(实体集合基类),想达到在基类中实现反射性地对子类自定义属性排序的功能。有了这样一个BasePojo为基础,就可以较容易地实现了!当然,还需要为这个BasePojo实现Comparable接口。
原来没有看到过别人做这样的尝试,如果你有更好的思路,还烦请指正为感!
分享到:
相关推荐
3. **编写通用DAO接口**:定义一个基类,如`BaseDAO<T>`,T代表POJO类型,接口中包含增删改查的基本方法。 4. **实现通用DAO接口**:实现`BaseDAO<T>`接口,使用JDBCTemplate的方法来执行SQL。例如,实现插入操作:...
UpLoad类是一个具体的Servlet实现,它继承自HttpServlet基类,并重写了doPost方法来处理POST请求。这段代码展示了如何使用Apache Commons FileUpload库来处理文件上传的功能。 ### 总结 通过对以上内容的分析,我们...
1. **POJO基类**:实体类应是普通的Java对象(POJO),不依赖于任何框架或容器。 2. **访问器方法**:实体类应提供getter和setter方法,以便Hibernate通过反射机制读取和更新属性值。 3. **默认构造器**:实体类需...
在本篇"Spring Security...总结来说,构建Spring Security用户登录模块涉及数据库设计、Pojo实体、安全配置和接口实现等多个方面。通过这些步骤,我们可以创建一个安全、可靠的登录系统,为用户提供认证和授权服务。
POJO是一个非正式术语,用于描述那些没有特殊框架或库依赖的简单Java类,它们仅包含一些私有属性、getter和setter方法。在EJB3.0中,这些POJO类被用作持久化实体,通过简单的注解(Annotations)来定义实体之间的...
- **无容器依赖的实体Bean**:EJB3.0的实体Bean可以作为POJO(Plain Old Java Object)存在,不再强制需要继承特定的基类或实现接口。 - **自动事务管理**:EJB3.0 提供了更强大的事务管理,开发者无需手动处理事务...
`ejbCreate`方法在EJB容器创建一个新的实体Bean实例时被调用,通常在这个方法中进行Bean对象的初始化工作,如设置默认值、打开数据库连接等。值得注意的是,`ejbCreate`不是Java语言内置的方法,而是EJB规范定义的...
接着,我们创建POJO类,例如这里的`Student`类,它代表了数据库中的一个实体。这个类包含了一些基本属性,如`id`、`firstname`和`lastname`,并提供了对应的getter和setter方法。这使得Spring和iBATIS能够通过...
【JAVA代码生成器源码-基于SSM架构】是一个实用工具,它可以帮助开发者快速构建Java Web应用程序的基础结构。SSM架构是由Spring、Spring MVC和MyBatis三个框架组成的,是目前广泛使用的Java后端开发技术栈。这个工具...
例如,可以定义一个基类 `Product` 来表示所有类型的货物,然后根据具体的货物类型(如书籍、电子产品等)创建不同的子类。每个子类继承自 `Product` 类,并根据需要添加额外的属性。 这种方式不仅使得代码结构更加...
Struts2是一个强大的Java web开发框架,用于构建可维护、可扩展且结构良好的应用程序。它在MVC(Model-View-Controller)设计模式的基础上提供了一种简化开发的方式,使得开发者可以更加专注于业务逻辑,而不是繁琐...
例如,对于User类,只需要在类上添加@Entity注解,表示这是一个实体类;在ID字段上添加@Id和@GeneratedValue注解,表明它是主键,并指定了自动增长策略。 - **一对多关系配置**:如果涉及更复杂的关系,如一对多或...
在进行Web开发的机试考试时,我们需要遵循一系列的步骤来构建一个完整的项目。以下是一些关键知识点: 1. **环境搭建** - **数据库创建**:首先,你需要根据试卷指示创建数据库。数据库的名称、表名、字段名以及表...
2. POJO(Plain Old Java Object):EJB 3.0允许开发者使用普通的Java对象作为业务组件,无需继承特定的基类或实现接口,增强了代码的可读性和可维护性。 3. JPA(Java Persistence API):这是EJB 3.0中的一个重要...
- **注解示例**:通过使用`@Entity`注解来声明一个类为实体类,使用`@Id`注解指定主键字段,使用`@Column`等注解来定义字段与数据库列的映射关系。 ```java @Entity @Table(name = "customer") public class ...
- **POJO支持**:EJB 3.0 支持Plain Old Java Objects (POJOs),这意味着EJB组件不再需要继承特定的基类或实现接口,降低了学习曲线。 - **实体管理**:实体Bean(Entity Beans)的API被简化,使用JPA(Java ...
Hibernate支持使用普通的Java对象(POJO)作为持久化对象,无需继承特定的基类或实现接口。对象的状态(瞬时、持久、脱管)由Hibernate自动管理。 5. **会话与事务** Session是Hibernate的主要工作接口,用于执行...
例如,为基类`User`创建一个表,并在表中添加一个字段来区分不同的子类类型,如`type`字段。然后,在Hibernate的映射文件中,可以通过`<subclass>`元素指定具体的子类类型及其对应的字段值。 通过以上步骤,我们...
在EJB 3.0中,实体bean(Entity Bean)采用了POJO(Plain Old Java Object)模式,不再需要实现特定接口或继承特定基类。通过`@Entity`注解,普通Java类可以被声明为数据库映射的对象,JPA(Java Persistence API)...