论坛首页 入门技术论坛

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

浏览 12156 次
该帖已经被评为新手帖
作者 正文
   发表时间:2009-04-11   最后修改:2009-04-11
OO
自己实现了一个较实用的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接口。


原来没有看到过别人做这样的尝试,如果你有更好的思路,还烦请指正为感!
   发表时间:2009-04-12  
这反射用的也太不值钱了吧
0 请登录后投票
   发表时间:2009-04-12  
支持造轮子  不过好多的ifelse
0 请登录后投票
   发表时间:2009-04-12   最后修改:2009-04-12
还是代码自动生成吧,然后设置一个eclipse的一个快捷键,自动把源文件作为输入,然后生成覆盖源文件,并自动刷新一下。
不过apache common已经提供了比较方便的方法可用。
0 请登录后投票
   发表时间:2009-04-12  
请问楼主的与apache commons lang比较有何优势?
0 请登录后投票
   发表时间:2009-04-13  
herowzz 写道
请问楼主的与apache commons lang比较有何优势?

谢谢各位的建议!

我只是一个初学者,也算是一个学生吧,只是凭空想象用来实现一些封装,以便于给伙伴使用,简化他们的代码编写。也许,我写的代码不地道。

对于apache commons lang,我没有去看过它的相关代码。也许各位的提醒得让我去注意一下了。



0 请登录后投票
   发表时间:2009-04-13  
对于投隐藏贴的,不记名,怎么说也得给个理由吧,javaeye应该给这个功能
0 请登录后投票
   发表时间:2009-04-24  
有必要搞的这么复杂吗!

反射是要降低性能的!
慎用!
0 请登录后投票
   发表时间:2009-04-25  
还是不错
0 请登录后投票
   发表时间:2009-04-25  
不支持这样用,这么用反射没什么好处

我也投个隐藏
0 请登录后投票
论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics