001/*
002 * Copyright (C) 2007 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005 * in compliance with the License. You may obtain a copy of the License at
006 *
007 * http://www.apache.org/licenses/LICENSE-2.0
008 *
009 * Unless required by applicable law or agreed to in writing, software distributed under the License
010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011 * or implied. See the License for the specific language governing permissions and limitations under
012 * the License.
013 */
014
015package com.google.common.base;
016
017import static com.google.common.base.Preconditions.checkNotNull;
018
019import com.google.common.annotations.GwtCompatible;
020import com.google.errorprone.annotations.CanIgnoreReturnValue;
021import java.util.Arrays;
022import org.checkerframework.checker.nullness.qual.Nullable;
023
024/**
025 * Helper functions that can operate on any {@code Object}.
026 *
027 * <p>See the Guava User Guide on <a
028 * href="https://github.com/google/guava/wiki/CommonObjectUtilitiesExplained">writing {@code Object}
029 * methods with {@code Objects}</a>.
030 *
031 * @author Laurence Gonsalves
032 * @since 2.0
033 */
034@GwtCompatible
035public final class Objects extends ExtraObjectsMethodsForWeb {
036  private Objects() {}
037
038  /**
039   * Determines whether two possibly-null objects are equal. Returns:
040   *
041   * <ul>
042   *   <li>{@code true} if {@code a} and {@code b} are both null.
043   *   <li>{@code true} if {@code a} and {@code b} are both non-null and they are equal according to
044   *       {@link Object#equals(Object)}.
045   *   <li>{@code false} in all other situations.
046   * </ul>
047   *
048   * <p>This assumes that any non-null objects passed to this function conform to the {@code
049   * equals()} contract.
050   *
051   * <p><b>Note for Java 7 and later:</b> This method should be treated as deprecated; use {@link
052   * java.util.Objects#equals} instead.
053   */
054  public static boolean equal(@Nullable Object a, @Nullable Object b) {
055    return a == b || (a != null && a.equals(b));
056  }
057
058  /**
059   * Generates a hash code for multiple values. The hash code is generated by calling {@link
060   * Arrays#hashCode(Object[])}. Note that array arguments to this method, with the exception of a
061   * single Object array, do not get any special handling; their hash codes are based on identity
062   * and not contents.
063   *
064   * <p>This is useful for implementing {@link Object#hashCode()}. For example, in an object that
065   * has three properties, {@code x}, {@code y}, and {@code z}, one could write:
066   *
067   * <pre>{@code
068   * public int hashCode() {
069   *   return Objects.hashCode(getX(), getY(), getZ());
070   * }
071   * }</pre>
072   *
073   * <p><b>Warning:</b> When a single object is supplied, the returned hash code does not equal the
074   * hash code of that object.
075   *
076   * <p><b>Note for Java 7 and later:</b> This method should be treated as deprecated; use {@link
077   * java.util.Objects#hash} instead.
078   */
079  public static int hashCode(@Nullable Object @Nullable ... objects) {
080    return Arrays.hashCode(objects);
081  }
082
083  /**
084   * Returns the first of two given parameters that is not {@code null}, if either is, or otherwise
085   * throws a {@link NullPointerException}.
086   *
087   * <p><b>Note:</b> if {@code first} is represented as an {@link Optional}, this can be
088   * accomplished with {@linkplain Optional#or(Object) first.or(second)}. That approach also allows
089   * for lazy evaluation of the fallback instance, using {@linkplain Optional#or(Supplier)
090   * first.or(Supplier)}.
091   *
092   * @return {@code first} if {@code first} is not {@code null}, or {@code second} if {@code first}
093   *     is {@code null} and {@code second} is not {@code null}
094   * @throws NullPointerException if both {@code first} and {@code second} were {@code null}
095   * @since 3.0
096   * @deprecated Use {@link MoreObjects#firstNonNull} instead. This method is scheduled for removal
097   *     in Guava 21.0.
098   */
099  @Deprecated
100  public static <T> T firstNonNull(@Nullable T first, @Nullable T second) {
101    return MoreObjects.firstNonNull(first, second);
102  }
103
104  /**
105   * Creates an instance of {@link ToStringHelper}.
106   *
107   * <p>This is helpful for implementing {@link Object#toString()}. Specification by example:
108   *
109   * <pre>   {@code
110   *   // Returns "ClassName{}"
111   *   Objects.toStringHelper(this)
112   *       .toString();
113   *
114   *   // Returns "ClassName{x=1}"
115   *   Objects.toStringHelper(this)
116   *       .add("x", 1)
117   *       .toString();
118   *
119   *   // Returns "MyObject{x=1}"
120   *   Objects.toStringHelper("MyObject")
121   *       .add("x", 1)
122   *       .toString();
123   *
124   *   // Returns "ClassName{x=1, y=foo}"
125   *   Objects.toStringHelper(this)
126   *       .add("x", 1)
127   *       .add("y", "foo")
128   *       .toString();
129   *
130   *   // Returns "ClassName{x=1}"
131   *   Objects.toStringHelper(this)
132   *       .omitNullValues()
133   *       .add("x", 1)
134   *       .add("y", null)
135   *       .toString();
136   *   }}</pre>
137   *
138   * <p>Note that in GWT, class names are often obfuscated.
139   *
140   * @param self the object to generate the string for (typically {@code this}), used only for its
141   *     class name
142   * @since 2.0
143   * @deprecated Use {@link MoreObjects#toStringHelper(Object)} instead. This method is scheduled
144   *     for removal in Guava 21.0.
145   */
146  @Deprecated
147  public static ToStringHelper toStringHelper(Object self) {
148    return new ToStringHelper(self.getClass().getSimpleName());
149  }
150
151  /**
152   * Creates an instance of {@link ToStringHelper} in the same manner as
153   * {@link Objects#toStringHelper(Object)}, but using the name of {@code clazz} instead of using an
154   * instance's {@link Object#getClass()}.
155   *
156   * <p>Note that in GWT, class names are often obfuscated.
157   *
158   * @param clazz the {@link Class} of the instance
159   * @since 7.0 (source-compatible since 2.0)
160   * @deprecated Use {@link MoreObjects#toStringHelper(Class)} instead. This method is scheduled for
161   *     removal in Guava 21.0.
162   */
163  @Deprecated
164  public static ToStringHelper toStringHelper(Class<?> clazz) {
165    return new ToStringHelper(clazz.getSimpleName());
166  }
167
168  /**
169   * Creates an instance of {@link ToStringHelper} in the same manner as
170   * {@link Objects#toStringHelper(Object)}, but using {@code className} instead of using an
171   * instance's {@link Object#getClass()}.
172   *
173   * @param className the name of the instance type
174   * @since 7.0 (source-compatible since 2.0)
175   * @deprecated Use {@link MoreObjects#toStringHelper(String)} instead. This method is scheduled
176   *     for removal in Guava 21.0.
177   */
178  @Deprecated
179  public static ToStringHelper toStringHelper(String className) {
180    return new ToStringHelper(className);
181  }
182
183  /**
184   * Support class for {@link Objects#toStringHelper}.
185   *
186   * @author Jason Lee
187   * @since 2.0
188   * @deprecated Use {@link MoreObjects.ToStringHelper} instead. This class is scheduled for removal
189   *     in Guava 21.0.
190   */
191  @Deprecated
192  public static final class ToStringHelper {
193    private final String className;
194    private final ValueHolder holderHead = new ValueHolder();
195    private ValueHolder holderTail = holderHead;
196    private boolean omitNullValues = false;
197
198    /**
199     * Use {@link Objects#toStringHelper(Object)} to create an instance.
200     */
201    private ToStringHelper(String className) {
202      this.className = checkNotNull(className);
203    }
204
205    /**
206     * Configures the {@link ToStringHelper} so {@link #toString()} will ignore properties with null
207     * value. The order of calling this method, relative to the {@code add()}/{@code addValue()}
208     * methods, is not significant.
209     *
210     * @since 12.0
211     */
212    @CanIgnoreReturnValue
213    public ToStringHelper omitNullValues() {
214      omitNullValues = true;
215      return this;
216    }
217
218    /**
219     * Adds a name/value pair to the formatted output in {@code name=value} format. If {@code value}
220     * is {@code null}, the string {@code "null"} is used, unless {@link #omitNullValues()} is
221     * called, in which case this name/value pair will not be added.
222     */
223    @CanIgnoreReturnValue
224    public ToStringHelper add(String name, @Nullable Object value) {
225      return addHolder(name, value);
226    }
227
228    /**
229     * Adds a name/value pair to the formatted output in {@code name=value} format.
230     *
231     * @since 11.0 (source-compatible since 2.0)
232     */
233    @CanIgnoreReturnValue
234    public ToStringHelper add(String name, boolean value) {
235      return addHolder(name, String.valueOf(value));
236    }
237
238    /**
239     * Adds a name/value pair to the formatted output in {@code name=value} format.
240     *
241     * @since 11.0 (source-compatible since 2.0)
242     */
243    @CanIgnoreReturnValue
244    public ToStringHelper add(String name, char value) {
245      return addHolder(name, String.valueOf(value));
246    }
247
248    /**
249     * Adds a name/value pair to the formatted output in {@code name=value} format.
250     *
251     * @since 11.0 (source-compatible since 2.0)
252     */
253    @CanIgnoreReturnValue
254    public ToStringHelper add(String name, double value) {
255      return addHolder(name, String.valueOf(value));
256    }
257
258    /**
259     * Adds a name/value pair to the formatted output in {@code name=value} format.
260     *
261     * @since 11.0 (source-compatible since 2.0)
262     */
263    @CanIgnoreReturnValue
264    public ToStringHelper add(String name, float value) {
265      return addHolder(name, String.valueOf(value));
266    }
267
268    /**
269     * Adds a name/value pair to the formatted output in {@code name=value} format.
270     *
271     * @since 11.0 (source-compatible since 2.0)
272     */
273    @CanIgnoreReturnValue
274    public ToStringHelper add(String name, int value) {
275      return addHolder(name, String.valueOf(value));
276    }
277
278    /**
279     * Adds a name/value pair to the formatted output in {@code name=value} format.
280     *
281     * @since 11.0 (source-compatible since 2.0)
282     */
283    @CanIgnoreReturnValue
284    public ToStringHelper add(String name, long value) {
285      return addHolder(name, String.valueOf(value));
286    }
287
288    /**
289     * Adds an unnamed value to the formatted output.
290     *
291     * <p>It is strongly encouraged to use {@link #add(String, Object)} instead and give value a
292     * readable name.
293     */
294    @CanIgnoreReturnValue
295    public ToStringHelper addValue(@Nullable Object value) {
296      return addHolder(value);
297    }
298
299    /**
300     * Adds an unnamed value to the formatted output.
301     *
302     * <p>It is strongly encouraged to use {@link #add(String, boolean)} instead and give value a
303     * readable name.
304     *
305     * @since 11.0 (source-compatible since 2.0)
306     */
307    @CanIgnoreReturnValue
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 and give value a
316     * readable name.
317     *
318     * @since 11.0 (source-compatible since 2.0)
319     */
320    @CanIgnoreReturnValue
321    public ToStringHelper addValue(char value) {
322      return addHolder(String.valueOf(value));
323    }
324
325    /**
326     * Adds an unnamed value to the formatted output.
327     *
328     * <p>It is strongly encouraged to use {@link #add(String, double)} instead and give value a
329     * readable name.
330     *
331     * @since 11.0 (source-compatible since 2.0)
332     */
333    @CanIgnoreReturnValue
334    public ToStringHelper addValue(double value) {
335      return addHolder(String.valueOf(value));
336    }
337
338    /**
339     * Adds an unnamed value to the formatted output.
340     *
341     * <p>It is strongly encouraged to use {@link #add(String, float)} instead and give value a
342     * readable name.
343     *
344     * @since 11.0 (source-compatible since 2.0)
345     */
346    @CanIgnoreReturnValue
347    public ToStringHelper addValue(float value) {
348      return addHolder(String.valueOf(value));
349    }
350
351    /**
352     * Adds an unnamed value to the formatted output.
353     *
354     * <p>It is strongly encouraged to use {@link #add(String, int)} instead and give value a
355     * readable name.
356     *
357     * @since 11.0 (source-compatible since 2.0)
358     */
359    @CanIgnoreReturnValue
360    public ToStringHelper addValue(int value) {
361      return addHolder(String.valueOf(value));
362    }
363
364    /**
365     * Adds an unnamed value to the formatted output.
366     *
367     * <p>It is strongly encouraged to use {@link #add(String, long)} instead and give value a
368     * readable name.
369     *
370     * @since 11.0 (source-compatible since 2.0)
371     */
372    @CanIgnoreReturnValue
373    public ToStringHelper addValue(long value) {
374      return addHolder(String.valueOf(value));
375    }
376
377    /**
378     * Returns a string in the format specified by {@link Objects#toStringHelper(Object)}.
379     *
380     * <p>After calling this method, you can keep adding more properties to later call toString()
381     * again and get a more complete representation of the same object; but properties cannot be
382     * removed, so this only allows limited reuse of the helper instance. The helper allows
383     * duplication of properties (multiple name/value pairs with the same name can be added).
384     */
385    @Override
386    public String toString() {
387      // create a copy to keep it consistent in case value changes
388      boolean omitNullValuesSnapshot = omitNullValues;
389      String nextSeparator = "";
390      StringBuilder builder = new StringBuilder(32).append(className).append('{');
391      for (ValueHolder valueHolder = holderHead.next;
392          valueHolder != null;
393          valueHolder = valueHolder.next) {
394        if (!omitNullValuesSnapshot || valueHolder.value != null) {
395          builder.append(nextSeparator);
396          nextSeparator = ", ";
397
398          if (valueHolder.name != null) {
399            builder.append(valueHolder.name).append('=');
400          }
401          builder.append(valueHolder.value);
402        }
403      }
404      return builder.append('}').toString();
405    }
406
407    private ValueHolder addHolder() {
408      ValueHolder valueHolder = new ValueHolder();
409      holderTail = holderTail.next = valueHolder;
410      return valueHolder;
411    }
412
413    private ToStringHelper addHolder(@Nullable Object value) {
414      ValueHolder valueHolder = addHolder();
415      valueHolder.value = value;
416      return this;
417    }
418
419    private ToStringHelper addHolder(String name, @Nullable Object value) {
420      ValueHolder valueHolder = addHolder();
421      valueHolder.value = value;
422      valueHolder.name = checkNotNull(name);
423      return this;
424    }
425
426    private static final class ValueHolder {
427      String name;
428      Object value;
429      ValueHolder next;
430    }
431  }
432}