/*
* Copyright (c) 2002-2012 Alibaba Group Holding Limited.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.citrus.util;
import static com.alibaba.citrus.util.Assert.*;
import static com.alibaba.citrus.util.BasicConstant.*;
import java.io.IOException;
import java.util.Arrays;
/**
* 有关<code>Object</code>处理的工具类。
* <p>
* 这个类中的每个方法都可以“安全”地处理<code>null</code>,而不会抛出<code>NullPointerException</code>。
* </p>
*
* @author Michael Zhou
*/
public class ObjectUtil {
// ==========================================================================
// 判空函数。
// ==========================================================================
/** 是否为<code>null</code>、空字符串、或空数组。 */
public static boolean isEmptyObject(Object object) {
if (object == null) {
return true;
} else if (object instanceof String) {
return StringUtil.isEmpty((String) object);
} else if (object.getClass().isArray()) {
return ArrayUtil.isEmptyArray(object);
} else {
return false;
}
}
// ==========================================================================
// 默认值函数。
//
// 当对象为null时,将对象转换成指定的默认对象。
// ==========================================================================
/**
* 如果对象为<code>null</code>,则返回指定默认对象,否则返回对象本身。
* <p/>
* <pre>
* ObjectUtil.defaultIfNull(null, null) = null
* ObjectUtil.defaultIfNull(null, "") = ""
* ObjectUtil.defaultIfNull(null, "zz") = "zz"
* ObjectUtil.defaultIfNull("abc", *) = "abc"
* ObjectUtil.defaultIfNull(Boolean.TRUE, *) = Boolean.TRUE
* </pre>
*
* @param object 要测试的对象
* @param defaultValue 默认值
* @return 对象本身或默认对象
*/
public static <T, S extends T> T defaultIfNull(T object, S defaultValue) {
return object == null ? defaultValue : object;
}
// ==========================================================================
// 比较函数。
//
// 以下方法用来比较两个对象的值或类型是否相同。
// ==========================================================================
/**
* 比较两个对象是否完全相等。
* <p>
* 此方法可以正确地比较多维数组。
* <p/>
* <pre>
* ObjectUtil.equals(null, null) = true
* ObjectUtil.equals(null, "") = false
* ObjectUtil.equals("", null) = false
* ObjectUtil.equals("", "") = true
* ObjectUtil.equals(Boolean.TRUE, null) = false
* ObjectUtil.equals(Boolean.TRUE, "true") = false
* ObjectUtil.equals(Boolean.TRUE, Boolean.TRUE) = true
* ObjectUtil.equals(Boolean.TRUE, Boolean.FALSE) = false
* </pre>
* <p/>
* </p>
*
* @param object1 对象1
* @param object2 对象2
* @return 如果相等, 则返回<code>true</code>
*/
public static boolean isEquals(Object object1, Object object2) {
if (object1 == object2) {
return true;
}
if (object1 == null || object2 == null) {
return false;
}
if (!object1.getClass().equals(object2.getClass())) {
return false;
}
if (object1 instanceof Object[]) {
return Arrays.deepEquals((Object[]) object1, (Object[]) object2);
} else if (object1 instanceof int[]) {
return Arrays.equals((int[]) object1, (int[]) object2);
} else if (object1 instanceof long[]) {
return Arrays.equals((long[]) object1, (long[]) object2);
} else if (object1 instanceof short[]) {
return Arrays.equals((short[]) object1, (short[]) object2);
} else if (object1 instanceof byte[]) {
return Arrays.equals((byte[]) object1, (byte[]) object2);
} else if (object1 instanceof double[]) {
return Arrays.equals((double[]) object1, (double[]) object2);
} else if (object1 instanceof float[]) {
return Arrays.equals((float[]) object1, (float[]) object2);
} else if (object1 instanceof char[]) {
return Arrays.equals((char[]) object1, (char[]) object2);
} else if (object1 instanceof boolean[]) {
return Arrays.equals((boolean[]) object1, (boolean[]) object2);
} else {
return object1.equals(object2);
}
}
/**
* 检查两个对象是否属于相同类型。<code>null</code>将被看作任意类型。
*
* @param object1 对象1
* @param object2 对象2
* @return 如果两个对象有相同的类型,则返回<code>true</code>
*/
public static boolean isSameType(Object object1, Object object2) {
if (object1 == null || object2 == null) {
return true;
}
return object1.getClass().equals(object2.getClass());
}
// ==========================================================================
// Hash code函数。
//
// 以下方法用来取得对象的hash code。
// ==========================================================================
/**
* 取得对象的hash值, 如果对象为<code>null</code>, 则返回<code>0</code>。
* <p>
* 此方法可以正确地处理多维数组。
* </p>
*
* @param object 对象
* @return hash值
*/
public static int hashCode(Object object) {
if (object == null) {
return 0;
} else if (object instanceof Object[]) {
return Arrays.deepHashCode((Object[]) object);
} else if (object instanceof int[]) {
return Arrays.hashCode((int[]) object);
} else if (object instanceof long[]) {
return Arrays.hashCode((long[]) object);
} else if (object instanceof short[]) {
return Arrays.hashCode((short[]) object);
} else if (object instanceof byte[]) {
return Arrays.hashCode((byte[]) object);
} else if (object instanceof double[]) {
return Arrays.hashCode((double[]) object);
} else if (object instanceof float[]) {
return Arrays.hashCode((float[]) object);
} else if (object instanceof char[]) {
return Arrays.hashCode((char[]) object);
} else if (object instanceof boolean[]) {
return Arrays.hashCode((boolean[]) object);
} else {
return object.hashCode();
}
}
// ==========================================================================
// 取得对象的identity。
// ==========================================================================
/**
* 取得对象的原始的hash值, 如果对象为<code>null</code>, 则返回<code>0</code>。
* <p>
* 该方法使用<code>System.identityHashCode</code>来取得hash值,该值不受对象本身的
* <code>hashCode</code>方法的影响。
* </p>
*
* @param object 对象
* @return hash值
*/
public static int identityHashCode(Object object) {
return object == null ? 0 : System.identityHashCode(object);
}
/**
* 取得对象自身的identity,如同对象没有覆盖<code>toString()</code>方法时,
* <code>Object.toString()</code>的原始输出。
* <p/>
* <pre>
* ObjectUtil.identityToString(null) = null
* ObjectUtil.identityToString("") = "java.lang.String@1e23"
* ObjectUtil.identityToString(Boolean.TRUE) = "java.lang.Boolean@7fa"
* ObjectUtil.identityToString(new int[0]) = "int[]@7fa"
* ObjectUtil.identityToString(new Object[0]) = "java.lang.Object[]@7fa"
* </pre>
*
* @param object 对象
* @return 对象的identity,如果对象是<code>null</code>,则返回<code>null</code>
*/
public static String identityToString(Object object) {
if (object == null) {
return null;
}
return appendIdentityToString(new StringBuilder(), object).toString();
}
/**
* 取得对象自身的identity,如同对象没有覆盖<code>toString()</code>方法时,
* <code>Object.toString()</code>的原始输出。
* <p/>
* <pre>
* ObjectUtil.identityToString(null, "NULL") = "NULL"
* ObjectUtil.identityToString("", "NULL") = "java.lang.String@1e23"
* ObjectUtil.identityToString(Boolean.TRUE, "NULL") = "java.lang.Boolean@7fa"
* ObjectUtil.identityToString(new int[0], "NULL") = "int[]@7fa"
* ObjectUtil.identityToString(new Object[0], "NULL") = "java.lang.Object[]@7fa"
* </pre>
*
* @param object 对象
* @param nullStr 如果对象为<code>null</code>,则返回该字符串
* @return 对象的identity,如果对象是<code>null</code>,则返回指定字符串
*/
public static String identityToString(Object object, String nullStr) {
if (object == null) {
return nullStr;
}
return appendIdentityToString(new StringBuilder(), object).toString();
}
/**
* 将对象自身的identity——如同对象没有覆盖<code>toString()</code>方法时,
* <code>Object.toString()</code>的原始输出——追加到<code>Appendable</code>中。
* <p/>
* <pre>
* ObjectUtil.appendIdentityToString(buf, null) = null
* ObjectUtil.appendIdentityToString(buf, Boolean.TRUE) = buf.append("java.lang.Boolean@7fa")
* ObjectUtil.appendIdentityToString(buf, new int[0]) = buf.append("int[]@7fa")
* ObjectUtil.appendIdentityToString(buf, new Object[0]) = buf.append("java.lang.Object[]@7fa")
* </pre>
*
* @param buffer <code>Appendable</code>对象
* @param object 对象
* @return <code>Appendable</code>对象,如果对象为<code>null</code>,则输出
* <code>"null"</code>
*/
public static <A extends Appendable> A appendIdentityToString(A buffer, Object object) {
assertNotNull(buffer, "appendable");
try {
if (object == null) {
buffer.append("null");
} else {
buffer.append(ClassUtil.getFriendlyClassNameForObject(object));
buffer.append('@').append(Integer.toHexString(identityHashCode(object)));
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return buffer;
}
// ==========================================================================
// toString方法。
// ==========================================================================
/**
* 取得对象的<code>toString()</code>的值,如果对象为<code>null</code>,则返回空字符串
* <code>""</code>。
* <p/>
* <pre>
* ObjectUtil.toString(null) = ""
* ObjectUtil.toString("") = ""
* ObjectUtil.toString("bat") = "bat"
* ObjectUtil.toString(Boolean.TRUE) = "true"
* ObjectUtil.toString([1, 2, 3]) = "[1, 2, 3]"
* </pre>
*
* @param object 对象
* @return 对象的<code>toString()</code>的返回值,或空字符串<code>""</code>
*/
public static String toString(Object object) {
return toString(object, EMPTY_STRING);
}
/**
* 取得对象的<code>toString()</code>的值,如果对象为<code>null</code>,则返回指定字符串。
* <p/>
* <pre>
* ObjectUtil.toString(null, null) = null
* ObjectUtil.toString(null, "null") = "null"
* ObjectUtil.toString("", "null") = ""
* ObjectUtil.toString("bat", "null") = "bat"
* ObjectUtil.toString(Boolean.TRUE, "null") = "true"
* ObjectUtil.toString([1, 2, 3], "null") = "[1, 2, 3]"
* </pre>
*
* @param object 对象
* @param nullStr 如果对象为<code>null</code>,则返回该字符串
* @return 对象的<code>toString()</code>的返回值,或指定字符串
*/
public static String toString(Object object, String nullStr) {
if (object == null) {
return nullStr;
} else if (object instanceof Object[]) {
return Arrays.deepToString((Object[]) object);
} else if (object instanceof int[]) {
return Arrays.toString((int[]) object);
} else if (object instanceof long[]) {
return Arrays.toString((long[]) object);
} else if (object instanceof short[]) {
return Arrays.toString((short[]) object);
} else if (object instanceof byte[]) {
return Arrays.toString((byte[]) object);
} else if (object instanceof double[]) {
return Arrays.toString((double[]) object);
} else if (object instanceof float[]) {
return Arrays.toString((float[]) object);
} else if (object instanceof char[]) {
return Arrays.toString((char[]) object);
} else if (object instanceof boolean[]) {
return Arrays.toString((boolean[]) object);
} else {
return object.toString();
}
}
}