001 /*
002 * Copyright (C) 2007 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package com.google.common.base;
018
019 import static com.google.common.base.Preconditions.checkNotNull;
020
021 import com.google.common.annotations.GwtCompatible;
022
023 import java.util.Arrays;
024
025 import javax.annotation.Nullable;
026
027 /**
028 * Helper functions that can operate on any {@code Object}.
029 *
030 * @author Laurence Gonsalves
031 * @since 2.0 (imported from Google Collections Library)
032 */
033 @GwtCompatible
034 public final class Objects {
035 private Objects() {}
036
037 /**
038 * Determines whether two possibly-null objects are equal. Returns:
039 *
040 * <ul>
041 * <li>{@code true} if {@code a} and {@code b} are both null.
042 * <li>{@code true} if {@code a} and {@code b} are both non-null and they are
043 * equal according to {@link Object#equals(Object)}.
044 * <li>{@code false} in all other situations.
045 * </ul>
046 *
047 * <p>This assumes that any non-null objects passed to this function conform
048 * to the {@code equals()} contract.
049 */
050 public static boolean equal(@Nullable Object a, @Nullable Object b) {
051 return a == b || (a != null && a.equals(b));
052 }
053
054 /**
055 * Generates a hash code for multiple values. The hash code is generated by
056 * calling {@link Arrays#hashCode(Object[])}.
057 *
058 * <p>This is useful for implementing {@link Object#hashCode()}. For example,
059 * in an object that has three properties, {@code x}, {@code y}, and
060 * {@code z}, one could write:
061 * <pre>
062 * public int hashCode() {
063 * return Objects.hashCode(getX(), getY(), getZ());
064 * }</pre>
065 *
066 * <b>Warning</b>: When a single object is supplied, the returned hash code
067 * does not equal the hash code of that object.
068 */
069 public static int hashCode(@Nullable Object... objects) {
070 return Arrays.hashCode(objects);
071 }
072
073 /**
074 * Creates an instance of {@link ToStringHelper}.
075 *
076 * <p>This is helpful for implementing {@link Object#toString()}.
077 * Specification by example: <pre> {@code
078 * // Returns "ClassName{}"
079 * Objects.toStringHelper(this)
080 * .toString();
081 *
082 * // Returns "ClassName{x=1}"
083 * Objects.toStringHelper(this)
084 * .add("x", 1)
085 * .toString();
086 *
087 * // Returns "MyObject{x=1}"
088 * Objects.toStringHelper("MyObject")
089 * .add("x", 1)
090 * .toString();
091 *
092 * // Returns "ClassName{x=1, y=foo}"
093 * Objects.toStringHelper(this)
094 * .add("x", 1)
095 * .add("y", "foo")
096 * .toString();
097 * }}</pre>
098 *
099 * <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 checkNotNull(name);
202 maybeAppendSeparator().append(name).append('=').append(value);
203 return this;
204 }
205
206 /**
207 * Adds a value to the formatted output in {@code value} format.
208 *
209 * <p>It is strongly encouraged to use {@link #add(String, Object)} instead
210 * and give value a readable name.
211 */
212 public ToStringHelper addValue(@Nullable Object value) {
213 maybeAppendSeparator().append(value);
214 return this;
215 }
216
217 /**
218 * Returns a string in the format specified by {@link
219 * Objects#toStringHelper(Object)}.
220 */
221 @Override public String toString() {
222 try {
223 return builder.append('}').toString();
224 } finally {
225 // Slice off the closing brace in case there are additional calls to
226 // #add or #addValue.
227 builder.setLength(builder.length() - 1);
228 }
229 }
230
231 private StringBuilder maybeAppendSeparator() {
232 if (needsSeparator) {
233 return builder.append(", ");
234 } else {
235 needsSeparator = true;
236 return builder;
237 }
238 }
239 }
240 }