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