反射实现toString工具类

来源:互联网 发布:五冠淘宝店铺年收入 编辑:程序博客网 时间:2024/04/29 19:47

在Java的开发过程中,编写对应数据库表信息的entity是必须的,很多时候为了调试我们很有必要重写entity的toString方法,为我们返回有用的entity信息,

一般是希望输出entity的属性名对应的属性值。

toString方法可以是这个样子的:

 @Override
    public String toString()
    {
        return "username: " + this.getUsername() + "& age: " + this.getAge();
    }

没什么,无非是手动拼装一把而已。不过有的时候项目大了,几百个entity都去手动拼装一把,实在有点让人心烦,更何况有些变态的entity一来就是百十个属性,

对于这种情况,这样拼装无疑是枯燥而且耗时的。

有没有简单一点的方法呢?小弟近来想到一个比较拙劣的方法,分享一把,有需要的可以看看,一个简单的工具类:

package com.huawei.zhangbo;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ToStringUtil
{
    public static String toString(Entity entity, String... fieldName)
    {
        Class cls = entity.getClass();
        StringBuffer buffer = new StringBuffer(cls.getSimpleName() + ": ");

        try
        {
            //不获取私有方法
            Method[] methods = cls.getMethods();
            if(null != fieldName && fieldName.length != 0)
            {
                for(Method method: methods)
                {
                    String mn = method.getName();
                    for(String fn: fieldName)
                    {
                        if(mn.equalsIgnoreCase("get" + fn))
                        {
                            String value = method.invoke(entity).toString();
                            buffer.append(mn + "=" + value + " &");
                        }
                    }
                }
            }
            else
            {
              //得到所有field
                Field[] fields = cls.getDeclaredFields();
                for(Method method: methods)
                {
                    String mn = method.getName();
                    for(Field field: fields)
                    {
                        String name = field.getName().toString();
                        if(mn.equalsIgnoreCase("get" + name))
                        {
                            String value = method.invoke(entity).toString();

                            buffer.append(name + "=" + value + " &");
                        }
                    }
                }
            }

        }
        catch(Exception e)
        {
            e.printStackTrace();
        }

        return buffer.substring(0, buffer.length()-1).toString();
    }

}

  小小的解释一把,非常简单,该方法有两个参数,Entity,String... ,Entity是我自己写的一个空接口,和Serializable接口一样起一个标识的作用,

标识实体类,很明显如果你的实体类不实现这个接口就不能使用我的工具类。我这样搞有我的理由,如果闲麻烦完全可以用Object取代之。第二个

参数String...,即String类型的参数,这样的写法具有灵活性,你可以不传这个参数,也可以传一个或者多个,最终Java会把你的参数封装成String类型的数组,

为什么不直接传String类型的数组,还搞这些花里胡哨的,已经说过,具有灵活性,如果写成String类型的数组你就必须传,即使传一个空数组,这样显然没有意义,

你懂得。这个参数就是传你需要输出的属性的属性名称,如果不传,输出全部属性(有get方法的,你懂得)

下面简单的说一下主要的代码执行的逻辑,

1,获取Entity参数的Class对象:  Class cls = entity.getClass();
2,通过反射获取该Entity的所有public方法:Method[] methods = cls.getMethods();

3,判断有没有String...参数

4,如果有,执行这些属性的get方法获取值与它们对应的属性名组装成字符串:

String value = method.invoke(entity).toString(); buffer.append(mn + "=" + value + " &");

5,如果没有,就需要输出全部属性的属性值,怎么搞,首先获取该entity的全部私有属性(为什么是私有,你懂的,当然只要你愿意完全可以得到所有属性输出)

Field[] fields = cls.getDeclaredFields();


6,通过所有属性和所有方法的循环查找,找到对应属性的get方法执行之,得到返回结果,在与属性名拼装字符串即可

7,最后返回拼装的字符串。

   由于很简单,讲得比较粗略

最后你的toString方法就简单了

public String toString()
    {
        return ToStringUtil.toString(this,"username");//只输出username属性
  }

public String toString()
    {
        return ToStringUtil.toString(this);//输出所有属性
  }

仅此而已。

代码中肯定存在遗漏或者不足的地方,肯定有更好的实现方法,比如:不用循环查找get方法执行,根据属性名我们本来已经可以组装它的get方法了

但是怎么执行一个指定名字的方法?望高手赐教之。

浪费你这么多时间,希望对你有帮助,望不吝指教。

原创粉丝点击