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 * Adds a name/value pair to the formatted output in {@code name=value} format. If {@code value} 177 * is {@code null}, the string {@code "null"} is used, unless {@link #omitNullValues()} is 178 * called, in which case this name/value pair will not be added. 179 */ 180 @CanIgnoreReturnValue 181 public ToStringHelper add(String name, @CheckForNull Object value) { 182 return addHolder(name, value); 183 } 184 185 /** 186 * Adds a name/value pair to the formatted output in {@code name=value} format. 187 * 188 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}). 189 */ 190 @CanIgnoreReturnValue 191 public ToStringHelper add(String name, boolean value) { 192 return addUnconditionalHolder(name, String.valueOf(value)); 193 } 194 195 /** 196 * Adds a name/value pair to the formatted output in {@code name=value} format. 197 * 198 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}). 199 */ 200 @CanIgnoreReturnValue 201 public ToStringHelper add(String name, char value) { 202 return addUnconditionalHolder(name, String.valueOf(value)); 203 } 204 205 /** 206 * Adds a name/value pair to the formatted output in {@code name=value} format. 207 * 208 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}). 209 */ 210 @CanIgnoreReturnValue 211 public ToStringHelper add(String name, double value) { 212 return addUnconditionalHolder(name, String.valueOf(value)); 213 } 214 215 /** 216 * Adds a name/value pair to the formatted output in {@code name=value} format. 217 * 218 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}). 219 */ 220 @CanIgnoreReturnValue 221 public ToStringHelper add(String name, float value) { 222 return addUnconditionalHolder(name, String.valueOf(value)); 223 } 224 225 /** 226 * Adds a name/value pair to the formatted output in {@code name=value} format. 227 * 228 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}). 229 */ 230 @CanIgnoreReturnValue 231 public ToStringHelper add(String name, int value) { 232 return addUnconditionalHolder(name, String.valueOf(value)); 233 } 234 235 /** 236 * Adds a name/value pair to the formatted output in {@code name=value} format. 237 * 238 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.add()}). 239 */ 240 @CanIgnoreReturnValue 241 public ToStringHelper add(String name, long value) { 242 return addUnconditionalHolder(name, String.valueOf(value)); 243 } 244 245 /** 246 * Adds an unnamed value to the formatted output. 247 * 248 * <p>It is strongly encouraged to use {@link #add(String, Object)} instead and give value a 249 * readable name. 250 */ 251 @CanIgnoreReturnValue 252 public ToStringHelper addValue(@CheckForNull Object value) { 253 return addHolder(value); 254 } 255 256 /** 257 * Adds an unnamed value to the formatted output. 258 * 259 * <p>It is strongly encouraged to use {@link #add(String, boolean)} instead and give value a 260 * readable name. 261 * 262 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}). 263 */ 264 @CanIgnoreReturnValue 265 public ToStringHelper addValue(boolean value) { 266 return addUnconditionalHolder(String.valueOf(value)); 267 } 268 269 /** 270 * Adds an unnamed value to the formatted output. 271 * 272 * <p>It is strongly encouraged to use {@link #add(String, char)} instead and give value a 273 * readable name. 274 * 275 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}). 276 */ 277 @CanIgnoreReturnValue 278 public ToStringHelper addValue(char value) { 279 return addUnconditionalHolder(String.valueOf(value)); 280 } 281 282 /** 283 * Adds an unnamed value to the formatted output. 284 * 285 * <p>It is strongly encouraged to use {@link #add(String, double)} instead and give value a 286 * readable name. 287 * 288 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}). 289 */ 290 @CanIgnoreReturnValue 291 public ToStringHelper addValue(double value) { 292 return addUnconditionalHolder(String.valueOf(value)); 293 } 294 295 /** 296 * Adds an unnamed value to the formatted output. 297 * 298 * <p>It is strongly encouraged to use {@link #add(String, float)} instead and give value a 299 * readable name. 300 * 301 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}). 302 */ 303 @CanIgnoreReturnValue 304 public ToStringHelper addValue(float value) { 305 return addUnconditionalHolder(String.valueOf(value)); 306 } 307 308 /** 309 * Adds an unnamed value to the formatted output. 310 * 311 * <p>It is strongly encouraged to use {@link #add(String, int)} instead and give value a 312 * readable name. 313 * 314 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}). 315 */ 316 @CanIgnoreReturnValue 317 public ToStringHelper addValue(int value) { 318 return addUnconditionalHolder(String.valueOf(value)); 319 } 320 321 /** 322 * Adds an unnamed value to the formatted output. 323 * 324 * <p>It is strongly encouraged to use {@link #add(String, long)} instead and give value a 325 * readable name. 326 * 327 * @since 18.0 (since 11.0 as {@code Objects.ToStringHelper.addValue()}). 328 */ 329 @CanIgnoreReturnValue 330 public ToStringHelper addValue(long value) { 331 return addUnconditionalHolder(String.valueOf(value)); 332 } 333 334 private static boolean isEmpty(Object value) { 335 // Put types estimated to be the most frequent first. 336 if (value instanceof CharSequence) { 337 return ((CharSequence) value).length() == 0; 338 } else if (value instanceof Collection) { 339 return ((Collection<?>) value).isEmpty(); 340 } else if (value instanceof Map) { 341 return ((Map<?, ?>) value).isEmpty(); 342 } else if (value instanceof java.util.Optional) { 343 return !((java.util.Optional<?>) value).isPresent(); 344 } else if (value instanceof OptionalInt) { 345 return !((OptionalInt) value).isPresent(); 346 } else if (value instanceof OptionalLong) { 347 return !((OptionalLong) value).isPresent(); 348 } else if (value instanceof OptionalDouble) { 349 return !((OptionalDouble) value).isPresent(); 350 } else if (value instanceof Optional) { 351 return !((Optional) value).isPresent(); 352 } else if (value.getClass().isArray()) { 353 return Array.getLength(value) == 0; 354 } 355 return false; 356 } 357 358 /** 359 * Returns a string in the format specified by {@link MoreObjects#toStringHelper(Object)}. 360 * 361 * <p>After calling this method, you can keep adding more properties to later call toString() 362 * again and get a more complete representation of the same object; but properties cannot be 363 * removed, so this only allows limited reuse of the helper instance. The helper allows 364 * duplication of properties (multiple name/value pairs with the same name can be added). 365 */ 366 @Override 367 public String toString() { 368 // create a copy to keep it consistent in case value changes 369 boolean omitNullValuesSnapshot = omitNullValues; 370 boolean omitEmptyValuesSnapshot = omitEmptyValues; 371 String nextSeparator = ""; 372 StringBuilder builder = new StringBuilder(32).append(className).append('{'); 373 for (ValueHolder valueHolder = holderHead.next; 374 valueHolder != null; 375 valueHolder = valueHolder.next) { 376 Object value = valueHolder.value; 377 if (valueHolder instanceof UnconditionalValueHolder 378 || (value == null 379 ? !omitNullValuesSnapshot 380 : (!omitEmptyValuesSnapshot || !isEmpty(value)))) { 381 builder.append(nextSeparator); 382 nextSeparator = ", "; 383 384 if (valueHolder.name != null) { 385 builder.append(valueHolder.name).append('='); 386 } 387 if (value != null && value.getClass().isArray()) { 388 Object[] objectArray = {value}; 389 String arrayString = Arrays.deepToString(objectArray); 390 builder.append(arrayString, 1, arrayString.length() - 1); 391 } else { 392 builder.append(value); 393 } 394 } 395 } 396 return builder.append('}').toString(); 397 } 398 399 private ValueHolder addHolder() { 400 ValueHolder valueHolder = new ValueHolder(); 401 holderTail = holderTail.next = valueHolder; 402 return valueHolder; 403 } 404 405 @CanIgnoreReturnValue 406 private ToStringHelper addHolder(@CheckForNull Object value) { 407 ValueHolder valueHolder = addHolder(); 408 valueHolder.value = value; 409 return this; 410 } 411 412 @CanIgnoreReturnValue 413 private ToStringHelper addHolder(String name, @CheckForNull Object value) { 414 ValueHolder valueHolder = addHolder(); 415 valueHolder.value = value; 416 valueHolder.name = checkNotNull(name); 417 return this; 418 } 419 420 private UnconditionalValueHolder addUnconditionalHolder() { 421 UnconditionalValueHolder valueHolder = new UnconditionalValueHolder(); 422 holderTail = holderTail.next = valueHolder; 423 return valueHolder; 424 } 425 426 @CanIgnoreReturnValue 427 private ToStringHelper addUnconditionalHolder(Object value) { 428 UnconditionalValueHolder valueHolder = addUnconditionalHolder(); 429 valueHolder.value = value; 430 return this; 431 } 432 433 @CanIgnoreReturnValue 434 private ToStringHelper addUnconditionalHolder(String name, Object value) { 435 UnconditionalValueHolder valueHolder = addUnconditionalHolder(); 436 valueHolder.value = value; 437 valueHolder.name = checkNotNull(name); 438 return this; 439 } 440 441 // Holder object for values that might be null and/or empty. 442 static class ValueHolder { 443 @CheckForNull String name; 444 @CheckForNull Object value; 445 @CheckForNull ValueHolder next; 446 } 447 448 /** 449 * Holder object for values that cannot be null or empty (will be printed unconditionally). This 450 * helps to shortcut most calls to isEmpty(), which is important because the check for emptiness 451 * is relatively expensive. Use a subtype so this also doesn't need any extra storage. 452 */ 453 private static final class UnconditionalValueHolder extends ValueHolder {} 454 } 455 456 private MoreObjects() {} 457}