/* * 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(); } } }