• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.google.common.base;
18 
19 import static com.google.common.base.Preconditions.checkNotNull;
20 
21 import com.google.common.annotations.GwtCompatible;
22 
23 import java.util.Arrays;
24 
25 import 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
34 public final class Objects {
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    */
equal(@ullable Object a, @Nullable Object b)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    */
hashCode(@ullable Object... objects)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    */
toStringHelper(Object self)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    */
toStringHelper(Class<?> clazz)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    */
toStringHelper(String className)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    */
simpleName(Class<?> clazz)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    */
firstNonNull(@ullable T first, @Nullable T second)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      */
ToStringHelper(String className)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      */
add(String name, @Nullable Object value)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      */
add(String name, boolean value)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      */
add(String name, char value)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      */
add(String name, double value)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      */
add(String name, float value)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      */
add(String name, int value)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      */
add(String name, long value)266     public ToStringHelper add(String name, long value) {
267       checkNameAndAppend(name).append(value);
268       return this;
269     }
270 
checkNameAndAppend(String name)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      */
addValue(@ullable Object value)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      */
addValue(boolean value)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      */
addValue(char value)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      */
addValue(double value)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      */
addValue(float value)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      */
addValue(int value)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      */
addValue(long value)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      */
toString()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 
maybeAppendSeparator()379     private StringBuilder maybeAppendSeparator() {
380       if (needsSeparator) {
381         return builder.append(", ");
382       } else {
383         needsSeparator = true;
384         return builder;
385       }
386     }
387   }
388 }
389