Objects.java revision 7dd252788645e940eada959bdde927426e2531c9
1/*
2 * Copyright (C) 2007 The Guava 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 * http://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
17package com.google.common.base;
18
19import static com.google.common.base.Preconditions.checkNotNull;
20
21import com.google.common.annotations.GwtCompatible;
22
23import java.util.Arrays;
24
25import javax.annotation.Nullable;
26
27/**
28 * Helper functions that can operate on any {@code Object}.
29 *
30 * <p>See the Guava User Guide on <a
31 * href="http://code.google.com/p/guava-libraries/wiki/CommonObjectUtilitiesExplained">writing
32 * {@code Object} methods with {@code Objects}</a>.
33 *
34 * @author Laurence Gonsalves
35 * @since 2.0 (imported from Google Collections Library)
36 */
37@GwtCompatible
38public final class Objects {
39  private Objects() {}
40
41  /**
42   * Determines whether two possibly-null objects are equal. Returns:
43   *
44   * <ul>
45   * <li>{@code true} if {@code a} and {@code b} are both null.
46   * <li>{@code true} if {@code a} and {@code b} are both non-null and they are
47   *     equal according to {@link Object#equals(Object)}.
48   * <li>{@code false} in all other situations.
49   * </ul>
50   *
51   * <p>This assumes that any non-null objects passed to this function conform
52   * to the {@code equals()} contract.
53   */
54  public static boolean equal(@Nullable Object a, @Nullable Object b) {
55    return a == b || (a != null && a.equals(b));
56  }
57
58  /**
59   * Generates a hash code for multiple values. The hash code is generated by
60   * calling {@link Arrays#hashCode(Object[])}.
61   *
62   * <p>This is useful for implementing {@link Object#hashCode()}. For example,
63   * in an object that has three properties, {@code x}, {@code y}, and
64   * {@code z}, one could write:
65   * <pre>
66   * public int hashCode() {
67   *   return Objects.hashCode(getX(), getY(), getZ());
68   * }</pre>
69   *
70   * <b>Warning</b>: When a single object is supplied, the returned hash code
71   * does not equal the hash code of that object.
72   */
73  public static int hashCode(@Nullable Object... objects) {
74    return Arrays.hashCode(objects);
75  }
76
77  /**
78   * Creates an instance of {@link ToStringHelper}.
79   *
80   * <p>This is helpful for implementing {@link Object#toString()}.
81   * Specification by example: <pre>   {@code
82   *   // Returns "ClassName{}"
83   *   Objects.toStringHelper(this)
84   *       .toString();
85   *
86   *   // Returns "ClassName{x=1}"
87   *   Objects.toStringHelper(this)
88   *       .add("x", 1)
89   *       .toString();
90   *
91   *   // Returns "MyObject{x=1}"
92   *   Objects.toStringHelper("MyObject")
93   *       .add("x", 1)
94   *       .toString();
95   *
96   *   // Returns "ClassName{x=1, y=foo}"
97   *   Objects.toStringHelper(this)
98   *       .add("x", 1)
99   *       .add("y", "foo")
100   *       .toString();
101   *   }}
102   *
103   *   // Returns "ClassName{x=1}"
104   *   Objects.toStringHelper(this)
105   *       .omitNullValues()
106   *       .add("x", 1)
107   *       .add("y", null)
108   *       .toString();
109   *   }}</pre>
110   *
111   * <p>Note that in GWT, class names are often obfuscated.
112   *
113   * @param self the object to generate the string for (typically {@code this}),
114   *        used only for its class name
115   * @since 2.0
116   */
117  public static ToStringHelper toStringHelper(Object self) {
118    return new ToStringHelper(simpleName(self.getClass()));
119  }
120
121  /**
122   * Creates an instance of {@link ToStringHelper} in the same manner as
123   * {@link Objects#toStringHelper(Object)}, but using the name of {@code clazz}
124   * instead of using an instance's {@link Object#getClass()}.
125   *
126   * <p>Note that in GWT, class names are often obfuscated.
127   *
128   * @param clazz the {@link Class} of the instance
129   * @since 7.0 (source-compatible since 2.0)
130   */
131  public static ToStringHelper toStringHelper(Class<?> clazz) {
132    return new ToStringHelper(simpleName(clazz));
133  }
134
135  /**
136   * Creates an instance of {@link ToStringHelper} in the same manner as
137   * {@link Objects#toStringHelper(Object)}, but using {@code className} instead
138   * of using an instance's {@link Object#getClass()}.
139   *
140   * @param className the name of the instance type
141   * @since 7.0 (source-compatible since 2.0)
142   */
143  public static ToStringHelper toStringHelper(String className) {
144    return new ToStringHelper(className);
145  }
146
147  /**
148   * {@link Class#getSimpleName()} is not GWT compatible yet, so we
149   * provide our own implementation.
150   */
151  private static String simpleName(Class<?> clazz) {
152    String name = clazz.getName();
153
154    // the nth anonymous class has a class name ending in "Outer$n"
155    // and local inner classes have names ending in "Outer.$1Inner"
156    name = name.replaceAll("\\$[0-9]+", "\\$");
157
158    // we want the name of the inner class all by its lonesome
159    int start = name.lastIndexOf('$');
160
161    // if this isn't an inner class, just find the start of the
162    // top level class name.
163    if (start == -1) {
164      start = name.lastIndexOf('.');
165    }
166    return name.substring(start + 1);
167  }
168
169  /**
170   * Returns the first of two given parameters that is not {@code null}, if
171   * either is, or otherwise throws a {@link NullPointerException}.
172   *
173   * <p><b>Note:</b> if {@code first} is represented as an {@code Optional<T>},
174   * this can be accomplished with {@code first.or(second)}. That approach also
175   * allows for lazy evaluation of the fallback instance, using
176   * {@code first.or(Supplier)}.
177   *
178   * @return {@code first} if {@code first} is not {@code null}, or
179   *     {@code second} if {@code first} is {@code null} and {@code second} is
180   *     not {@code null}
181   * @throws NullPointerException if both {@code first} and {@code second} were
182   *     {@code null}
183   * @since 3.0
184   */
185  public static <T> T firstNonNull(@Nullable T first, @Nullable T second) {
186    return first != null ? first : checkNotNull(second);
187  }
188
189  /**
190   * Support class for {@link Objects#toStringHelper}.
191   *
192   * @author Jason Lee
193   * @since 2.0
194   */
195  public static final class ToStringHelper {
196    private final String className;
197    private ValueHolder holderHead = new ValueHolder();
198    private ValueHolder holderTail = holderHead;
199    private boolean omitNullValues = false;
200
201    /**
202     * Use {@link Objects#toStringHelper(Object)} to create an instance.
203     */
204    private ToStringHelper(String className) {
205      this.className = checkNotNull(className);
206    }
207
208    /**
209     * Configures the {@link ToStringHelper} so {@link #toString()} will ignore
210     * properties with null value. The order of calling this method, relative
211     * to the {@code add()}/{@code addValue()} methods, is not significant.
212     *
213     * @since 12.0
214     */
215    public ToStringHelper omitNullValues() {
216      omitNullValues = true;
217      return this;
218    }
219
220    /**
221     * Adds a name/value pair to the formatted output in {@code name=value}
222     * format. If {@code value} is {@code null}, the string {@code "null"}
223     * is used, unless {@link #omitNullValues()} is called, in which case this
224     * name/value pair will not be added.
225     */
226    public ToStringHelper add(String name, @Nullable Object value) {
227      return addHolder(name, value);
228    }
229
230    /**
231     * Adds a name/value pair to the formatted output in {@code name=value}
232     * format.
233     *
234     * @since 11.0 (source-compatible since 2.0)
235     */
236    public ToStringHelper add(String name, boolean value) {
237      return addHolder(name, String.valueOf(value));
238    }
239
240    /**
241     * Adds a name/value pair to the formatted output in {@code name=value}
242     * format.
243     *
244     * @since 11.0 (source-compatible since 2.0)
245     */
246    public ToStringHelper add(String name, char value) {
247      return addHolder(name, String.valueOf(value));
248    }
249
250    /**
251     * Adds a name/value pair to the formatted output in {@code name=value}
252     * format.
253     *
254     * @since 11.0 (source-compatible since 2.0)
255     */
256    public ToStringHelper add(String name, double value) {
257      return addHolder(name, String.valueOf(value));
258    }
259
260    /**
261     * Adds a name/value pair to the formatted output in {@code name=value}
262     * format.
263     *
264     * @since 11.0 (source-compatible since 2.0)
265     */
266    public ToStringHelper add(String name, float value) {
267      return addHolder(name, String.valueOf(value));
268    }
269
270    /**
271     * Adds a name/value pair to the formatted output in {@code name=value}
272     * format.
273     *
274     * @since 11.0 (source-compatible since 2.0)
275     */
276    public ToStringHelper add(String name, int value) {
277      return addHolder(name, String.valueOf(value));
278    }
279
280    /**
281     * Adds a name/value pair to the formatted output in {@code name=value}
282     * format.
283     *
284     * @since 11.0 (source-compatible since 2.0)
285     */
286    public ToStringHelper add(String name, long value) {
287      return addHolder(name, String.valueOf(value));
288    }
289
290    /**
291     * Adds an unnamed value to the formatted output.
292     *
293     * <p>It is strongly encouraged to use {@link #add(String, Object)} instead
294     * and give value a readable name.
295     */
296    public ToStringHelper addValue(@Nullable Object value) {
297      return addHolder(value);
298    }
299
300    /**
301     * Adds an unnamed value to the formatted output.
302     *
303     * <p>It is strongly encouraged to use {@link #add(String, boolean)} instead
304     * and give value a readable name.
305     *
306     * @since 11.0 (source-compatible since 2.0)
307     */
308    public ToStringHelper addValue(boolean value) {
309      return addHolder(String.valueOf(value));
310    }
311
312    /**
313     * Adds an unnamed value to the formatted output.
314     *
315     * <p>It is strongly encouraged to use {@link #add(String, char)} instead
316     * and give value a readable name.
317     *
318     * @since 11.0 (source-compatible since 2.0)
319     */
320    public ToStringHelper addValue(char value) {
321      return addHolder(String.valueOf(value));
322    }
323
324    /**
325     * Adds an unnamed value to the formatted output.
326     *
327     * <p>It is strongly encouraged to use {@link #add(String, double)} instead
328     * and give value a readable name.
329     *
330     * @since 11.0 (source-compatible since 2.0)
331     */
332    public ToStringHelper addValue(double value) {
333      return addHolder(String.valueOf(value));
334    }
335
336    /**
337     * Adds an unnamed value to the formatted output.
338     *
339     * <p>It is strongly encouraged to use {@link #add(String, float)} instead
340     * and give value a readable name.
341     *
342     * @since 11.0 (source-compatible since 2.0)
343     */
344    public ToStringHelper addValue(float value) {
345      return addHolder(String.valueOf(value));
346    }
347
348    /**
349     * Adds an unnamed value to the formatted output.
350     *
351     * <p>It is strongly encouraged to use {@link #add(String, int)} instead
352     * and give value a readable name.
353     *
354     * @since 11.0 (source-compatible since 2.0)
355     */
356    public ToStringHelper addValue(int value) {
357      return addHolder(String.valueOf(value));
358    }
359
360    /**
361     * Adds an unnamed value to the formatted output.
362     *
363     * <p>It is strongly encouraged to use {@link #add(String, long)} instead
364     * and give value a readable name.
365     *
366     * @since 11.0 (source-compatible since 2.0)
367     */
368    public ToStringHelper addValue(long value) {
369      return addHolder(String.valueOf(value));
370    }
371
372    /**
373     * Returns a string in the format specified by {@link
374     * Objects#toStringHelper(Object)}.
375     *
376     * <p>After calling this method, you can keep adding more properties to later
377     * call toString() again and get a more complete representation of the
378     * same object; but properties cannot be removed, so this only allows
379     * limited reuse of the helper instance. The helper allows duplication of
380     * properties (multiple name/value pairs with the same name can be added).
381     */
382    @Override
383    public String toString() {
384      // create a copy to keep it consistent in case value changes
385      boolean omitNullValuesSnapshot = omitNullValues;
386      String nextSeparator = "";
387      StringBuilder builder = new StringBuilder(32).append(className).append('{');
388      for (ValueHolder valueHolder = holderHead.next; valueHolder != null; valueHolder = valueHolder.next) {
389        if (!omitNullValuesSnapshot || valueHolder.value != null) {
390          builder.append(nextSeparator);
391          nextSeparator = ", ";
392
393          if (valueHolder.name != null) {
394            builder.append(valueHolder.name).append('=');
395          }
396          builder.append(valueHolder.value);
397        }
398      }
399      return builder.append('}').toString();
400    }
401
402    private ValueHolder addHolder() {
403      ValueHolder valueHolder = new ValueHolder();
404      holderTail = holderTail.next = valueHolder;
405      return valueHolder;
406    }
407
408    private ToStringHelper addHolder(@Nullable Object value) {
409      ValueHolder valueHolder = addHolder();
410      valueHolder.value = value;
411      return this;
412    }
413
414    private ToStringHelper addHolder(String name, @Nullable Object value) {
415      ValueHolder valueHolder = addHolder();
416      valueHolder.value = value;
417      valueHolder.name = checkNotNull(name);
418      return this;
419    }
420
421    private static final class ValueHolder {
422      String name;
423      Object value;
424      ValueHolder next;
425    }
426  }
427}
428