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 017 package com.google.common.base; 018 019 import static com.google.common.base.Preconditions.checkNotNull; 020 021 import com.google.common.annotations.Beta; 022 import com.google.common.annotations.GwtCompatible; 023 024 import java.util.Arrays; 025 import java.util.LinkedList; 026 import java.util.List; 027 028 import javax.annotation.Nullable; 029 030 /** 031 * Helper functions that can operate on any {@code Object}. 032 * 033 * <p>See the Guava User Guide on <a 034 * href="http://code.google.com/p/guava-libraries/wiki/CommonObjectUtilitiesExplained">writing 035 * {@code Object} methods with {@code Objects}</a>. 036 * 037 * @author Laurence Gonsalves 038 * @since 2.0 (imported from Google Collections Library) 039 */ 040 @GwtCompatible 041 public final class Objects { 042 private Objects() {} 043 044 /** 045 * Determines whether two possibly-null objects are equal. Returns: 046 * 047 * <ul> 048 * <li>{@code true} if {@code a} and {@code b} are both null. 049 * <li>{@code true} if {@code a} and {@code b} are both non-null and they are 050 * equal according to {@link Object#equals(Object)}. 051 * <li>{@code false} in all other situations. 052 * </ul> 053 * 054 * <p>This assumes that any non-null objects passed to this function conform 055 * to the {@code equals()} contract. 056 */ 057 public static boolean equal(@Nullable Object a, @Nullable Object b) { 058 return a == b || (a != null && a.equals(b)); 059 } 060 061 /** 062 * Generates a hash code for multiple values. The hash code is generated by 063 * calling {@link Arrays#hashCode(Object[])}. 064 * 065 * <p>This is useful for implementing {@link Object#hashCode()}. For example, 066 * in an object that has three properties, {@code x}, {@code y}, and 067 * {@code z}, one could write: 068 * <pre> 069 * public int hashCode() { 070 * return Objects.hashCode(getX(), getY(), getZ()); 071 * }</pre> 072 * 073 * <b>Warning</b>: When a single object is supplied, the returned hash code 074 * does not equal the hash code of that object. 075 */ 076 public static int hashCode(@Nullable Object... objects) { 077 return Arrays.hashCode(objects); 078 } 079 080 /** 081 * Creates an instance of {@link ToStringHelper}. 082 * 083 * <p>This is helpful for implementing {@link Object#toString()}. 084 * Specification by example: <pre> {@code 085 * // Returns "ClassName{}" 086 * Objects.toStringHelper(this) 087 * .toString(); 088 * 089 * // Returns "ClassName{x=1}" 090 * Objects.toStringHelper(this) 091 * .add("x", 1) 092 * .toString(); 093 * 094 * // Returns "MyObject{x=1}" 095 * Objects.toStringHelper("MyObject") 096 * .add("x", 1) 097 * .toString(); 098 * 099 * // Returns "ClassName{x=1, y=foo}" 100 * Objects.toStringHelper(this) 101 * .add("x", 1) 102 * .add("y", "foo") 103 * .toString(); 104 * }} 105 * 106 * // Returns "ClassName{x=1}" 107 * Objects.toStringHelper(this) 108 * .omitNullValues() 109 * .add("x", 1) 110 * .add("y", null) 111 * .toString(); 112 * }}</pre> 113 * 114 * <p>Note that in GWT, class names are often obfuscated. 115 * 116 * @param self the object to generate the string for (typically {@code this}), 117 * used only for its class name 118 * @since 2.0 119 */ 120 public static ToStringHelper toStringHelper(Object self) { 121 return new ToStringHelper(simpleName(self.getClass())); 122 } 123 124 /** 125 * Creates an instance of {@link ToStringHelper} in the same manner as 126 * {@link Objects#toStringHelper(Object)}, but using the name of {@code clazz} 127 * instead of using an instance's {@link Object#getClass()}. 128 * 129 * <p>Note that in GWT, class names are often obfuscated. 130 * 131 * @param clazz the {@link Class} of the instance 132 * @since 7.0 (source-compatible since 2.0) 133 */ 134 public static ToStringHelper toStringHelper(Class<?> clazz) { 135 return new ToStringHelper(simpleName(clazz)); 136 } 137 138 /** 139 * Creates an instance of {@link ToStringHelper} in the same manner as 140 * {@link Objects#toStringHelper(Object)}, but using {@code className} instead 141 * of using an instance's {@link Object#getClass()}. 142 * 143 * @param className the name of the instance type 144 * @since 7.0 (source-compatible since 2.0) 145 */ 146 public static ToStringHelper toStringHelper(String className) { 147 return new ToStringHelper(className); 148 } 149 150 /** 151 * {@link Class#getSimpleName()} is not GWT compatible yet, so we 152 * provide our own implementation. 153 */ 154 private static String simpleName(Class<?> clazz) { 155 String name = clazz.getName(); 156 157 // the nth anonymous class has a class name ending in "Outer$n" 158 // and local inner classes have names ending in "Outer.$1Inner" 159 name = name.replaceAll("\\$[0-9]+", "\\$"); 160 161 // we want the name of the inner class all by its lonesome 162 int start = name.lastIndexOf('$'); 163 164 // if this isn't an inner class, just find the start of the 165 // top level class name. 166 if (start == -1) { 167 start = name.lastIndexOf('.'); 168 } 169 return name.substring(start + 1); 170 } 171 172 /** 173 * Returns the first of two given parameters that is not {@code null}, if 174 * either is, or otherwise throws a {@link NullPointerException}. 175 * 176 * <p><b>Note:</b> if {@code first} is represented as an {@code Optional<T>}, 177 * this can be accomplished with {@code first.or(second)}. That approach also 178 * allows for lazy evaluation of the fallback instance, using 179 * {@code first.or(Supplier)}. 180 * 181 * @return {@code first} if {@code first} is not {@code null}, or 182 * {@code second} if {@code first} is {@code null} and {@code second} is 183 * not {@code null} 184 * @throws NullPointerException if both {@code first} and {@code second} were 185 * {@code null} 186 * @since 3.0 187 */ 188 public static <T> T firstNonNull(@Nullable T first, @Nullable T second) { 189 return first != null ? first : checkNotNull(second); 190 } 191 192 /** 193 * Support class for {@link Objects#toStringHelper}. 194 * 195 * @author Jason Lee 196 * @since 2.0 197 */ 198 public static final class ToStringHelper { 199 private final String className; 200 private final List<ValueHolder> valueHolders = 201 new LinkedList<ValueHolder>(); 202 private boolean omitNullValues = false; 203 204 /** 205 * Use {@link Objects#toStringHelper(Object)} to create an instance. 206 */ 207 private ToStringHelper(String className) { 208 this.className = checkNotNull(className); 209 } 210 211 /** 212 * When called, the formatted output returned by {@link #toString()} will 213 * ignore {@code null} values. 214 * 215 * @since 12.0 216 */ 217 @Beta 218 public ToStringHelper omitNullValues() { 219 omitNullValues = true; 220 return this; 221 } 222 223 /** 224 * Adds a name/value pair to the formatted output in {@code name=value} 225 * format. If {@code value} is {@code null}, the string {@code "null"} 226 * is used, unless {@link #omitNullValues()} is called, in which case this 227 * name/value pair will not be added. 228 */ 229 public ToStringHelper add(String name, @Nullable Object value) { 230 checkNotNull(name); 231 addHolder(value).builder.append(name).append('=').append(value); 232 return this; 233 } 234 235 /** 236 * Adds a name/value pair to the formatted output in {@code name=value} 237 * format. 238 * 239 * @since 11.0 (source-compatible since 2.0) 240 */ 241 public ToStringHelper add(String name, boolean value) { 242 checkNameAndAppend(name).append(value); 243 return this; 244 } 245 246 /** 247 * Adds a name/value pair to the formatted output in {@code name=value} 248 * format. 249 * 250 * @since 11.0 (source-compatible since 2.0) 251 */ 252 public ToStringHelper add(String name, char value) { 253 checkNameAndAppend(name).append(value); 254 return this; 255 } 256 257 /** 258 * Adds a name/value pair to the formatted output in {@code name=value} 259 * format. 260 * 261 * @since 11.0 (source-compatible since 2.0) 262 */ 263 public ToStringHelper add(String name, double value) { 264 checkNameAndAppend(name).append(value); 265 return this; 266 } 267 268 /** 269 * Adds a name/value pair to the formatted output in {@code name=value} 270 * format. 271 * 272 * @since 11.0 (source-compatible since 2.0) 273 */ 274 public ToStringHelper add(String name, float value) { 275 checkNameAndAppend(name).append(value); 276 return this; 277 } 278 279 /** 280 * Adds a name/value pair to the formatted output in {@code name=value} 281 * format. 282 * 283 * @since 11.0 (source-compatible since 2.0) 284 */ 285 public ToStringHelper add(String name, int value) { 286 checkNameAndAppend(name).append(value); 287 return this; 288 } 289 290 /** 291 * Adds a name/value pair to the formatted output in {@code name=value} 292 * format. 293 * 294 * @since 11.0 (source-compatible since 2.0) 295 */ 296 public ToStringHelper add(String name, long value) { 297 checkNameAndAppend(name).append(value); 298 return this; 299 } 300 301 private StringBuilder checkNameAndAppend(String name) { 302 checkNotNull(name); 303 return addHolder().builder.append(name).append('='); 304 } 305 306 /** 307 * Adds an unnamed value to the formatted output. 308 * 309 * <p>It is strongly encouraged to use {@link #add(String, Object)} instead 310 * and give value a readable name. 311 */ 312 public ToStringHelper addValue(@Nullable Object value) { 313 addHolder(value).builder.append(value); 314 return this; 315 } 316 317 /** 318 * Adds an unnamed value to the formatted output. 319 * 320 * <p>It is strongly encouraged to use {@link #add(String, boolean)} instead 321 * and give value a readable name. 322 * 323 * @since 11.0 (source-compatible since 2.0) 324 */ 325 public ToStringHelper addValue(boolean value) { 326 addHolder().builder.append(value); 327 return this; 328 } 329 330 /** 331 * Adds an unnamed value to the formatted output. 332 * 333 * <p>It is strongly encouraged to use {@link #add(String, char)} instead 334 * and give value a readable name. 335 * 336 * @since 11.0 (source-compatible since 2.0) 337 */ 338 public ToStringHelper addValue(char value) { 339 addHolder().builder.append(value); 340 return this; 341 } 342 343 /** 344 * Adds an unnamed value to the formatted output. 345 * 346 * <p>It is strongly encouraged to use {@link #add(String, double)} instead 347 * and give value a readable name. 348 * 349 * @since 11.0 (source-compatible since 2.0) 350 */ 351 public ToStringHelper addValue(double value) { 352 addHolder().builder.append(value); 353 return this; 354 } 355 356 /** 357 * Adds an unnamed value to the formatted output. 358 * 359 * <p>It is strongly encouraged to use {@link #add(String, float)} instead 360 * and give value a readable name. 361 * 362 * @since 11.0 (source-compatible since 2.0) 363 */ 364 public ToStringHelper addValue(float value) { 365 addHolder().builder.append(value); 366 return this; 367 } 368 369 /** 370 * Adds an unnamed value to the formatted output. 371 * 372 * <p>It is strongly encouraged to use {@link #add(String, int)} instead 373 * and give value a readable name. 374 * 375 * @since 11.0 (source-compatible since 2.0) 376 */ 377 public ToStringHelper addValue(int value) { 378 addHolder().builder.append(value); 379 return this; 380 } 381 382 /** 383 * Adds an unnamed value to the formatted output. 384 * 385 * <p>It is strongly encouraged to use {@link #add(String, long)} instead 386 * and give value a readable name. 387 * 388 * @since 11.0 (source-compatible since 2.0) 389 */ 390 public ToStringHelper addValue(long value) { 391 addHolder().builder.append(value); 392 return this; 393 } 394 395 /** 396 * Returns a string in the format specified by {@link 397 * Objects#toStringHelper(Object)}. 398 */ 399 @Override public String toString() { 400 // create a copy to keep it consistent in case value changes 401 boolean omitNullValuesSnapshot = omitNullValues; 402 boolean needsSeparator = false; 403 StringBuilder builder = new StringBuilder(32).append(className) 404 .append('{'); 405 for (ValueHolder valueHolder : valueHolders) { 406 if (!omitNullValuesSnapshot || !valueHolder.isNull) { 407 if (needsSeparator) { 408 builder.append(", "); 409 } else { 410 needsSeparator = true; 411 } 412 // must explicitly cast it, otherwise GWT tests might fail because 413 // it tries to access StringBuilder.append(StringBuilder), which is 414 // a private method 415 // TODO(user): change once 5904010 is fixed 416 CharSequence sequence = valueHolder.builder; 417 builder.append(sequence); 418 } 419 } 420 return builder.append('}').toString(); 421 } 422 423 private ValueHolder addHolder() { 424 ValueHolder valueHolder = new ValueHolder(); 425 valueHolders.add(valueHolder); 426 return valueHolder; 427 } 428 429 private ValueHolder addHolder(@Nullable Object value) { 430 ValueHolder valueHolder = addHolder(); 431 valueHolder.isNull = (value == null); 432 return valueHolder; 433 } 434 435 private static final class ValueHolder { 436 final StringBuilder builder = new StringBuilder(); 437 boolean isNull; 438 } 439 } 440 }