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    *      https://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.Field;
21  import java.lang.reflect.Modifier;
22  import java.util.Arrays;
23  import java.util.Collection;
24  import java.util.Comparator;
25  import java.util.Objects;
26  
27  import org.apache.commons.lang3.ArraySorter;
28  import org.apache.commons.lang3.ArrayUtils;
29  import org.apache.commons.lang3.ClassUtils;
30  import org.apache.commons.lang3.stream.Streams;
31  
32  /**
33   * Assists in implementing {@link Object#toString()} methods using reflection.
34   *
35   * <p>
36   * This class uses reflection to determine the fields to append. Because these fields are usually private, the class
37   * uses {@link java.lang.reflect.AccessibleObject#setAccessible(java.lang.reflect.AccessibleObject[], boolean)} to
38   * change the visibility of the fields. This will fail under a security manager, unless the appropriate permissions are
39   * set up correctly.
40   * </p>
41   * <p>
42   * Using reflection to access (private) fields circumvents any synchronization protection guarding access to these
43   * fields. If a toString method cannot safely read a field, you should exclude it from the toString method, or use
44   * synchronization consistent with the class' lock management around the invocation of the method. Take special care to
45   * exclude non-thread-safe collection classes, because these classes may throw ConcurrentModificationException if
46   * modified while the toString method is executing.
47   * </p>
48   * <p>
49   * A typical invocation for this method would look like:
50   * </p>
51   * <pre>
52   * public String toString() {
53   *     return ReflectionToStringBuilder.toString(this);
54   * }
55   * </pre>
56   * <p>
57   * You can also use the builder to debug 3rd party objects:
58   * </p>
59   * <pre>
60   * System.out.println(&quot;An object: &quot; + ReflectionToStringBuilder.toString(anObject));
61   * </pre>
62   * <p>
63   * A subclass can control field output by overriding the methods:
64   * </p>
65   * <ul>
66   * <li>{@link #accept(java.lang.reflect.Field)}</li>
67   * <li>{@link #getValue(java.lang.reflect.Field)}</li>
68   * </ul>
69   * <p>
70   * For example, this method does <em>not</em> include the {@code password} field in the returned {@link String}:
71   * </p>
72   * <pre>
73   * public String toString() {
74   *     return (new ReflectionToStringBuilder(this) {
75   *         protected boolean accept(Field f) {
76   *             return super.accept(f) &amp;&amp; !f.getName().equals(&quot;password&quot;);
77   *         }
78   *     }).toString();
79   * }
80   * </pre>
81   * <p>
82   * Alternatively the {@link ToStringExclude} annotation can be used to exclude fields from being incorporated in the
83   * result.
84   * </p>
85   * <p>
86   * It is also possible to use the {@link ToStringSummary} annotation to output the summary information instead of the
87   * detailed information of a field.
88   * </p>
89   * <p>
90   * The exact format of the {@code toString} is determined by the {@link ToStringStyle} passed into the constructor.
91   * </p>
92   *
93   * <p>
94   * <strong>Note:</strong> the default {@link ToStringStyle} will only do a "shallow" formatting, i.e. composed objects are not
95   * further traversed. To get "deep" formatting, use an instance of {@link RecursiveToStringStyle}.
96   * </p>
97   *
98   * @since 2.0
99   */
100 public 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 &quot;toString()'ed&quot;, 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 }