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