001/* 002 * Copyright 2002-2020 the original author or 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 * https://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 org.springframework.util; 018 019import java.lang.reflect.Array; 020import java.util.Arrays; 021import java.util.Collection; 022import java.util.Map; 023import java.util.Optional; 024import java.util.StringJoiner; 025 026import org.springframework.lang.Nullable; 027 028/** 029 * Miscellaneous object utility methods. 030 * 031 * <p>Mainly for internal use within the framework. 032 * 033 * <p>Thanks to Alex Ruiz for contributing several enhancements to this class! 034 * 035 * @author Juergen Hoeller 036 * @author Keith Donald 037 * @author Rod Johnson 038 * @author Rob Harrop 039 * @author Chris Beams 040 * @author Sam Brannen 041 * @since 19.03.2004 042 * @see ClassUtils 043 * @see CollectionUtils 044 * @see StringUtils 045 */ 046public abstract class ObjectUtils { 047 048 private static final int INITIAL_HASH = 7; 049 private static final int MULTIPLIER = 31; 050 051 private static final String EMPTY_STRING = ""; 052 private static final String NULL_STRING = "null"; 053 private static final String ARRAY_START = "{"; 054 private static final String ARRAY_END = "}"; 055 private static final String EMPTY_ARRAY = ARRAY_START + ARRAY_END; 056 private static final String ARRAY_ELEMENT_SEPARATOR = ", "; 057 private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0]; 058 059 060 /** 061 * Return whether the given throwable is a checked exception: 062 * that is, neither a RuntimeException nor an Error. 063 * @param ex the throwable to check 064 * @return whether the throwable is a checked exception 065 * @see java.lang.Exception 066 * @see java.lang.RuntimeException 067 * @see java.lang.Error 068 */ 069 public static boolean isCheckedException(Throwable ex) { 070 return !(ex instanceof RuntimeException || ex instanceof Error); 071 } 072 073 /** 074 * Check whether the given exception is compatible with the specified 075 * exception types, as declared in a throws clause. 076 * @param ex the exception to check 077 * @param declaredExceptions the exception types declared in the throws clause 078 * @return whether the given exception is compatible 079 */ 080 public static boolean isCompatibleWithThrowsClause(Throwable ex, @Nullable Class<?>... declaredExceptions) { 081 if (!isCheckedException(ex)) { 082 return true; 083 } 084 if (declaredExceptions != null) { 085 for (Class<?> declaredException : declaredExceptions) { 086 if (declaredException.isInstance(ex)) { 087 return true; 088 } 089 } 090 } 091 return false; 092 } 093 094 /** 095 * Determine whether the given object is an array: 096 * either an Object array or a primitive array. 097 * @param obj the object to check 098 */ 099 public static boolean isArray(@Nullable Object obj) { 100 return (obj != null && obj.getClass().isArray()); 101 } 102 103 /** 104 * Determine whether the given array is empty: 105 * i.e. {@code null} or of zero length. 106 * @param array the array to check 107 * @see #isEmpty(Object) 108 */ 109 public static boolean isEmpty(@Nullable Object[] array) { 110 return (array == null || array.length == 0); 111 } 112 113 /** 114 * Determine whether the given object is empty. 115 * <p>This method supports the following object types. 116 * <ul> 117 * <li>{@code Optional}: considered empty if {@link Optional#empty()}</li> 118 * <li>{@code Array}: considered empty if its length is zero</li> 119 * <li>{@link CharSequence}: considered empty if its length is zero</li> 120 * <li>{@link Collection}: delegates to {@link Collection#isEmpty()}</li> 121 * <li>{@link Map}: delegates to {@link Map#isEmpty()}</li> 122 * </ul> 123 * <p>If the given object is non-null and not one of the aforementioned 124 * supported types, this method returns {@code false}. 125 * @param obj the object to check 126 * @return {@code true} if the object is {@code null} or <em>empty</em> 127 * @since 4.2 128 * @see Optional#isPresent() 129 * @see ObjectUtils#isEmpty(Object[]) 130 * @see StringUtils#hasLength(CharSequence) 131 * @see StringUtils#isEmpty(Object) 132 * @see CollectionUtils#isEmpty(java.util.Collection) 133 * @see CollectionUtils#isEmpty(java.util.Map) 134 */ 135 public static boolean isEmpty(@Nullable Object obj) { 136 if (obj == null) { 137 return true; 138 } 139 140 if (obj instanceof Optional) { 141 return !((Optional<?>) obj).isPresent(); 142 } 143 if (obj instanceof CharSequence) { 144 return ((CharSequence) obj).length() == 0; 145 } 146 if (obj.getClass().isArray()) { 147 return Array.getLength(obj) == 0; 148 } 149 if (obj instanceof Collection) { 150 return ((Collection<?>) obj).isEmpty(); 151 } 152 if (obj instanceof Map) { 153 return ((Map<?, ?>) obj).isEmpty(); 154 } 155 156 // else 157 return false; 158 } 159 160 /** 161 * Unwrap the given object which is potentially a {@link java.util.Optional}. 162 * @param obj the candidate object 163 * @return either the value held within the {@code Optional}, {@code null} 164 * if the {@code Optional} is empty, or simply the given object as-is 165 * @since 5.0 166 */ 167 @Nullable 168 public static Object unwrapOptional(@Nullable Object obj) { 169 if (obj instanceof Optional) { 170 Optional<?> optional = (Optional<?>) obj; 171 if (!optional.isPresent()) { 172 return null; 173 } 174 Object result = optional.get(); 175 Assert.isTrue(!(result instanceof Optional), "Multi-level Optional usage not supported"); 176 return result; 177 } 178 return obj; 179 } 180 181 /** 182 * Check whether the given array contains the given element. 183 * @param array the array to check (may be {@code null}, 184 * in which case the return value will always be {@code false}) 185 * @param element the element to check for 186 * @return whether the element has been found in the given array 187 */ 188 public static boolean containsElement(@Nullable Object[] array, Object element) { 189 if (array == null) { 190 return false; 191 } 192 for (Object arrayEle : array) { 193 if (nullSafeEquals(arrayEle, element)) { 194 return true; 195 } 196 } 197 return false; 198 } 199 200 /** 201 * Check whether the given array of enum constants contains a constant with the given name, 202 * ignoring case when determining a match. 203 * @param enumValues the enum values to check, typically obtained via {@code MyEnum.values()} 204 * @param constant the constant name to find (must not be null or empty string) 205 * @return whether the constant has been found in the given array 206 */ 207 public static boolean containsConstant(Enum<?>[] enumValues, String constant) { 208 return containsConstant(enumValues, constant, false); 209 } 210 211 /** 212 * Check whether the given array of enum constants contains a constant with the given name. 213 * @param enumValues the enum values to check, typically obtained via {@code MyEnum.values()} 214 * @param constant the constant name to find (must not be null or empty string) 215 * @param caseSensitive whether case is significant in determining a match 216 * @return whether the constant has been found in the given array 217 */ 218 public static boolean containsConstant(Enum<?>[] enumValues, String constant, boolean caseSensitive) { 219 for (Enum<?> candidate : enumValues) { 220 if (caseSensitive ? candidate.toString().equals(constant) : 221 candidate.toString().equalsIgnoreCase(constant)) { 222 return true; 223 } 224 } 225 return false; 226 } 227 228 /** 229 * Case insensitive alternative to {@link Enum#valueOf(Class, String)}. 230 * @param <E> the concrete Enum type 231 * @param enumValues the array of all Enum constants in question, usually per {@code Enum.values()} 232 * @param constant the constant to get the enum value of 233 * @throws IllegalArgumentException if the given constant is not found in the given array 234 * of enum values. Use {@link #containsConstant(Enum[], String)} as a guard to avoid this exception. 235 */ 236 public static <E extends Enum<?>> E caseInsensitiveValueOf(E[] enumValues, String constant) { 237 for (E candidate : enumValues) { 238 if (candidate.toString().equalsIgnoreCase(constant)) { 239 return candidate; 240 } 241 } 242 throw new IllegalArgumentException("Constant [" + constant + "] does not exist in enum type " + 243 enumValues.getClass().getComponentType().getName()); 244 } 245 246 /** 247 * Append the given object to the given array, returning a new array 248 * consisting of the input array contents plus the given object. 249 * @param array the array to append to (can be {@code null}) 250 * @param obj the object to append 251 * @return the new array (of the same component type; never {@code null}) 252 */ 253 public static <A, O extends A> A[] addObjectToArray(@Nullable A[] array, @Nullable O obj) { 254 Class<?> compType = Object.class; 255 if (array != null) { 256 compType = array.getClass().getComponentType(); 257 } 258 else if (obj != null) { 259 compType = obj.getClass(); 260 } 261 int newArrLength = (array != null ? array.length + 1 : 1); 262 @SuppressWarnings("unchecked") 263 A[] newArr = (A[]) Array.newInstance(compType, newArrLength); 264 if (array != null) { 265 System.arraycopy(array, 0, newArr, 0, array.length); 266 } 267 newArr[newArr.length - 1] = obj; 268 return newArr; 269 } 270 271 /** 272 * Convert the given array (which may be a primitive array) to an 273 * object array (if necessary of primitive wrapper objects). 274 * <p>A {@code null} source value will be converted to an 275 * empty Object array. 276 * @param source the (potentially primitive) array 277 * @return the corresponding object array (never {@code null}) 278 * @throws IllegalArgumentException if the parameter is not an array 279 */ 280 public static Object[] toObjectArray(@Nullable Object source) { 281 if (source instanceof Object[]) { 282 return (Object[]) source; 283 } 284 if (source == null) { 285 return EMPTY_OBJECT_ARRAY; 286 } 287 if (!source.getClass().isArray()) { 288 throw new IllegalArgumentException("Source is not an array: " + source); 289 } 290 int length = Array.getLength(source); 291 if (length == 0) { 292 return EMPTY_OBJECT_ARRAY; 293 } 294 Class<?> wrapperType = Array.get(source, 0).getClass(); 295 Object[] newArray = (Object[]) Array.newInstance(wrapperType, length); 296 for (int i = 0; i < length; i++) { 297 newArray[i] = Array.get(source, i); 298 } 299 return newArray; 300 } 301 302 303 //--------------------------------------------------------------------- 304 // Convenience methods for content-based equality/hash-code handling 305 //--------------------------------------------------------------------- 306 307 /** 308 * Determine if the given objects are equal, returning {@code true} if 309 * both are {@code null} or {@code false} if only one is {@code null}. 310 * <p>Compares arrays with {@code Arrays.equals}, performing an equality 311 * check based on the array elements rather than the array reference. 312 * @param o1 first Object to compare 313 * @param o2 second Object to compare 314 * @return whether the given objects are equal 315 * @see Object#equals(Object) 316 * @see java.util.Arrays#equals 317 */ 318 public static boolean nullSafeEquals(@Nullable Object o1, @Nullable Object o2) { 319 if (o1 == o2) { 320 return true; 321 } 322 if (o1 == null || o2 == null) { 323 return false; 324 } 325 if (o1.equals(o2)) { 326 return true; 327 } 328 if (o1.getClass().isArray() && o2.getClass().isArray()) { 329 return arrayEquals(o1, o2); 330 } 331 return false; 332 } 333 334 /** 335 * Compare the given arrays with {@code Arrays.equals}, performing an equality 336 * check based on the array elements rather than the array reference. 337 * @param o1 first array to compare 338 * @param o2 second array to compare 339 * @return whether the given objects are equal 340 * @see #nullSafeEquals(Object, Object) 341 * @see java.util.Arrays#equals 342 */ 343 private static boolean arrayEquals(Object o1, Object o2) { 344 if (o1 instanceof Object[] && o2 instanceof Object[]) { 345 return Arrays.equals((Object[]) o1, (Object[]) o2); 346 } 347 if (o1 instanceof boolean[] && o2 instanceof boolean[]) { 348 return Arrays.equals((boolean[]) o1, (boolean[]) o2); 349 } 350 if (o1 instanceof byte[] && o2 instanceof byte[]) { 351 return Arrays.equals((byte[]) o1, (byte[]) o2); 352 } 353 if (o1 instanceof char[] && o2 instanceof char[]) { 354 return Arrays.equals((char[]) o1, (char[]) o2); 355 } 356 if (o1 instanceof double[] && o2 instanceof double[]) { 357 return Arrays.equals((double[]) o1, (double[]) o2); 358 } 359 if (o1 instanceof float[] && o2 instanceof float[]) { 360 return Arrays.equals((float[]) o1, (float[]) o2); 361 } 362 if (o1 instanceof int[] && o2 instanceof int[]) { 363 return Arrays.equals((int[]) o1, (int[]) o2); 364 } 365 if (o1 instanceof long[] && o2 instanceof long[]) { 366 return Arrays.equals((long[]) o1, (long[]) o2); 367 } 368 if (o1 instanceof short[] && o2 instanceof short[]) { 369 return Arrays.equals((short[]) o1, (short[]) o2); 370 } 371 return false; 372 } 373 374 /** 375 * Return as hash code for the given object; typically the value of 376 * {@code Object#hashCode()}}. If the object is an array, 377 * this method will delegate to any of the {@code nullSafeHashCode} 378 * methods for arrays in this class. If the object is {@code null}, 379 * this method returns 0. 380 * @see Object#hashCode() 381 * @see #nullSafeHashCode(Object[]) 382 * @see #nullSafeHashCode(boolean[]) 383 * @see #nullSafeHashCode(byte[]) 384 * @see #nullSafeHashCode(char[]) 385 * @see #nullSafeHashCode(double[]) 386 * @see #nullSafeHashCode(float[]) 387 * @see #nullSafeHashCode(int[]) 388 * @see #nullSafeHashCode(long[]) 389 * @see #nullSafeHashCode(short[]) 390 */ 391 public static int nullSafeHashCode(@Nullable Object obj) { 392 if (obj == null) { 393 return 0; 394 } 395 if (obj.getClass().isArray()) { 396 if (obj instanceof Object[]) { 397 return nullSafeHashCode((Object[]) obj); 398 } 399 if (obj instanceof boolean[]) { 400 return nullSafeHashCode((boolean[]) obj); 401 } 402 if (obj instanceof byte[]) { 403 return nullSafeHashCode((byte[]) obj); 404 } 405 if (obj instanceof char[]) { 406 return nullSafeHashCode((char[]) obj); 407 } 408 if (obj instanceof double[]) { 409 return nullSafeHashCode((double[]) obj); 410 } 411 if (obj instanceof float[]) { 412 return nullSafeHashCode((float[]) obj); 413 } 414 if (obj instanceof int[]) { 415 return nullSafeHashCode((int[]) obj); 416 } 417 if (obj instanceof long[]) { 418 return nullSafeHashCode((long[]) obj); 419 } 420 if (obj instanceof short[]) { 421 return nullSafeHashCode((short[]) obj); 422 } 423 } 424 return obj.hashCode(); 425 } 426 427 /** 428 * Return a hash code based on the contents of the specified array. 429 * If {@code array} is {@code null}, this method returns 0. 430 */ 431 public static int nullSafeHashCode(@Nullable Object[] array) { 432 if (array == null) { 433 return 0; 434 } 435 int hash = INITIAL_HASH; 436 for (Object element : array) { 437 hash = MULTIPLIER * hash + nullSafeHashCode(element); 438 } 439 return hash; 440 } 441 442 /** 443 * Return a hash code based on the contents of the specified array. 444 * If {@code array} is {@code null}, this method returns 0. 445 */ 446 public static int nullSafeHashCode(@Nullable boolean[] array) { 447 if (array == null) { 448 return 0; 449 } 450 int hash = INITIAL_HASH; 451 for (boolean element : array) { 452 hash = MULTIPLIER * hash + Boolean.hashCode(element); 453 } 454 return hash; 455 } 456 457 /** 458 * Return a hash code based on the contents of the specified array. 459 * If {@code array} is {@code null}, this method returns 0. 460 */ 461 public static int nullSafeHashCode(@Nullable byte[] array) { 462 if (array == null) { 463 return 0; 464 } 465 int hash = INITIAL_HASH; 466 for (byte element : array) { 467 hash = MULTIPLIER * hash + element; 468 } 469 return hash; 470 } 471 472 /** 473 * Return a hash code based on the contents of the specified array. 474 * If {@code array} is {@code null}, this method returns 0. 475 */ 476 public static int nullSafeHashCode(@Nullable char[] array) { 477 if (array == null) { 478 return 0; 479 } 480 int hash = INITIAL_HASH; 481 for (char element : array) { 482 hash = MULTIPLIER * hash + element; 483 } 484 return hash; 485 } 486 487 /** 488 * Return a hash code based on the contents of the specified array. 489 * If {@code array} is {@code null}, this method returns 0. 490 */ 491 public static int nullSafeHashCode(@Nullable double[] array) { 492 if (array == null) { 493 return 0; 494 } 495 int hash = INITIAL_HASH; 496 for (double element : array) { 497 hash = MULTIPLIER * hash + Double.hashCode(element); 498 } 499 return hash; 500 } 501 502 /** 503 * Return a hash code based on the contents of the specified array. 504 * If {@code array} is {@code null}, this method returns 0. 505 */ 506 public static int nullSafeHashCode(@Nullable float[] array) { 507 if (array == null) { 508 return 0; 509 } 510 int hash = INITIAL_HASH; 511 for (float element : array) { 512 hash = MULTIPLIER * hash + Float.hashCode(element); 513 } 514 return hash; 515 } 516 517 /** 518 * Return a hash code based on the contents of the specified array. 519 * If {@code array} is {@code null}, this method returns 0. 520 */ 521 public static int nullSafeHashCode(@Nullable int[] array) { 522 if (array == null) { 523 return 0; 524 } 525 int hash = INITIAL_HASH; 526 for (int element : array) { 527 hash = MULTIPLIER * hash + element; 528 } 529 return hash; 530 } 531 532 /** 533 * Return a hash code based on the contents of the specified array. 534 * If {@code array} is {@code null}, this method returns 0. 535 */ 536 public static int nullSafeHashCode(@Nullable long[] array) { 537 if (array == null) { 538 return 0; 539 } 540 int hash = INITIAL_HASH; 541 for (long element : array) { 542 hash = MULTIPLIER * hash + Long.hashCode(element); 543 } 544 return hash; 545 } 546 547 /** 548 * Return a hash code based on the contents of the specified array. 549 * If {@code array} is {@code null}, this method returns 0. 550 */ 551 public static int nullSafeHashCode(@Nullable short[] array) { 552 if (array == null) { 553 return 0; 554 } 555 int hash = INITIAL_HASH; 556 for (short element : array) { 557 hash = MULTIPLIER * hash + element; 558 } 559 return hash; 560 } 561 562 /** 563 * Return the same value as {@link Boolean#hashCode(boolean)}}. 564 * @deprecated as of Spring Framework 5.0, in favor of the native JDK 8 variant 565 */ 566 @Deprecated 567 public static int hashCode(boolean bool) { 568 return Boolean.hashCode(bool); 569 } 570 571 /** 572 * Return the same value as {@link Double#hashCode(double)}}. 573 * @deprecated as of Spring Framework 5.0, in favor of the native JDK 8 variant 574 */ 575 @Deprecated 576 public static int hashCode(double dbl) { 577 return Double.hashCode(dbl); 578 } 579 580 /** 581 * Return the same value as {@link Float#hashCode(float)}}. 582 * @deprecated as of Spring Framework 5.0, in favor of the native JDK 8 variant 583 */ 584 @Deprecated 585 public static int hashCode(float flt) { 586 return Float.hashCode(flt); 587 } 588 589 /** 590 * Return the same value as {@link Long#hashCode(long)}}. 591 * @deprecated as of Spring Framework 5.0, in favor of the native JDK 8 variant 592 */ 593 @Deprecated 594 public static int hashCode(long lng) { 595 return Long.hashCode(lng); 596 } 597 598 599 //--------------------------------------------------------------------- 600 // Convenience methods for toString output 601 //--------------------------------------------------------------------- 602 603 /** 604 * Return a String representation of an object's overall identity. 605 * @param obj the object (may be {@code null}) 606 * @return the object's identity as String representation, 607 * or an empty String if the object was {@code null} 608 */ 609 public static String identityToString(@Nullable Object obj) { 610 if (obj == null) { 611 return EMPTY_STRING; 612 } 613 return obj.getClass().getName() + "@" + getIdentityHexString(obj); 614 } 615 616 /** 617 * Return a hex String form of an object's identity hash code. 618 * @param obj the object 619 * @return the object's identity code in hex notation 620 */ 621 public static String getIdentityHexString(Object obj) { 622 return Integer.toHexString(System.identityHashCode(obj)); 623 } 624 625 /** 626 * Return a content-based String representation if {@code obj} is 627 * not {@code null}; otherwise returns an empty String. 628 * <p>Differs from {@link #nullSafeToString(Object)} in that it returns 629 * an empty String rather than "null" for a {@code null} value. 630 * @param obj the object to build a display String for 631 * @return a display String representation of {@code obj} 632 * @see #nullSafeToString(Object) 633 */ 634 public static String getDisplayString(@Nullable Object obj) { 635 if (obj == null) { 636 return EMPTY_STRING; 637 } 638 return nullSafeToString(obj); 639 } 640 641 /** 642 * Determine the class name for the given object. 643 * <p>Returns a {@code "null"} String if {@code obj} is {@code null}. 644 * @param obj the object to introspect (may be {@code null}) 645 * @return the corresponding class name 646 */ 647 public static String nullSafeClassName(@Nullable Object obj) { 648 return (obj != null ? obj.getClass().getName() : NULL_STRING); 649 } 650 651 /** 652 * Return a String representation of the specified Object. 653 * <p>Builds a String representation of the contents in case of an array. 654 * Returns a {@code "null"} String if {@code obj} is {@code null}. 655 * @param obj the object to build a String representation for 656 * @return a String representation of {@code obj} 657 */ 658 public static String nullSafeToString(@Nullable Object obj) { 659 if (obj == null) { 660 return NULL_STRING; 661 } 662 if (obj instanceof String) { 663 return (String) obj; 664 } 665 if (obj instanceof Object[]) { 666 return nullSafeToString((Object[]) obj); 667 } 668 if (obj instanceof boolean[]) { 669 return nullSafeToString((boolean[]) obj); 670 } 671 if (obj instanceof byte[]) { 672 return nullSafeToString((byte[]) obj); 673 } 674 if (obj instanceof char[]) { 675 return nullSafeToString((char[]) obj); 676 } 677 if (obj instanceof double[]) { 678 return nullSafeToString((double[]) obj); 679 } 680 if (obj instanceof float[]) { 681 return nullSafeToString((float[]) obj); 682 } 683 if (obj instanceof int[]) { 684 return nullSafeToString((int[]) obj); 685 } 686 if (obj instanceof long[]) { 687 return nullSafeToString((long[]) obj); 688 } 689 if (obj instanceof short[]) { 690 return nullSafeToString((short[]) obj); 691 } 692 String str = obj.toString(); 693 return (str != null ? str : EMPTY_STRING); 694 } 695 696 /** 697 * Return a String representation of the contents of the specified array. 698 * <p>The String representation consists of a list of the array's elements, 699 * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated 700 * by the characters {@code ", "} (a comma followed by a space). 701 * Returns a {@code "null"} String if {@code array} is {@code null}. 702 * @param array the array to build a String representation for 703 * @return a String representation of {@code array} 704 */ 705 public static String nullSafeToString(@Nullable Object[] array) { 706 if (array == null) { 707 return NULL_STRING; 708 } 709 int length = array.length; 710 if (length == 0) { 711 return EMPTY_ARRAY; 712 } 713 StringJoiner stringJoiner = new StringJoiner(ARRAY_ELEMENT_SEPARATOR, ARRAY_START, ARRAY_END); 714 for (Object o : array) { 715 stringJoiner.add(String.valueOf(o)); 716 } 717 return stringJoiner.toString(); 718 } 719 720 /** 721 * Return a String representation of the contents of the specified array. 722 * <p>The String representation consists of a list of the array's elements, 723 * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated 724 * by the characters {@code ", "} (a comma followed by a space). 725 * Returns a {@code "null"} String if {@code array} is {@code null}. 726 * @param array the array to build a String representation for 727 * @return a String representation of {@code array} 728 */ 729 public static String nullSafeToString(@Nullable boolean[] array) { 730 if (array == null) { 731 return NULL_STRING; 732 } 733 int length = array.length; 734 if (length == 0) { 735 return EMPTY_ARRAY; 736 } 737 StringJoiner stringJoiner = new StringJoiner(ARRAY_ELEMENT_SEPARATOR, ARRAY_START, ARRAY_END); 738 for (boolean b : array) { 739 stringJoiner.add(String.valueOf(b)); 740 } 741 return stringJoiner.toString(); 742 } 743 744 /** 745 * Return a String representation of the contents of the specified array. 746 * <p>The String representation consists of a list of the array's elements, 747 * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated 748 * by the characters {@code ", "} (a comma followed by a space). 749 * Returns a {@code "null"} String if {@code array} is {@code null}. 750 * @param array the array to build a String representation for 751 * @return a String representation of {@code array} 752 */ 753 public static String nullSafeToString(@Nullable byte[] array) { 754 if (array == null) { 755 return NULL_STRING; 756 } 757 int length = array.length; 758 if (length == 0) { 759 return EMPTY_ARRAY; 760 } 761 StringJoiner stringJoiner = new StringJoiner(ARRAY_ELEMENT_SEPARATOR, ARRAY_START, ARRAY_END); 762 for (byte b : array) { 763 stringJoiner.add(String.valueOf(b)); 764 } 765 return stringJoiner.toString(); 766 } 767 768 /** 769 * Return a String representation of the contents of the specified array. 770 * <p>The String representation consists of a list of the array's elements, 771 * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated 772 * by the characters {@code ", "} (a comma followed by a space). 773 * Returns a {@code "null"} String if {@code array} is {@code null}. 774 * @param array the array to build a String representation for 775 * @return a String representation of {@code array} 776 */ 777 public static String nullSafeToString(@Nullable char[] array) { 778 if (array == null) { 779 return NULL_STRING; 780 } 781 int length = array.length; 782 if (length == 0) { 783 return EMPTY_ARRAY; 784 } 785 StringJoiner stringJoiner = new StringJoiner(ARRAY_ELEMENT_SEPARATOR, ARRAY_START, ARRAY_END); 786 for (char c : array) { 787 stringJoiner.add('\'' + String.valueOf(c) + '\''); 788 } 789 return stringJoiner.toString(); 790 } 791 792 /** 793 * Return a String representation of the contents of the specified array. 794 * <p>The String representation consists of a list of the array's elements, 795 * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated 796 * by the characters {@code ", "} (a comma followed by a space). 797 * Returns a {@code "null"} String if {@code array} is {@code null}. 798 * @param array the array to build a String representation for 799 * @return a String representation of {@code array} 800 */ 801 public static String nullSafeToString(@Nullable double[] array) { 802 if (array == null) { 803 return NULL_STRING; 804 } 805 int length = array.length; 806 if (length == 0) { 807 return EMPTY_ARRAY; 808 } 809 StringJoiner stringJoiner = new StringJoiner(ARRAY_ELEMENT_SEPARATOR, ARRAY_START, ARRAY_END); 810 for (double d : array) { 811 stringJoiner.add(String.valueOf(d)); 812 } 813 return stringJoiner.toString(); 814 } 815 816 /** 817 * Return a String representation of the contents of the specified array. 818 * <p>The String representation consists of a list of the array's elements, 819 * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated 820 * by the characters {@code ", "} (a comma followed by a space). 821 * Returns a {@code "null"} String if {@code array} is {@code null}. 822 * @param array the array to build a String representation for 823 * @return a String representation of {@code array} 824 */ 825 public static String nullSafeToString(@Nullable float[] array) { 826 if (array == null) { 827 return NULL_STRING; 828 } 829 int length = array.length; 830 if (length == 0) { 831 return EMPTY_ARRAY; 832 } 833 StringJoiner stringJoiner = new StringJoiner(ARRAY_ELEMENT_SEPARATOR, ARRAY_START, ARRAY_END); 834 for (float f : array) { 835 stringJoiner.add(String.valueOf(f)); 836 } 837 return stringJoiner.toString(); 838 } 839 840 /** 841 * Return a String representation of the contents of the specified array. 842 * <p>The String representation consists of a list of the array's elements, 843 * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated 844 * by the characters {@code ", "} (a comma followed by a space). 845 * Returns a {@code "null"} String if {@code array} is {@code null}. 846 * @param array the array to build a String representation for 847 * @return a String representation of {@code array} 848 */ 849 public static String nullSafeToString(@Nullable int[] array) { 850 if (array == null) { 851 return NULL_STRING; 852 } 853 int length = array.length; 854 if (length == 0) { 855 return EMPTY_ARRAY; 856 } 857 StringJoiner stringJoiner = new StringJoiner(ARRAY_ELEMENT_SEPARATOR, ARRAY_START, ARRAY_END); 858 for (int i : array) { 859 stringJoiner.add(String.valueOf(i)); 860 } 861 return stringJoiner.toString(); 862 } 863 864 /** 865 * Return a String representation of the contents of the specified array. 866 * <p>The String representation consists of a list of the array's elements, 867 * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated 868 * by the characters {@code ", "} (a comma followed by a space). 869 * Returns a {@code "null"} String if {@code array} is {@code null}. 870 * @param array the array to build a String representation for 871 * @return a String representation of {@code array} 872 */ 873 public static String nullSafeToString(@Nullable long[] array) { 874 if (array == null) { 875 return NULL_STRING; 876 } 877 int length = array.length; 878 if (length == 0) { 879 return EMPTY_ARRAY; 880 } 881 StringJoiner stringJoiner = new StringJoiner(ARRAY_ELEMENT_SEPARATOR, ARRAY_START, ARRAY_END); 882 for (long l : array) { 883 stringJoiner.add(String.valueOf(l)); 884 } 885 return stringJoiner.toString(); 886 } 887 888 /** 889 * Return a String representation of the contents of the specified array. 890 * <p>The String representation consists of a list of the array's elements, 891 * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated 892 * by the characters {@code ", "} (a comma followed by a space). 893 * Returns a {@code "null"} String if {@code array} is {@code null}. 894 * @param array the array to build a String representation for 895 * @return a String representation of {@code array} 896 */ 897 public static String nullSafeToString(@Nullable short[] array) { 898 if (array == null) { 899 return NULL_STRING; 900 } 901 int length = array.length; 902 if (length == 0) { 903 return EMPTY_ARRAY; 904 } 905 StringJoiner stringJoiner = new StringJoiner(ARRAY_ELEMENT_SEPARATOR, ARRAY_START, ARRAY_END); 906 for (short s : array) { 907 stringJoiner.add(String.valueOf(s)); 908 } 909 return stringJoiner.toString(); 910 } 911 912}