View Javadoc
1   /*
2    *    Copyright 2009-2023 the original author or authors.
3    *
4    *    Licensed under the Apache License, Version 2.0 (the "License");
5    *    you may not use this file except in compliance with the License.
6    *    You may obtain a copy of the License at
7    *
8    *       https://www.apache.org/licenses/LICENSE-2.0
9    *
10   *    Unless required by applicable law or agreed to in writing, software
11   *    distributed under the License is distributed on an "AS IS" BASIS,
12   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *    See the License for the specific language governing permissions and
14   *    limitations under the License.
15   */
16  package org.apache.ibatis.reflection;
17  
18  import java.util.Arrays;
19  
20  /**
21   * Provides hashCode, equals and toString methods that can handle array.
22   */
23  public class ArrayUtil {
24  
25    /**
26     * Returns a hash code for {@code obj}.
27     *
28     * @param obj
29     *          The object to get a hash code for. May be an array or <code>null</code>.
30     *
31     * @return A hash code of {@code obj} or 0 if {@code obj} is <code>null</code>
32     */
33    public static int hashCode(Object obj) {
34      if (obj == null) {
35        // for consistency with Arrays#hashCode() and Objects#hashCode()
36        return 0;
37      }
38      final Class<?> clazz = obj.getClass();
39      if (!clazz.isArray()) {
40        return obj.hashCode();
41      }
42      final Class<?> componentType = clazz.getComponentType();
43      if (long.class.equals(componentType)) {
44        return Arrays.hashCode((long[]) obj);
45      }
46      if (int.class.equals(componentType)) {
47        return Arrays.hashCode((int[]) obj);
48      } else if (short.class.equals(componentType)) {
49        return Arrays.hashCode((short[]) obj);
50      } else if (char.class.equals(componentType)) {
51        return Arrays.hashCode((char[]) obj);
52      } else if (byte.class.equals(componentType)) {
53        return Arrays.hashCode((byte[]) obj);
54      } else if (boolean.class.equals(componentType)) {
55        return Arrays.hashCode((boolean[]) obj);
56      } else if (float.class.equals(componentType)) {
57        return Arrays.hashCode((float[]) obj);
58      } else if (double.class.equals(componentType)) {
59        return Arrays.hashCode((double[]) obj);
60      } else {
61        return Arrays.hashCode((Object[]) obj);
62      }
63    }
64  
65    /**
66     * Compares two objects. Returns <code>true</code> if
67     * <ul>
68     * <li>{@code thisObj} and {@code thatObj} are both <code>null</code></li>
69     * <li>{@code thisObj} and {@code thatObj} are instances of the same type and {@link Object#equals(Object)} returns
70     * <code>true</code></li>
71     * <li>{@code thisObj} and {@code thatObj} are arrays with the same component type and equals() method of
72     * {@link Arrays} returns <code>true</code> (not deepEquals())</li>
73     * </ul>
74     *
75     * @param thisObj
76     *          The left hand object to compare. May be an array or <code>null</code>
77     * @param thatObj
78     *          The right hand object to compare. May be an array or <code>null</code>
79     *
80     * @return <code>true</code> if two objects are equal; <code>false</code> otherwise.
81     */
82    public static boolean equals(Object thisObj, Object thatObj) {
83      if (thisObj == null) {
84        return thatObj == null;
85      }
86      if (thatObj == null) {
87        return false;
88      }
89      final Class<?> clazz = thisObj.getClass();
90      if (!clazz.equals(thatObj.getClass())) {
91        return false;
92      }
93      if (!clazz.isArray()) {
94        return thisObj.equals(thatObj);
95      }
96      final Class<?> componentType = clazz.getComponentType();
97      if (long.class.equals(componentType)) {
98        return Arrays.equals((long[]) thisObj, (long[]) thatObj);
99      }
100     if (int.class.equals(componentType)) {
101       return Arrays.equals((int[]) thisObj, (int[]) thatObj);
102     } else if (short.class.equals(componentType)) {
103       return Arrays.equals((short[]) thisObj, (short[]) thatObj);
104     } else if (char.class.equals(componentType)) {
105       return Arrays.equals((char[]) thisObj, (char[]) thatObj);
106     } else if (byte.class.equals(componentType)) {
107       return Arrays.equals((byte[]) thisObj, (byte[]) thatObj);
108     } else if (boolean.class.equals(componentType)) {
109       return Arrays.equals((boolean[]) thisObj, (boolean[]) thatObj);
110     } else if (float.class.equals(componentType)) {
111       return Arrays.equals((float[]) thisObj, (float[]) thatObj);
112     } else if (double.class.equals(componentType)) {
113       return Arrays.equals((double[]) thisObj, (double[]) thatObj);
114     } else {
115       return Arrays.equals((Object[]) thisObj, (Object[]) thatObj);
116     }
117   }
118 
119   /**
120    * If the {@code obj} is an array, toString() method of {@link Arrays} is called. Otherwise {@link Object#toString()}
121    * is called. Returns "null" if {@code obj} is <code>null</code>.
122    *
123    * @param obj
124    *          An object. May be an array or <code>null</code>.
125    *
126    * @return String representation of the {@code obj}.
127    */
128   public static String toString(Object obj) {
129     if (obj == null) {
130       return "null";
131     }
132     final Class<?> clazz = obj.getClass();
133     if (!clazz.isArray()) {
134       return obj.toString();
135     }
136     final Class<?> componentType = obj.getClass().getComponentType();
137     if (long.class.equals(componentType)) {
138       return Arrays.toString((long[]) obj);
139     }
140     if (int.class.equals(componentType)) {
141       return Arrays.toString((int[]) obj);
142     } else if (short.class.equals(componentType)) {
143       return Arrays.toString((short[]) obj);
144     } else if (char.class.equals(componentType)) {
145       return Arrays.toString((char[]) obj);
146     } else if (byte.class.equals(componentType)) {
147       return Arrays.toString((byte[]) obj);
148     } else if (boolean.class.equals(componentType)) {
149       return Arrays.toString((boolean[]) obj);
150     } else if (float.class.equals(componentType)) {
151       return Arrays.toString((float[]) obj);
152     } else if (double.class.equals(componentType)) {
153       return Arrays.toString((double[]) obj);
154     } else {
155       return Arrays.toString((Object[]) obj);
156     }
157   }
158 
159   private ArrayUtil() {
160   }
161 
162 }