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