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