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