ObjectUtil.java



/*
* File:ObjectUtil.java
* User:xiaocao000
* Date:2009-3-14
*/
package com.xiaocao000.lang;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import com.xiaocao000.io.IOStreamUtil;

/**
* ObjectUtil<br>
* <ol>
* <li>isEmpty(); isNotEmpty();
* <li>toString();
* <li>equals();
* <li>clone();
* </ol>
*
* @author xiaocao000
* Date:2009-3-14
* @version 1.0
*/
public class ObjectUtil
{
private static final String NULL = "null";
private static final String EMPTY_STR = "";

/** 定义toString时忽略的属性名称字符串集合 */
private static final String[] IGNORE_FIELD_NAMES = {"log", "logger",
"serialVersionUID", // 实现序列化接口时自动添加的字段
};

/** 定义toString时忽略的属性类名字符串集合 */
private static final String[] IGNORE_FIELD_CLASSES = {
"org.apache.log4j.Logger",
"java.util.logging.Logger", // 日志记录器声明的属性
"java.lang.Object", "java.lang.Class",
"java.lang.reflect.AccessibleObject", "java.lang.reflect.Field",
"java.lang.reflect.Method", "java.lang.reflect.Constructor",};

// =====================================================
// isNull(); isNotNull();
// isEmpty(); isNotEmpty();
// =====================================================
/**
* 判断指定的对象是否为null。
*
* @param obj 要判断的对象实例
* @return true:为null false:非null
*/
public static boolean isNull(Object obj)
{
return obj == null;
}

/**
* 判断指定的对象是否不为null。
*
* @param obj 要判断的对象实例
* @return true:非null false:为null
*/
public static boolean isNotNull(Object obj)
{
return !isNull(obj);
}

/**
* 判断指定的对象数组是否为空。
*
* @param objs 要判断的对象数组实例
* @return true:对象数组为空 false:对象数组非空
*/
public static boolean isEmpty(Object[] objs)
{
return isNull(objs) || objs.length == 0;
}

/**
* 判断指定的对象数组是否非空。
*
* @param objs 要判断的对象数组实例
* @return true:对象数组非空 false:对象数组为空
*/
public static boolean isNotEmpty(Object[] objs)
{
return !isEmpty(objs);
}

/**
* 判断指定的集合类是否为空。<BR>
* 为空的含义是指:该集合为null,或者该集合不包含任何元素。
*
* @param coll 要判断的集合实例
* @return true:集合为空 false:集合非空
*/
public static boolean isEmpty(Collection<?> coll)
{
return isNull(coll) || coll.isEmpty();
}

/**
* 判断指定的集合类是否非空。 <BR>
* 非空的含义是指:该集合非null并且该集合包含元素。
*
* @param coll 要判断的集合实例
* @return true:集合非空 false:集合为空
*/
public static boolean isNotEmpty(Collection<?> coll)
{
return !isEmpty(coll);
}

/**
* 判断指定的Map类是否为空。 <BR>
* 为空的含义是指:该Map为null,或者该Map不包含任何元素。
*
* @param map 要判断的Map实例
* @return true:Map为空 false:Map非空
*/
public static boolean isEmpty(Map<?, ?> map)
{
return isNull(map) || map.isEmpty();
}

/**
* 判断指定的Map类是否非空。<BR>
* 非空的含义是指:该Map非null并且该Map包含元素。
*
* @param map 要判断的Map实例
* @return true:Map非空 false:Map为空
*/
public static boolean isNotEmpty(Map<?, ?> map)
{
return !isEmpty(map);
}

/**
* 判断指定的CharSequence类是否为空。 <BR>
* 为空的含义是指:该CharSequence为null,或者该CharSequence长度为0。<BR>
* 对String类型,虽然也属于CharSequence,<BR>
* 但因为通常字符串都有特殊的处理要求,所以使用方法isEmpty(String str);
*
* @param charSeq 要判断的CharSequence实例
* @return true:CharSequence为空 false:CharSequence非空
*/
public static boolean isEmpty(CharSequence charSeq)
{
return isNull(charSeq) || charSeq.length() == 0;
}

/**
* 判断指定的CharSequence类是否非空。 <BR>
* 非空的含义是指:该CharSequence非null并且该CharSequence包含元素。<BR>
* 对String类型,虽然也属于CharSequence, <BR>
* 但因为通常字符串都有特殊的处理要求,所以使用方法isNotEmpty(String str);
*
* @param charSeq 要判断的CharSequence实例
* @return true:CharSequence非空 false:CharSequence为空
*/
public static boolean isNotEmpty(CharSequence charSeq)
{
return !isEmpty(charSeq);
}

/**
* 判断指定的String类是否为空。 <BR>
* 为空的含义是指:该String为null,或者该String为空串""。
*
* @param str 要判断的String实例
* @return true:String为空 false:String非空
*/
public static boolean isEmpty(String str)
{
return isNull(str) || EMPTY_STR.equals(str);
}

/**
* 判断指定的String类是否非空。 <BR>
* 非空的含义是指:该String非null并且该String不为空串。
*
* @param str 要判断的String实例
* @return true:String非空 false:String为空
*/
public static boolean isNotEmpty(String str)
{
return !isEmpty(str);
}

/**
* 判断指定的String类是否为空。<BR>
* 为空的含义是指:该String为null,或者该String为空串""。
*
* @param str 要判断的String实例
* @return true:String为空 false:String非空
*/
public static boolean isTrimEmpty(String str)
{
return isNull(str) || EMPTY_STR.equals(str.trim());
}

/**
* 判断指定的String类是否非空。 <BR>
* 非空的含义是指:该String非null并且该String不为空串。
*
* @param str 要判断的String实例
* @return true:String非空 false:String为空
*/
public static boolean isTrimNotEmpty(String str)
{
return !isTrimEmpty(str);
}

// =============================================================
// toString()
// 1. Java 基本型别,包括基本对象型别 直接调用对象本身的toString()
// 2. 简单的Bean类型 采用反射机制取得每个属性的值
// 3. Java集合类型 如:Collection,Map以及对象数组
// 4. 非Java基本型别的对象类型作为属性
// 5. enum处理:能正确调用object.toString(),归类为Java基本类型
// 6. 继承关系处理:先取得所有父类,再取得所有属性 递归toString
// 7. 内部类处理:内部类包含了一个对外部类的默认引用,其名称会包含"this$",忽略即可
// =============================================================

/**
* 通用的toString方法。 <BR>
* 1. 以对象形式存在的基本型别数组,如:byte[],long[]需要特殊处理。<BR>
*
* @param obj 要转化为字符串的对象
* @return 转化后的字符串
*/
public static String toString(Object obj)
{
if (isNull(obj))
{
return NULL;
}

Class<?> clazz = obj.getClass();
if (clazz.equals(Object.class) || clazz.equals(Class.class))
{
return obj.toString();
}

// 如果是Java基本型别 可以直接调用toString得到正确的信息
if (ClassUtil.isJavaBasicType(clazz))
{
return obj.toString();
}

StringBuilder sb = new StringBuilder();

// 如果是数组类
if (clazz.isArray())
{
// Java基本型别的数组,可以利用Arrays.toString()完成转化,
// 这里转为对象数组再用deepToString(),只是为了添加附加信息和减少代码
if (ClassUtil.isPrimitiveArray(clazz))
{
Object[] objs = new Object[] {obj};
sb.append(clazz.getSimpleName()).append("=");
String objsStr = Arrays.deepToString(objs);
sb.append(objsStr.substring(1, objsStr.length() - 1));
return sb.toString();
}

// 基本类型的数组已经处理,这里只可能是对象数组。
// 将基本型别数组与对象数字分开处理的原因是:
// 基本型别数组可以利用Arrays.deepToString(Object[] objs)转为String
// 但对象数组中的对象没有声明toSring 方法时也需要deepToString,
// Arrays.deepToString方法就无能为力了
return toString((Object[]) obj);
}

// 如果是集合类Collection
if (Collection.class.isAssignableFrom(clazz))
{
return toString((Collection<?>) obj);
}

// 如果是映射类Map
if (Map.class.isAssignableFrom(clazz))
{
return toString((Map<?, ?>) obj);
}

// 到这里,是Bean类型的对象,反射每个字段toString
sb.append(clazz.getSimpleName()).append("{");
Field[] fields = ClassUtil.getAllField(clazz);

if (fields.length > 0)
{
boolean isAppend = false;
AccessibleObject.setAccessible(fields, true);
for (Field field : fields)
{
// 需要忽略的属性
if (isIgnoreField(field))
{
continue;
}
isAppend = true;
sb.append(field.getName()).append("=");
try
{
// 这里如果对每一个属性都调用ObjectUtil.toString()
// 对内部类,会造成堆栈溢出,需要解决
sb.append(toString(field.get(obj))).append(",");
}
catch (Exception e)
{
sb.append("???,");
}
}
if (isAppend)
{
sb.deleteCharAt(sb.length() - 1);
}
}
sb.append("}");
return sb.toString();
}

public static <T> void addAll(List<T> list, T[] array)
{
if (isNull(list) || isNull(array))
{
return;
}

for (T t : array)
{
list.add(t);
}
}

/**
* 判断属性字段是否为toString时忽略的字段属性。
*
* @param field 需要判断是否忽略属性的字段。
* @return true:为忽略属性 false:非忽略属性
*/
public static boolean isIgnoreField(Field field)
{
if (isNull(field))
{
return false;
}

// 根据名称判断总归比根据类名判断要快
return isIgnoreFieldByName(field) || isIgnoreFieldByClass(field);
}

/**
* 根据字段的Name判断是否该字段为已定义的忽略属性
*
* @param field 需要判断是否忽略属性的字段。
* @return true:为忽略属性 false:非忽略属性
*/
private static boolean isIgnoreFieldByName(Field field)
{
// 如果是已定义的需要忽略的属性
for (String fieldName : IGNORE_FIELD_NAMES)
{
if (fieldName.equals(field.getName()))
{
return true;
}
}

// 如果是需要模糊匹配需要忽略的属性
// 说明:如果一个类定义了内部类,内部类保留一个对外部类的默认引用
// 这会导致递归toString时堆栈溢出,而这个默认引用又不需要toString,所以忽略
if (field.getName().indexOf("this$") != -1)
{
return true;
}

return false;
}

/**
* 根据字段的Class判断是否该字段为已定义的忽略属性
*
* @param field 需要判断是否忽略属性的字段。
* @return true:为忽略属性 false:非忽略属性
*/
private static boolean isIgnoreFieldByClass(Field field)
{
Class<?> clazz = null;
for (String className : IGNORE_FIELD_CLASSES)
{
clazz = ReflectionUtil.forName(className);
if (clazz != null && clazz.isAssignableFrom(field.getType()))
{
return true;
}
}

return false;
}

/**
* 将对象数组转换为String。
*
* @param objs 对象数组
* @return 转换后的字符串
*/
public static String toString(Object[] objs)
{
if (isNull(objs))
{
return NULL;
}
if (objs.length == 0)
{
return "[]";
}

StringBuilder sb = new StringBuilder();
sb.append(objs.getClass().getSimpleName()).append("(length=").append(
objs.length).append(")=[");
for (Object obj : objs)
{
sb.append(toString(obj)).append(',');
}
sb.deleteCharAt(sb.length() - 1);
sb.append(']');

return sb.toString();
}

/**
* 将Collection转换为String。
*
* @param coll Collection
* @return 转换后的字符串
*/
public static String toString(Collection<?> coll)
{
if (isNull(coll))
{
return NULL;
}
if (coll.isEmpty())
{
return "{}";
}

StringBuilder sb = new StringBuilder();
sb.append(coll.getClass().getSimpleName()).append("(size=").append(
coll.size()).append(")={");
for (Object obj : coll)
{
sb.append(toString(obj)).append(',');
}
sb.deleteCharAt(sb.length() - 1);
sb.append('}');

return sb.toString();
}

/**
* 将Map转换为String。
*
* @param map Map
* @return 转换后的字符串
*/
public static String toString(Map<?, ?> map)
{
if (isNull(map))
{
return NULL;
}
if (map.isEmpty())
{
return "{}";
}

StringBuilder sb = new StringBuilder();
sb.append(map.getClass().getSimpleName());
sb.append("(size=").append(map.size()).append(")={");
for (Map.Entry<?, ?> entry : map.entrySet())
{
sb.append(toString(entry.getKey())).append('=');
sb.append(toString(entry.getValue())).append(',');
}
sb.deleteCharAt(sb.length() - 1);
sb.append('}');

return sb.toString();
}

// =============================================================
// equals()
// 1. Java 基本型别,包括基本对象型别 直接调用对象本身的equals()
// 2. 简单的Bean类型 采用反射机制比较每个属性的equals
// 3. Java集合类型 如:Collection,Map以及对象数组
// 4. 非Java基本型别的对象类型作为属性如何处理
// 5. enum类型
// 6. 内部类如何处理
// =============================================================

/**
* 通用的equals 方法
*
* @param a 对象a
* @param b 对象b
* @return true 两个对象值相等 false 两个对象值不相等
*/
public static boolean equals(Object a, Object b)
{
// 如果任何一个对象为null,认为值不等。
if (isNull(a) || isNull(b))
{
return false;
}

// 如果是同一个对象,认为值相等。
if (a == b)
{
return true;
}

Class<?> aClazz = a.getClass();

// 如果两个对象不是同一型别,认为值不等。
if (!aClazz.equals(b.getClass()))
{
return false;
}

// 以下开始,认为两个对象是相同型别的对象
// 是Java基本类型的,可以直接equals
if (ClassUtil.isJavaBasicType(aClazz))
{
return a.equals(b);
}

// 如果是数组类
if (aClazz.isArray())
{
// Java基本型别的数组,可以利用Arrays.toString()完成转化,
// 这里转为对象数组再用deepToString(),只是为了添加附加信息和减少代码
if (ClassUtil.isPrimitiveArray(aClazz)
|| ClassUtil.isPrimitiveWrapperArray(aClazz))
{
return Arrays.deepEquals(new Object[] {a}, new Object[] {b});
}

// 基本类型的数组已经处理,这里只可能是对象数组。
// 将基本型别数组与对象数字分开处理的原因是:
// 基本型别数组可以利用Arrays.deepEquals()
// 但对象数组中的对象没有声明equals 方法时也需要deepEquals,
// Arrays.deepEquals方法就无能为力了
return equals((Object[]) a, (Object[]) b);
}

// 如果是集合类
if (ClassUtil.isCollection(aClazz))
{
return equals((Collection<?>) a, (Collection<?>) b);
}

// 如果是映射类
if (ClassUtil.isMap(aClazz))
{
return equals((Map<?, ?>) a, (Map<?, ?>) b);
}

// 到这里认为是基本Bean类型,比较每一个属性。
try
{
Field[] fields = aClazz.getDeclaredFields();

// 没有声明属性
if (isEmpty(fields))
{
return true;
}

AccessibleObject.setAccessible(fields, true);
for (int i = 0; i < fields.length; i++)
{
Field field = fields[i];

if (!equals(field.get(a), field.get(b)))
{
return false;
}
}
}
catch (Exception e)
{
return false;
}

return true;
}

/**
* 通用的equals 方法
*
* @param a 对象数组a
* @param b 对象数组b
* @return true 两个对象数组值相等 false 两个对象数组值不相等
*/
public static boolean equals(Object[] a, Object[] b)
{
if (isNull(a) || isNull(b))
{
return false;
}

// 去掉这段代码,不区分对象数组具体类型,只比较值
if (!a.getClass().equals(b.getClass()))
{
return false;
}

if (a.length != b.length)
{
return false;
}

for (int i = 0; i < a.length; i++)
{
if (!equals(a[i], b[i]))
{
return false;
}
}

return true;
}

/**
* 通用的equals 方法
*
* @param a Collection a
* @param b Collection b
* @return true 两个Collection值相等 false 两个Collection值不相等
*/
public static boolean equals(Collection<?> a, Collection<?> b)
{
if (isNull(a) || isNull(b))
{
return false;
}

// 去掉这段代码,不区分集合具体子类型,只比较值
if (!a.getClass().equals(b.getClass()))
{
return false;
}

if (a.size() != b.size())
{
return false;
}

return equals(a.toArray(), b.toArray());
}

/**
* 通用的equals 方法
*
* @param a Map a
* @param b Map b
* @return true 两个Map值相等 false 两个Map值不相等
*/
public static boolean equals(Map<?, ?> a, Map<?, ?> b)
{
if (isNull(a) || isNull(b))
{
return false;
}

// 去掉这段代码,不区分映射具体子类型,只比较值
if (!a.getClass().equals(b.getClass()))
{
return false;
}

if (a.size() != b.size())
{
return false;
}

for (Map.Entry<?, ?> entry : a.entrySet())
{
if (!b.containsKey(entry.getKey())
|| !equals(entry.getValue(), b.get(entry.getKey())))
{
return false;
}
}

return true;
}

/**
* clone方法。需要克隆的对象必须实现Serializable接口
*
* @param obj 需要克隆的对象。
* @return 克隆的对象。
*/
public static Object clone(Object obj)
{
if (isNull(obj))
{
return null;
}

Object cloneObj = null;
if (obj instanceof Serializable)
{
ByteArrayOutputStream baos = null;
ObjectOutputStream oos = null;
ObjectInputStream ois = null;

try
{
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
ois = new ObjectInputStream(new ByteArrayInputStream(baos
.toByteArray()));

cloneObj = ois.readObject();
}
catch (Exception e)
{
return cloneObj;
}
finally
{
IOStreamUtil.closeQuietly(baos);
IOStreamUtil.closeQuietly(oos);
IOStreamUtil.closeQuietly(ois);
}
}

return cloneObj;
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值