001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * https://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.lang3.builder; 019 020import java.lang.reflect.Field; 021import java.lang.reflect.Modifier; 022import java.util.Arrays; 023import java.util.Collection; 024import java.util.Comparator; 025import java.util.Objects; 026 027import org.apache.commons.lang3.ArraySorter; 028import org.apache.commons.lang3.ArrayUtils; 029import org.apache.commons.lang3.ClassUtils; 030import org.apache.commons.lang3.stream.Streams; 031 032/** 033 * Assists in implementing {@link Object#toString()} methods using reflection. 034 * 035 * <p> 036 * This class uses reflection to determine the fields to append. Because these fields are usually private, the class 037 * uses {@link java.lang.reflect.AccessibleObject#setAccessible(java.lang.reflect.AccessibleObject[], boolean)} to 038 * change the visibility of the fields. This will fail under a security manager, unless the appropriate permissions are 039 * set up correctly. 040 * </p> 041 * <p> 042 * Using reflection to access (private) fields circumvents any synchronization protection guarding access to these 043 * fields. If a toString method cannot safely read a field, you should exclude it from the toString method, or use 044 * synchronization consistent with the class' lock management around the invocation of the method. Take special care to 045 * exclude non-thread-safe collection classes, because these classes may throw ConcurrentModificationException if 046 * modified while the toString method is executing. 047 * </p> 048 * <p> 049 * A typical invocation for this method would look like: 050 * </p> 051 * <pre> 052 * public String toString() { 053 * return ReflectionToStringBuilder.toString(this); 054 * } 055 * </pre> 056 * <p> 057 * You can also use the builder to debug 3rd party objects: 058 * </p> 059 * <pre> 060 * System.out.println("An object: " + ReflectionToStringBuilder.toString(anObject)); 061 * </pre> 062 * <p> 063 * A subclass can control field output by overriding the methods: 064 * </p> 065 * <ul> 066 * <li>{@link #accept(java.lang.reflect.Field)}</li> 067 * <li>{@link #getValue(java.lang.reflect.Field)}</li> 068 * </ul> 069 * <p> 070 * For example, this method does <em>not</em> include the {@code password} field in the returned {@link String}: 071 * </p> 072 * <pre> 073 * public String toString() { 074 * return (new ReflectionToStringBuilder(this) { 075 * protected boolean accept(Field f) { 076 * return super.accept(f) && !f.getName().equals("password"); 077 * } 078 * }).toString(); 079 * } 080 * </pre> 081 * <p> 082 * Alternatively the {@link ToStringExclude} annotation can be used to exclude fields from being incorporated in the 083 * result. 084 * </p> 085 * <p> 086 * It is also possible to use the {@link ToStringSummary} annotation to output the summary information instead of the 087 * detailed information of a field. 088 * </p> 089 * <p> 090 * The exact format of the {@code toString} is determined by the {@link ToStringStyle} passed into the constructor. 091 * </p> 092 * 093 * <p> 094 * <strong>Note:</strong> the default {@link ToStringStyle} will only do a "shallow" formatting, i.e. composed objects are not 095 * further traversed. To get "deep" formatting, use an instance of {@link RecursiveToStringStyle}. 096 * </p> 097 * 098 * @since 2.0 099 */ 100public class ReflectionToStringBuilder extends ToStringBuilder { 101 102 /** 103 * Converts the given Collection into an array of Strings. The returned array does not contain {@code null} 104 * entries. Note that {@link Arrays#sort(Object[])} will throw an {@link NullPointerException} if an array element 105 * is {@code null}. 106 * 107 * @param collection 108 * The collection to convert 109 * @return A new array of Strings. 110 */ 111 static String[] toNoNullStringArray(final Collection<String> collection) { 112 if (collection == null) { 113 return ArrayUtils.EMPTY_STRING_ARRAY; 114 } 115 return toNoNullStringArray(collection.toArray()); 116 } 117 118 /** 119 * Returns a new array of Strings without null elements. Internal method used to normalize exclude lists 120 * (arrays and collections). Note that {@link Arrays#sort(Object[])} will throw an {@link NullPointerException} 121 * if an array element is {@code null}. 122 * 123 * @param array 124 * The array to check 125 * @return The given array or a new array without null. 126 */ 127 static String[] toNoNullStringArray(final Object[] array) { 128 return Streams.nonNull(array).map(Objects::toString).toArray(String[]::new); 129 } 130 131 /** 132 * Builds a {@code toString} value using the default {@link ToStringStyle} through reflection. 133 * 134 * <p> 135 * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will 136 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is 137 * also not as efficient as testing explicitly. 138 * </p> 139 * 140 * <p> 141 * Transient members will be not be included, as they are likely derived. Static fields will not be included. 142 * Superclass fields will be appended. 143 * </p> 144 * 145 * @param object 146 * the Object to be output 147 * @return The String result 148 * @throws IllegalArgumentException Thrown if the Object is {@code null}. 149 * @see ToStringExclude 150 * @see ToStringSummary 151 */ 152 public static String toString(final Object object) { 153 return toString(object, null, false, false, null); 154 } 155 156 /** 157 * Builds a {@code toString} value through reflection. 158 * 159 * <p> 160 * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will 161 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is 162 * also not as efficient as testing explicitly. 163 * </p> 164 * 165 * <p> 166 * Transient members will be not be included, as they are likely derived. Static fields will not be included. 167 * Superclass fields will be appended. 168 * </p> 169 * 170 * <p> 171 * If the style is {@code null}, the default {@link ToStringStyle} is used. 172 * </p> 173 * 174 * @param object 175 * the Object to be output 176 * @param style 177 * the style of the {@code toString} to create, may be {@code null} 178 * @return The String result 179 * @throws IllegalArgumentException Thrown if the Object or {@link ToStringStyle} is {@code null}. 180 * @see ToStringExclude 181 * @see ToStringSummary 182 */ 183 public static String toString(final Object object, final ToStringStyle style) { 184 return toString(object, style, false, false, null); 185 } 186 187 /** 188 * Builds a {@code toString} value through reflection. 189 * 190 * <p> 191 * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will 192 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is 193 * also not as efficient as testing explicitly. 194 * </p> 195 * 196 * <p> 197 * If the {@code outputTransients} is {@code true}, transient members will be output, otherwise they 198 * are ignored, as they are likely derived fields, and not part of the value of the Object. 199 * </p> 200 * 201 * <p> 202 * Static fields will not be included. Superclass fields will be appended. 203 * </p> 204 * 205 * <p> 206 * If the style is {@code null}, the default {@link ToStringStyle} is used. 207 * </p> 208 * 209 * @param object 210 * the Object to be output 211 * @param style 212 * the style of the {@code toString} to create, may be {@code null} 213 * @param outputTransients 214 * whether to include transient fields 215 * @return The String result 216 * @throws IllegalArgumentException Thrown if the Object is {@code null}. 217 * @see ToStringExclude 218 * @see ToStringSummary 219 */ 220 public static String toString(final Object object, final ToStringStyle style, final boolean outputTransients) { 221 return toString(object, style, outputTransients, false, null); 222 } 223 224 /** 225 * Builds a {@code toString} value through reflection. 226 * 227 * <p> 228 * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will 229 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is 230 * also not as efficient as testing explicitly. 231 * </p> 232 * 233 * <p> 234 * If the {@code outputTransients} is {@code true}, transient fields will be output, otherwise they 235 * are ignored, as they are likely derived fields, and not part of the value of the Object. 236 * </p> 237 * 238 * <p> 239 * If the {@code outputStatics} is {@code true}, static fields will be output, otherwise they are 240 * ignored. 241 * </p> 242 * 243 * <p> 244 * Static fields will not be included. Superclass fields will be appended. 245 * </p> 246 * 247 * <p> 248 * If the style is {@code null}, the default {@link ToStringStyle} is used. 249 * </p> 250 * 251 * @param object 252 * the Object to be output 253 * @param style 254 * the style of the {@code toString} to create, may be {@code null} 255 * @param outputTransients 256 * whether to include transient fields 257 * @param outputStatics 258 * whether to include static fields 259 * @return The String result 260 * @throws IllegalArgumentException Thrown if the Object is {@code null}. 261 * @see ToStringExclude 262 * @see ToStringSummary 263 * @since 2.1 264 */ 265 public static String toString(final Object object, final ToStringStyle style, final boolean outputTransients, final boolean outputStatics) { 266 return toString(object, style, outputTransients, outputStatics, null); 267 } 268 269 /** 270 * Builds a {@code toString} value through reflection. 271 * 272 * <p> 273 * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will 274 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is 275 * also not as efficient as testing explicitly. 276 * </p> 277 * 278 * <p> 279 * If the {@code outputTransients} is {@code true}, transient fields will be output, otherwise they 280 * are ignored, as they are likely derived fields, and not part of the value of the Object. 281 * </p> 282 * 283 * <p> 284 * If the {@code outputStatics} is {@code true}, static fields will be output, otherwise they are 285 * ignored. 286 * </p> 287 * 288 * <p> 289 * Superclass fields will be appended up to and including the specified superclass. A null superclass is treated as 290 * {@link Object}. 291 * </p> 292 * 293 * <p> 294 * If the style is {@code null}, the default {@link ToStringStyle} is used. 295 * </p> 296 * 297 * @param <T> 298 * the type of the object 299 * @param object 300 * the Object to be output 301 * @param style 302 * the style of the {@code toString} to create, may be {@code null} 303 * @param outputTransients 304 * whether to include transient fields 305 * @param outputStatics 306 * whether to include static fields 307 * @param excludeNullValues 308 * whether to exclude fields whose values are null 309 * @param reflectUpToClass 310 * the superclass to reflect up to (inclusive), may be {@code null} 311 * @return The String result 312 * @throws IllegalArgumentException Thrown if the Object is {@code null}. 313 * @see ToStringExclude 314 * @see ToStringSummary 315 * @since 3.6 316 */ 317 public static <T> String toString( 318 final T object, final ToStringStyle style, final boolean outputTransients, 319 final boolean outputStatics, final boolean excludeNullValues, final Class<? super T> reflectUpToClass) { 320 return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients, outputStatics, excludeNullValues) 321 .toString(); 322 } 323 324 /** 325 * Builds a {@code toString} value through reflection. 326 * 327 * <p> 328 * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will 329 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is 330 * also not as efficient as testing explicitly. 331 * </p> 332 * 333 * <p> 334 * If the {@code outputTransients} is {@code true}, transient fields will be output, otherwise they 335 * are ignored, as they are likely derived fields, and not part of the value of the Object. 336 * </p> 337 * 338 * <p> 339 * If the {@code outputStatics} is {@code true}, static fields will be output, otherwise they are 340 * ignored. 341 * </p> 342 * 343 * <p> 344 * Superclass fields will be appended up to and including the specified superclass. A null superclass is treated as 345 * {@link Object}. 346 * </p> 347 * 348 * <p> 349 * If the style is {@code null}, the default {@link ToStringStyle} is used. 350 * </p> 351 * 352 * @param <T> 353 * the type of the object 354 * @param object 355 * the Object to be output 356 * @param style 357 * the style of the {@code toString} to create, may be {@code null} 358 * @param outputTransients 359 * whether to include transient fields 360 * @param outputStatics 361 * whether to include static fields 362 * @param reflectUpToClass 363 * the superclass to reflect up to (inclusive), may be {@code null} 364 * @return The String result 365 * @throws IllegalArgumentException Thrown if the Object is {@code null}. 366 * @see ToStringExclude 367 * @see ToStringSummary 368 * @since 2.1 369 */ 370 public static <T> String toString( 371 final T object, final ToStringStyle style, final boolean outputTransients, 372 final boolean outputStatics, final Class<? super T> reflectUpToClass) { 373 return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients, outputStatics) 374 .toString(); 375 } 376 377 /** 378 * Builds a String for a toString method excluding the given field names. 379 * 380 * @param object 381 * The object to "toString". 382 * @param excludeFieldNames 383 * The field names to exclude. Null excludes nothing. 384 * @return The toString value. 385 */ 386 public static String toStringExclude(final Object object, final Collection<String> excludeFieldNames) { 387 return toStringExclude(object, toNoNullStringArray(excludeFieldNames)); 388 } 389 390 /** 391 * Builds a String for a toString method excluding the given field names. 392 * 393 * @param object 394 * The object to "toString". 395 * @param excludeFieldNames 396 * The field names to exclude 397 * @return The toString value. 398 */ 399 public static String toStringExclude(final Object object, final String... excludeFieldNames) { 400 return new ReflectionToStringBuilder(object).setExcludeFieldNames(excludeFieldNames).toString(); 401 } 402 403 /** 404 * Builds a String for a toString method including the given field names. 405 * 406 * @param object 407 * The object to "toString". 408 * @param includeFieldNames 409 * {@code null} or empty means all fields are included. All fields are included by default. This method will override the default behavior. 410 * @return The toString value. 411 * @since 3.13.0 412 */ 413 public static String toStringInclude(final Object object, final Collection<String> includeFieldNames) { 414 return toStringInclude(object, toNoNullStringArray(includeFieldNames)); 415 } 416 417 /** 418 * Builds a String for a toString method including the given field names. 419 * 420 * @param object 421 * The object to "toString". 422 * @param includeFieldNames 423 * The field names to include. {@code null} or empty means all fields are included. All fields are included by default. This method will override the default 424 * behavior. 425 * @return The toString value. 426 * @since 3.13.0 427 */ 428 public static String toStringInclude(final Object object, final String... includeFieldNames) { 429 return new ReflectionToStringBuilder(object).setIncludeFieldNames(includeFieldNames).toString(); 430 } 431 432 /** 433 * Whether or not to append static fields. 434 */ 435 private boolean appendStatics; 436 437 /** 438 * Whether or not to append transient fields. 439 */ 440 private boolean appendTransients; 441 442 /** 443 * Whether or not to append fields that are null. 444 */ 445 private boolean excludeNullValues; 446 447 /** 448 * Which field names to exclude from output. Intended for fields like {@code "password"}. 449 * 450 * @since 3.0 this is protected instead of private 451 */ 452 protected String[] excludeFieldNames; 453 454 /** 455 * Field names that will be included in the output. All fields are included by default. 456 * 457 * @since 3.13.0 458 */ 459 protected String[] includeFieldNames; 460 461 /** 462 * The last super class to stop appending fields for. 463 */ 464 private Class<?> upToClass; 465 466 /** 467 * Constructs a new instance. 468 * 469 * <p> 470 * This constructor outputs using the default style set with {@code setDefaultStyle}. 471 * </p> 472 * 473 * @param object 474 * the Object to build a {@code toString} for, must not be {@code null} 475 */ 476 public ReflectionToStringBuilder(final Object object) { 477 super(object); 478 } 479 480 /** 481 * Constructs a new instance. 482 * 483 * <p> 484 * If the style is {@code null}, the default style is used. 485 * </p> 486 * 487 * @param object 488 * the Object to build a {@code toString} for, must not be {@code null} 489 * @param style 490 * the style of the {@code toString} to create, may be {@code null} 491 */ 492 public ReflectionToStringBuilder(final Object object, final ToStringStyle style) { 493 super(object, style); 494 } 495 496 /** 497 * Constructs a new instance. 498 * 499 * <p> 500 * If the style is {@code null}, the default style is used. 501 * </p> 502 * 503 * <p> 504 * If the buffer is {@code null}, a new one is created. 505 * </p> 506 * 507 * @param object 508 * the Object to build a {@code toString} for 509 * @param style 510 * the style of the {@code toString} to create, may be {@code null} 511 * @param buffer 512 * the {@link StringBuffer} to populate, may be {@code null} 513 */ 514 public ReflectionToStringBuilder(final Object object, final ToStringStyle style, final StringBuffer buffer) { 515 super(object, style, buffer); 516 } 517 518 /** 519 * Constructs a new instance. 520 * 521 * @param <T> 522 * the type of the object 523 * @param object 524 * the Object to build a {@code toString} for 525 * @param style 526 * the style of the {@code toString} to create, may be {@code null} 527 * @param buffer 528 * the {@link StringBuffer} to populate, may be {@code null} 529 * @param reflectUpToClass 530 * the superclass to reflect up to (inclusive), may be {@code null} 531 * @param outputTransients 532 * whether to include transient fields 533 * @param outputStatics 534 * whether to include static fields 535 * @since 2.1 536 */ 537 public <T> ReflectionToStringBuilder( 538 final T object, final ToStringStyle style, final StringBuffer buffer, 539 final Class<? super T> reflectUpToClass, final boolean outputTransients, final boolean outputStatics) { 540 super(object, style, buffer); 541 setUpToClass(reflectUpToClass); 542 setAppendTransients(outputTransients); 543 setAppendStatics(outputStatics); 544 } 545 546 /** 547 * Constructs a new instance. 548 * 549 * @param <T> 550 * the type of the object 551 * @param object 552 * the Object to build a {@code toString} for 553 * @param style 554 * the style of the {@code toString} to create, may be {@code null} 555 * @param buffer 556 * the {@link StringBuffer} to populate, may be {@code null} 557 * @param reflectUpToClass 558 * the superclass to reflect up to (inclusive), may be {@code null} 559 * @param outputTransients 560 * whether to include transient fields 561 * @param outputStatics 562 * whether to include static fields 563 * @param excludeNullValues 564 * whether to exclude fields who value is null 565 * @since 3.6 566 */ 567 public <T> ReflectionToStringBuilder( 568 final T object, final ToStringStyle style, final StringBuffer buffer, 569 final Class<? super T> reflectUpToClass, final boolean outputTransients, final boolean outputStatics, 570 final boolean excludeNullValues) { 571 super(object, style, buffer); 572 setUpToClass(reflectUpToClass); 573 setAppendTransients(outputTransients); 574 setAppendStatics(outputStatics); 575 setExcludeNullValues(excludeNullValues); 576 } 577 578 /** 579 * Returns whether or not to append the given {@link Field}. 580 * <ul> 581 * <li>Transient fields are appended only if {@link #isAppendTransients()} returns {@code true}.</li> 582 * <li>Static fields are appended only if {@link #isAppendStatics()} returns {@code true}.</li> 583 * <li>Inner class fields are not appended.</li> 584 * </ul> 585 * 586 * @param field 587 * The Field to test. 588 * @return Whether or not to append the given {@link Field}. 589 */ 590 protected boolean accept(final Field field) { 591 if (field.getName().indexOf(ClassUtils.INNER_CLASS_SEPARATOR_CHAR) != -1) { 592 // Reject field from inner class. 593 return false; 594 } 595 if (Modifier.isTransient(field.getModifiers()) && !isAppendTransients()) { 596 // Reject transient fields. 597 return false; 598 } 599 if (Modifier.isStatic(field.getModifiers()) && !isAppendStatics()) { 600 // Reject static fields. 601 return false; 602 } 603 if (this.excludeFieldNames != null && Arrays.binarySearch(this.excludeFieldNames, field.getName()) >= 0) { 604 // Reject fields from the getExcludeFieldNames list. 605 return false; 606 } 607 if (ArrayUtils.isNotEmpty(includeFieldNames)) { 608 // Accept fields from the getIncludeFieldNames list. {@code null} or empty means all fields are included. All fields are included by default. 609 return Arrays.binarySearch(this.includeFieldNames, field.getName()) >= 0; 610 } 611 return !field.isAnnotationPresent(ToStringExclude.class); 612 } 613 614 /** 615 * Appends the fields and values defined by the given object of the given Class. 616 * 617 * <p> 618 * If a cycle is detected as an object is "toString()'ed", such an object is rendered as if 619 * {@code Object.toString()} had been called and not implemented by the object. 620 * </p> 621 * 622 * @param clazz 623 * The class of object parameter 624 */ 625 protected void appendFieldsIn(final Class<?> clazz) { 626 if (clazz.isArray()) { 627 reflectionAppendArray(getObject()); 628 return; 629 } 630 // The elements in the returned array are not sorted and are not in any particular order. 631 final Field[] fields = ArraySorter.sort(clazz.getDeclaredFields(), Comparator.comparing(Field::getName)); 632 for (final Field field : fields) { 633 final String fieldName = field.getName(); 634 if (accept(field)) { 635 setAccessible(field); 636 try { 637 // Warning: Field.get(Object) creates wrappers objects 638 // for primitive types. 639 final Object fieldValue = field.isAccessible() ? getValue(field) : null; 640 if (!excludeNullValues || fieldValue != null) { 641 this.append(fieldName, fieldValue, !field.isAnnotationPresent(ToStringSummary.class)); 642 } 643 } catch (final IllegalAccessException e) { 644 // this can't happen. Would get a Security exception instead throw a runtime exception in case the 645 // impossible happens. 646 throw new IllegalStateException(e); 647 } 648 } 649 } 650 } 651 652 /** 653 * Gets the excludeFieldNames. 654 * 655 * @return The excludeFieldNames. 656 */ 657 public String[] getExcludeFieldNames() { 658 return this.excludeFieldNames.clone(); 659 } 660 661 /** 662 * Gets the includeFieldNames 663 * 664 * @return The includeFieldNames. 665 * @since 3.13.0 666 */ 667 public String[] getIncludeFieldNames() { 668 return this.includeFieldNames.clone(); 669 } 670 671 /** 672 * Gets the last super class to stop appending fields for. 673 * 674 * @return The last super class to stop appending fields for. 675 */ 676 public Class<?> getUpToClass() { 677 return this.upToClass; 678 } 679 680 /** 681 * Gets the field value using {@code java.lang.reflect.Field.get(Object)}. 682 * 683 * @param field 684 * The Field to query. 685 * @return The Object from the given Field. 686 * @throws IllegalArgumentException Thrown as described in {@link java.lang.reflect.Field#get(Object)}. 687 * @throws IllegalAccessException Thrown as described in {@link java.lang.reflect.Field#get(Object)}. 688 * @see java.lang.reflect.Field#get(Object) 689 */ 690 protected Object getValue(final Field field) throws IllegalAccessException { 691 return field.get(getObject()); 692 } 693 694 /** 695 * Tests whether or not to append static fields. 696 * 697 * @return Whether or not to append static fields. 698 * @since 2.1 699 */ 700 public boolean isAppendStatics() { 701 return this.appendStatics; 702 } 703 704 /** 705 * Tests whether or not to append transient fields. 706 * 707 * @return Whether or not to append transient fields. 708 */ 709 public boolean isAppendTransients() { 710 return this.appendTransients; 711 } 712 713 /** 714 * Tests whether or not to append fields whose values are null. 715 * 716 * @return Whether or not to append fields whose values are null. 717 * @since 3.6 718 */ 719 public boolean isExcludeNullValues() { 720 return this.excludeNullValues; 721 } 722 723 /** 724 * Appends to the {@code toString} an {@link Object} array. 725 * 726 * @param array 727 * the array to add to the {@code toString} 728 * @return {@code this} instance. 729 */ 730 public ReflectionToStringBuilder reflectionAppendArray(final Object array) { 731 getStyle().reflectionAppendArrayDetail(getStringBuffer(), null, array); 732 return this; 733 } 734 735 /** 736 * Sets whether or not to append static fields. 737 * 738 * @param appendStatics 739 * Whether or not to append static fields. 740 * @since 2.1 741 */ 742 public void setAppendStatics(final boolean appendStatics) { 743 this.appendStatics = appendStatics; 744 } 745 746 /** 747 * Sets whether or not to append transient fields. 748 * 749 * @param appendTransients 750 * Whether or not to append transient fields. 751 */ 752 public void setAppendTransients(final boolean appendTransients) { 753 this.appendTransients = appendTransients; 754 } 755 756 /** 757 * Sets the field names to exclude. 758 * 759 * @param excludeFieldNamesParam 760 * The excludeFieldNames to excluding from toString or {@code null}. 761 * @return {@code this} 762 */ 763 public ReflectionToStringBuilder setExcludeFieldNames(final String... excludeFieldNamesParam) { 764 if (excludeFieldNamesParam == null) { 765 this.excludeFieldNames = null; 766 } else { 767 // clone and remove nulls 768 this.excludeFieldNames = ArraySorter.sort(toNoNullStringArray(excludeFieldNamesParam)); 769 } 770 return this; 771 } 772 773 /** 774 * Sets whether or not to append fields whose values are null. 775 * 776 * @param excludeNullValues 777 * Whether or not to append fields whose values are null. 778 * @since 3.6 779 */ 780 public void setExcludeNullValues(final boolean excludeNullValues) { 781 this.excludeNullValues = excludeNullValues; 782 } 783 784 /** 785 * Sets the field names to include. {@code null} or empty means all fields are included. All fields are included by default. This method will override the default behavior. 786 * 787 * @param includeFieldNamesParam 788 * The includeFieldNames that must be on toString or {@code null}. 789 * @return {@code this} 790 * @since 3.13.0 791 */ 792 public ReflectionToStringBuilder setIncludeFieldNames(final String... includeFieldNamesParam) { 793 if (includeFieldNamesParam == null) { 794 this.includeFieldNames = null; 795 } else { 796 // clone and remove nulls 797 this.includeFieldNames = ArraySorter.sort(toNoNullStringArray(includeFieldNamesParam)); 798 } 799 return this; 800 } 801 802 /** 803 * Sets the last super class to stop appending fields for. 804 * 805 * @param clazz 806 * The last super class to stop appending fields for. 807 */ 808 public void setUpToClass(final Class<?> clazz) { 809 if (clazz != null) { 810 final Object object = getObject(); 811 if (object != null && !clazz.isInstance(object)) { 812 throw new IllegalArgumentException("Specified class is not a superclass of the object"); 813 } 814 } 815 this.upToClass = clazz; 816 } 817 818 /** 819 * Gets the String built by this builder. 820 * 821 * @return The built string 822 */ 823 @Override 824 public String toString() { 825 if (getObject() == null) { 826 return getStyle().getNullText(); 827 } 828 829 validate(); 830 831 Class<?> clazz = getObject().getClass(); 832 appendFieldsIn(clazz); 833 while (clazz.getSuperclass() != null && clazz != getUpToClass()) { 834 clazz = clazz.getSuperclass(); 835 appendFieldsIn(clazz); 836 } 837 return super.toString(); 838 } 839 840 /** 841 * Validates that include and exclude names do not intersect. 842 */ 843 private void validate() { 844 if (ArrayUtils.containsAny(this.excludeFieldNames, (Object[]) this.includeFieldNames)) { 845 ToStringStyle.unregister(getObject()); 846 throw new IllegalStateException("includeFieldNames and excludeFieldNames must not intersect"); 847 } 848 } 849 850}