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