001/* 002 * Copyright (C) 2014 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 005 * in compliance with the License. You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software distributed under the License 010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 011 * or implied. See the License for the specific language governing permissions and limitations under 012 * the License. 013 */ 014 015package com.google.common.base; 016 017import static com.google.common.base.Preconditions.checkNotNull; 018 019import com.google.common.annotations.GwtCompatible; 020import com.google.errorprone.annotations.CanIgnoreReturnValue; 021import java.lang.reflect.Array; 022import java.util.Arrays; 023import java.util.Collection; 024import java.util.Map; 025import java.util.OptionalDouble; 026import java.util.OptionalInt; 027import java.util.OptionalLong; 028import javax.annotation.CheckForNull; 029 030/** 031 * Helper functions that operate on any {@code Object}, and are not already provided in {@link 032 * java.util.Objects}. 033 * 034 * <p>See the Guava User Guide on <a 035 * href="https://github.com/google/guava/wiki/CommonObjectUtilitiesExplained">writing {@code Object} 036 * methods with {@code MoreObjects}</a>. 037 * 038 * @author Laurence Gonsalves 039 * @since 18.0 (since 2.0 as {@code Objects}) 040 */ 041@GwtCompatible 042@ElementTypesAreNonnullByDefault 043public final class MoreObjects { 044 /** 045 * Returns the first of two given parameters that is not {@code null}, if either is, or otherwise 046 * throws a {@link NullPointerException}. 047 * 048 * <p>To find the first non-null element in an iterable, use {@code Iterables.find(iterable, 049 * Predicates.notNull())}. For varargs, use {@code Iterables.find(Arrays.asList(a, b, c, ...), 050 * Predicates.notNull())}, static importing as necessary. 051 * 052 * <p><b>Note:</b> if {@code first} is represented as an {@link Optional}, this can be 053 * accomplished with {@link Optional#or(Object) first.or(second)}. That approach also allows for 054 * lazy evaluation of the fallback instance, using {@link Optional#or(Supplier) 055 * first.or(supplier)}. 056 * 057 * <p><b>Java 9 users:</b> use {@code java.util.Objects.requireNonNullElse(first, second)} 058 * instead. 059 * 060 * @return {@code first} if it is non-null; otherwise {@code second} if it is non-null 061 * @throws NullPointerException if both {@code first} and {@code second} are null 062 * @since 18.0 (since 3.0 as {@code Objects.firstNonNull()}). 063 */ 064 public static <T> T firstNonNull(@CheckForNull T first, @CheckForNull T second) { 065 if (first != null) { 066 return first; 067 } 068 if (second != null) { 069 return second; 070 } 071 throw new NullPointerException("Both parameters are null"); 072 } 073 074 /** 075 * Creates an instance of {@link ToStringHelper}. 076 * 077 * <p>This is helpful for implementing {@link Object#toString()}. Specification by example: 078 * 079 * <pre>{@code 080 * // Returns "ClassName{}" 081 * MoreObjects.toStringHelper(this) 082 * .toString(); 083 * 084 * // Returns "ClassName{x=1}" 085 * MoreObjects.toStringHelper(this) 086 * .add("x", 1) 087 * .toString(); 088 * 089 * // Returns "MyObject{x=1}" 090 * MoreObjects.toStringHelper("MyObject") 091 * .add("x", 1) 092 * .toString(); 093 * 094 * // Returns "ClassName{x=1, y=foo}" 095 * MoreObjects.toStringHelper(this) 096 * .add("x", 1) 097 * .add("y", "foo") 098 * .toString(); 099 * 100 * // Returns "ClassName{x=1}" 101 * MoreObjects.toStringHelper(this) 102 * .omitNullValues() 103 * .add("x", 1) 104 * .add("y", null) 105 * .toString(); 106 * }</pre> 107 * 108 * <p>Note that in GWT, class names are often obfuscated. 109 * 110 * @param self the object to generate the string for (typically {@code this}), used only for its 111 * class name 112 * @since 18.0 (since 2.0 as {@code Objects.toStringHelper()}). 113 */ 114 public static ToStringHelper toStringHelper(Object self) { 115 return new ToStringHelper(self.getClass().getSimpleName()); 116 } 117 118 /** 119 * Creates an instance of {@link ToStringHelper} in the same manner as {@link 120 * #toStringHelper(Object)}, but using the simple name of {@code clazz} instead of using an 121 * instance's {@link Object#getClass()}. 122 * 123 * <p>Note that in GWT, class names are often obfuscated. 124 * 125 * @param clazz the {@link Class} of the instance 126 * @since 18.0 (since 7.0 as {@code Objects.toStringHelper()}). 127 */ 128 public static ToStringHelper toStringHelper(Class<?> clazz) { 129 return new ToStringHelper(clazz.getSimpleName()); 130 } 131 132 /** 133 * Creates an instance of {@link ToStringHelper} in the same manner as {@link 134 * #toStringHelper(Object)}, but using {@code className} instead of using an instance's {@link 135 * Object#getClass()}. 136 * 137 * @param className the name of the instance type 138 * @since 18.0 (since 7.0 as {@code Objects.toStringHelper()}). 139 */ 140 public static ToStringHelper toStringHelper(String className) { 141 return new ToStringHelper(className); 142 } 143 144 /** 145 * Support class for {@link MoreObjects#toStringHelper}. 146 * 147 * @author Jason Lee 148 * @since 18.0 (since 2.0 as {@code Objects.ToStringHelper}). 149 */ 150 public static final class ToStringHelper { 151 private final String className; 152 private final ValueHolder holderHead = new ValueHolder(); 153 private ValueHolder holderTail = holderHead; 154 private boolean omitNullValues = false; 155 private boolean omitEmptyValues = false; 156 157 /** Use {@link MoreObjects#toStringHelper(Object)} to create an instance. */ 158 private ToStringHelper(String className) { 159 this.className = checkNotNull(className); 160 } 161 162 /** 163 * Configures the {@link ToStringHelper} so {@link #toString()} will ignore properties with null 164 * value. The order of calling this method, relative to the {@code add()}/{@code addValue()} 165 * methods, is not significant. 166 * 167 * @since 18.0 (since 12.0 as {@code Objects.ToStringHelper.omitNullValues()}). 168 */ 169 @CanIgnoreReturnValue 170 public ToStringHelper omitNullValues() { 171 omitNullValues = true; 172 return this; 173 } 174 175 /** 176 * Configures the {@link ToStringHelper} so {@link #toString()} will ignore properties with 177 * empty values. The order of calling this method, relative to the {@code add()}/{@code 178 * addValue()} methods, is not significant. 179 * 180 * <p><b>Note:</b> in general, code should assume that the string form returned by {@code 181 * ToStringHelper} for a given object may change. In particular, the list of types which are 182 * checked for emptiness is subject to change. We currently check {@code CharSequence}s, {@code 183 * Collection}s, {@code Map}s, optionals (including Guava's), and arrays. 184 * 185 * @since 33.4.0 186 */ 187 @CanIgnoreReturnValue 188 public ToStringHelper omitEmptyValues() { 189 omitEmptyValues = true; 190 return this; 191 } 192 193 /** 194 * Adds a name/value pair to the formatted output in {@code name=value} format. If {@code value} 195 * is {@code null}, the string {@code "null"} is used, unless {@link #omitNullValues()} is 196 * called, in which case this name/value pair will not be added. 197 */ 198 @CanIgnoreReturnValue 199 public ToStringHelper add(String name, @CheckForNull Object value) { 200 return addHolder(name, value); 201 } 202 203 /** 204 * Adds a name/value pair to the formatted output in {@code name=value} format. 205 * 206 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}). 207 */ 208 @CanIgnoreReturnValue 209 public ToStringHelper add(String name, boolean value) { 210 return addUnconditionalHolder(name, String.valueOf(value)); 211 } 212 213 /** 214 * Adds a name/value pair to the formatted output in {@code name=value} format. 215 * 216 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}). 217 */ 218 @CanIgnoreReturnValue 219 public ToStringHelper add(String name, char value) { 220 return addUnconditionalHolder(name, String.valueOf(value)); 221 } 222 223 /** 224 * Adds a name/value pair to the formatted output in {@code name=value} format. 225 * 226 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}). 227 */ 228 @CanIgnoreReturnValue 229 public ToStringHelper add(String name, double value) { 230 return addUnconditionalHolder(name, String.valueOf(value)); 231 } 232 233 /** 234 * Adds a name/value pair to the formatted output in {@code name=value} format. 235 * 236 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}). 237 */ 238 @CanIgnoreReturnValue 239 public ToStringHelper add(String name, float value) { 240 return addUnconditionalHolder(name, String.valueOf(value)); 241 } 242 243 /** 244 * Adds a name/value pair to the formatted output in {@code name=value} format. 245 * 246 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}). 247 */ 248 @CanIgnoreReturnValue 249 public ToStringHelper add(String name, int value) { 250 return addUnconditionalHolder(name, String.valueOf(value)); 251 } 252 253 /** 254 * Adds a name/value pair to the formatted output in {@code name=value} format. 255 * 256 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}). 257 */ 258 @CanIgnoreReturnValue 259 public ToStringHelper add(String name, long value) { 260 return addUnconditionalHolder(name, String.valueOf(value)); 261 } 262 263 /** 264 * Adds an unnamed value to the formatted output. 265 * 266 * <p>It is strongly encouraged to use {@link #add(String, Object)} instead and give value a 267 * readable name. 268 */ 269 @CanIgnoreReturnValue 270 public ToStringHelper addValue(@CheckForNull Object value) { 271 return addHolder(value); 272 } 273 274 /** 275 * Adds an unnamed value to the formatted output. 276 * 277 * <p>It is strongly encouraged to use {@link #add(String, boolean)} instead and give value a 278 * readable name. 279 * 280 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}). 281 */ 282 @CanIgnoreReturnValue 283 public ToStringHelper addValue(boolean value) { 284 return addUnconditionalHolder(String.valueOf(value)); 285 } 286 287 /** 288 * Adds an unnamed value to the formatted output. 289 * 290 * <p>It is strongly encouraged to use {@link #add(String, char)} instead and give value a 291 * readable name. 292 * 293 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}). 294 */ 295 @CanIgnoreReturnValue 296 public ToStringHelper addValue(char value) { 297 return addUnconditionalHolder(String.valueOf(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, double)} instead and give value a 304 * readable name. 305 * 306 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}). 307 */ 308 @CanIgnoreReturnValue 309 public ToStringHelper addValue(double value) { 310 return addUnconditionalHolder(String.valueOf(value)); 311 } 312 313 /** 314 * Adds an unnamed value to the formatted output. 315 * 316 * <p>It is strongly encouraged to use {@link #add(String, float)} instead and give value a 317 * readable name. 318 * 319 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}). 320 */ 321 @CanIgnoreReturnValue 322 public ToStringHelper addValue(float value) { 323 return addUnconditionalHolder(String.valueOf(value)); 324 } 325 326 /** 327 * Adds an unnamed value to the formatted output. 328 * 329 * <p>It is strongly encouraged to use {@link #add(String, int)} instead and give value a 330 * readable name. 331 * 332 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}). 333 */ 334 @CanIgnoreReturnValue 335 public ToStringHelper addValue(int value) { 336 return addUnconditionalHolder(String.valueOf(value)); 337 } 338 339 /** 340 * Adds an unnamed value to the formatted output. 341 * 342 * <p>It is strongly encouraged to use {@link #add(String, long)} instead and give value a 343 * readable name. 344 * 345 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}). 346 */ 347 @CanIgnoreReturnValue 348 public ToStringHelper addValue(long value) { 349 return addUnconditionalHolder(String.valueOf(value)); 350 } 351 352 private static boolean isEmpty(Object value) { 353 // Put types estimated to be the most frequent first. 354 if (value instanceof CharSequence) { 355 return ((CharSequence) value).length() == 0; 356 } else if (value instanceof Collection) { 357 return ((Collection<?>) value).isEmpty(); 358 } else if (value instanceof Map) { 359 return ((Map<?, ?>) value).isEmpty(); 360 } else if (value instanceof java.util.Optional) { 361 return !((java.util.Optional<?>) value).isPresent(); 362 } else if (value instanceof OptionalInt) { 363 return !((OptionalInt) value).isPresent(); 364 } else if (value instanceof OptionalLong) { 365 return !((OptionalLong) value).isPresent(); 366 } else if (value instanceof OptionalDouble) { 367 return !((OptionalDouble) value).isPresent(); 368 } else if (value instanceof Optional) { 369 return !((Optional) value).isPresent(); 370 } else if (value.getClass().isArray()) { 371 return Array.getLength(value) == 0; 372 } 373 return false; 374 } 375 376 /** 377 * Returns a string in the format specified by {@link MoreObjects#toStringHelper(Object)}. 378 * 379 * <p>After calling this method, you can keep adding more properties to later call toString() 380 * again and get a more complete representation of the same object; but properties cannot be 381 * removed, so this only allows limited reuse of the helper instance. The helper allows 382 * duplication of properties (multiple name/value pairs with the same name can be added). 383 */ 384 @Override 385 public String toString() { 386 // create a copy to keep it consistent in case value changes 387 boolean omitNullValuesSnapshot = omitNullValues; 388 boolean omitEmptyValuesSnapshot = omitEmptyValues; 389 String nextSeparator = ""; 390 StringBuilder builder = new StringBuilder(32).append(className).append('{'); 391 for (ValueHolder valueHolder = holderHead.next; 392 valueHolder != null; 393 valueHolder = valueHolder.next) { 394 Object value = valueHolder.value; 395 if (valueHolder instanceof UnconditionalValueHolder 396 || (value == null 397 ? !omitNullValuesSnapshot 398 : (!omitEmptyValuesSnapshot || !isEmpty(value)))) { 399 builder.append(nextSeparator); 400 nextSeparator = ", "; 401 402 if (valueHolder.name != null) { 403 builder.append(valueHolder.name).append('='); 404 } 405 if (value != null && value.getClass().isArray()) { 406 Object[] objectArray = {value}; 407 String arrayString = Arrays.deepToString(objectArray); 408 builder.append(arrayString, 1, arrayString.length() - 1); 409 } else { 410 builder.append(value); 411 } 412 } 413 } 414 return builder.append('}').toString(); 415 } 416 417 private ValueHolder addHolder() { 418 ValueHolder valueHolder = new ValueHolder(); 419 holderTail = holderTail.next = valueHolder; 420 return valueHolder; 421 } 422 423 @CanIgnoreReturnValue 424 private ToStringHelper addHolder(@CheckForNull Object value) { 425 ValueHolder valueHolder = addHolder(); 426 valueHolder.value = value; 427 return this; 428 } 429 430 @CanIgnoreReturnValue 431 private ToStringHelper addHolder(String name, @CheckForNull Object value) { 432 ValueHolder valueHolder = addHolder(); 433 valueHolder.value = value; 434 valueHolder.name = checkNotNull(name); 435 return this; 436 } 437 438 private UnconditionalValueHolder addUnconditionalHolder() { 439 UnconditionalValueHolder valueHolder = new UnconditionalValueHolder(); 440 holderTail = holderTail.next = valueHolder; 441 return valueHolder; 442 } 443 444 @CanIgnoreReturnValue 445 private ToStringHelper addUnconditionalHolder(Object value) { 446 UnconditionalValueHolder valueHolder = addUnconditionalHolder(); 447 valueHolder.value = value; 448 return this; 449 } 450 451 @CanIgnoreReturnValue 452 private ToStringHelper addUnconditionalHolder(String name, Object value) { 453 UnconditionalValueHolder valueHolder = addUnconditionalHolder(); 454 valueHolder.value = value; 455 valueHolder.name = checkNotNull(name); 456 return this; 457 } 458 459 // Holder object for values that might be null and/or empty. 460 static class ValueHolder { 461 @CheckForNull String name; 462 @CheckForNull Object value; 463 @CheckForNull ValueHolder next; 464 } 465 466 /** 467 * Holder object for values that cannot be null or empty (will be printed unconditionally). This 468 * helps to shortcut most calls to isEmpty(), which is important because the check for emptiness 469 * is relatively expensive. Use a subtype so this also doesn't need any extra storage. 470 */ 471 private static final class UnconditionalValueHolder extends ValueHolder {} 472 } 473 474 private MoreObjects() {} 475}