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 017package com.google.common.base; 018 019import static com.google.common.base.Preconditions.checkNotNull; 020 021import com.google.common.annotations.GwtCompatible; 022 023import java.util.Arrays; 024 025import javax.annotation.Nullable; 026 027/** 028 * Helper functions that can operate on any {@code Object}. 029 * 030 * <p>See the Guava User Guide on <a 031 * href="http://code.google.com/p/guava-libraries/wiki/CommonObjectUtilitiesExplained">writing 032 * {@code Object} methods with {@code Objects}</a>. 033 * 034 * @author Laurence Gonsalves 035 * @since 2.0 (imported from Google Collections Library) 036 */ 037@GwtCompatible 038public final class Objects { 039 private Objects() {} 040 041 /** 042 * Determines whether two possibly-null objects are equal. Returns: 043 * 044 * <ul> 045 * <li>{@code true} if {@code a} and {@code b} are both null. 046 * <li>{@code true} if {@code a} and {@code b} are both non-null and they are 047 * equal according to {@link Object#equals(Object)}. 048 * <li>{@code false} in all other situations. 049 * </ul> 050 * 051 * <p>This assumes that any non-null objects passed to this function conform 052 * to the {@code equals()} contract. 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 060 * calling {@link Arrays#hashCode(Object[])}. 061 * 062 * <p>This is useful for implementing {@link Object#hashCode()}. For example, 063 * in an object that has three properties, {@code x}, {@code y}, and 064 * {@code z}, one could write: 065 * <pre> 066 * public int hashCode() { 067 * return Objects.hashCode(getX(), getY(), getZ()); 068 * }</pre> 069 * 070 * <b>Warning</b>: When a single object is supplied, the returned hash code 071 * does not equal the hash code of that object. 072 */ 073 public static int hashCode(@Nullable Object... objects) { 074 return Arrays.hashCode(objects); 075 } 076 077 /** 078 * Creates an instance of {@link ToStringHelper}. 079 * 080 * <p>This is helpful for implementing {@link Object#toString()}. 081 * Specification by example: <pre> {@code 082 * // Returns "ClassName{}" 083 * Objects.toStringHelper(this) 084 * .toString(); 085 * 086 * // Returns "ClassName{x=1}" 087 * Objects.toStringHelper(this) 088 * .add("x", 1) 089 * .toString(); 090 * 091 * // Returns "MyObject{x=1}" 092 * Objects.toStringHelper("MyObject") 093 * .add("x", 1) 094 * .toString(); 095 * 096 * // Returns "ClassName{x=1, y=foo}" 097 * Objects.toStringHelper(this) 098 * .add("x", 1) 099 * .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 public String toString() { 383 // create a copy to keep it consistent in case value changes 384 boolean omitNullValuesSnapshot = omitNullValues; 385 String nextSeparator = ""; 386 StringBuilder builder = new StringBuilder(32).append(className) 387 .append('{'); 388 for (ValueHolder valueHolder = holderHead.next; valueHolder != null; 389 valueHolder = valueHolder.next) { 390 if (!omitNullValuesSnapshot || valueHolder.value != null) { 391 builder.append(nextSeparator); 392 nextSeparator = ", "; 393 394 if (valueHolder.name != null) { 395 builder.append(valueHolder.name).append('='); 396 } 397 builder.append(valueHolder.value); 398 } 399 } 400 return builder.append('}').toString(); 401 } 402 403 private ValueHolder addHolder() { 404 ValueHolder valueHolder = new ValueHolder(); 405 holderTail = holderTail.next = valueHolder; 406 return valueHolder; 407 } 408 409 private ToStringHelper addHolder(@Nullable Object value) { 410 ValueHolder valueHolder = addHolder(); 411 valueHolder.value = value; 412 return this; 413 } 414 415 private ToStringHelper addHolder(String name, @Nullable Object value) { 416 ValueHolder valueHolder = addHolder(); 417 valueHolder.value = value; 418 valueHolder.name = checkNotNull(name); 419 return this; 420 } 421 422 private static final class ValueHolder { 423 String name; 424 Object value; 425 ValueHolder next; 426 } 427 } 428}