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 <i>not</i> 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      * {@code java.lang.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      * {@code java.lang.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     /**
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      *            {@code null} or empty means all fields are included. All fields are included by default. This method will override the default behavior.
424      * @return The toString value.
425      * @since 3.13.0
426      */
427     public static String toStringInclude(final Object object, final Collection<String> includeFieldNames) {
428         return toStringInclude(object, toNoNullStringArray(includeFieldNames));
429     }
430 
431     /**
432      * Builds a String for a toString method including the given field names.
433      *
434      * @param object
435      *            The object to "toString".
436      * @param includeFieldNames
437      *            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
438      *             behavior.
439      * @return The toString value.
440      * @since 3.13.0
441      */
442     public static String toStringInclude(final Object object, final String... includeFieldNames) {
443         return new ReflectionToStringBuilder(object).setIncludeFieldNames(includeFieldNames).toString();
444     }
445 
446     /**
447      * Whether or not to append static fields.
448      */
449     private boolean appendStatics;
450 
451     /**
452      * Whether or not to append transient fields.
453      */
454     private boolean appendTransients;
455 
456     /**
457      * Whether or not to append fields that are null.
458      */
459     private boolean excludeNullValues;
460 
461     /**
462      * Which field names to exclude from output. Intended for fields like {@code "password"}.
463      *
464      * @since 3.0 this is protected instead of private
465      */
466     protected String[] excludeFieldNames;
467 
468     /**
469      * Field names that will be included in the output. All fields are included by default.
470      *
471      * @since 3.13.0
472      */
473     protected String[] includeFieldNames;
474 
475     /**
476      * The last super class to stop appending fields for.
477      */
478     private Class<?> upToClass;
479 
480     /**
481      * Constructs a new instance.
482      *
483      * <p>
484      * This constructor outputs using the default style set with {@code setDefaultStyle}.
485      * </p>
486      *
487      * @param object
488      *            the Object to build a {@code toString} for, must not be {@code null}
489      */
490     public ReflectionToStringBuilder(final Object object) {
491         super(object);
492     }
493 
494     /**
495      * Constructs a new instance.
496      *
497      * <p>
498      * If the style is {@code null}, the default style is used.
499      * </p>
500      *
501      * @param object
502      *            the Object to build a {@code toString} for, must not be {@code null}
503      * @param style
504      *            the style of the {@code toString} to create, may be {@code null}
505      */
506     public ReflectionToStringBuilder(final Object object, final ToStringStyle style) {
507         super(object, style);
508     }
509 
510     /**
511      * Constructs a new instance.
512      *
513      * <p>
514      * If the style is {@code null}, the default style is used.
515      * </p>
516      *
517      * <p>
518      * If the buffer is {@code null}, a new one is created.
519      * </p>
520      *
521      * @param object
522      *            the Object to build a {@code toString} for
523      * @param style
524      *            the style of the {@code toString} to create, may be {@code null}
525      * @param buffer
526      *            the {@link StringBuffer} to populate, may be {@code null}
527      */
528     public ReflectionToStringBuilder(final Object object, final ToStringStyle style, final StringBuffer buffer) {
529         super(object, style, buffer);
530     }
531 
532     /**
533      * Constructs a new instance.
534      *
535      * @param <T>
536      *            the type of the object
537      * @param object
538      *            the Object to build a {@code toString} for
539      * @param style
540      *            the style of the {@code toString} to create, may be {@code null}
541      * @param buffer
542      *            the {@link StringBuffer} to populate, may be {@code null}
543      * @param reflectUpToClass
544      *            the superclass to reflect up to (inclusive), may be {@code null}
545      * @param outputTransients
546      *            whether to include transient fields
547      * @param outputStatics
548      *            whether to include static fields
549      * @since 2.1
550      */
551     public <T> ReflectionToStringBuilder(
552             final T object, final ToStringStyle style, final StringBuffer buffer,
553             final Class<? super T> reflectUpToClass, final boolean outputTransients, final boolean outputStatics) {
554         super(object, style, buffer);
555         this.setUpToClass(reflectUpToClass);
556         this.setAppendTransients(outputTransients);
557         this.setAppendStatics(outputStatics);
558     }
559 
560     /**
561      * Constructs a new instance.
562      *
563      * @param <T>
564      *            the type of the object
565      * @param object
566      *            the Object to build a {@code toString} for
567      * @param style
568      *            the style of the {@code toString} to create, may be {@code null}
569      * @param buffer
570      *            the {@link StringBuffer} to populate, may be {@code null}
571      * @param reflectUpToClass
572      *            the superclass to reflect up to (inclusive), may be {@code null}
573      * @param outputTransients
574      *            whether to include transient fields
575      * @param outputStatics
576      *            whether to include static fields
577      * @param excludeNullValues
578      *            whether to exclude fields who value is null
579      * @since 3.6
580      */
581     public <T> ReflectionToStringBuilder(
582             final T object, final ToStringStyle style, final StringBuffer buffer,
583             final Class<? super T> reflectUpToClass, final boolean outputTransients, final boolean outputStatics,
584             final boolean excludeNullValues) {
585         super(object, style, buffer);
586         this.setUpToClass(reflectUpToClass);
587         this.setAppendTransients(outputTransients);
588         this.setAppendStatics(outputStatics);
589         this.setExcludeNullValues(excludeNullValues);
590     }
591 
592     /**
593      * Returns whether or not to append the given {@link Field}.
594      * <ul>
595      * <li>Transient fields are appended only if {@link #isAppendTransients()} returns {@code true}.
596      * <li>Static fields are appended only if {@link #isAppendStatics()} returns {@code true}.
597      * <li>Inner class fields are not appended.</li>
598      * </ul>
599      *
600      * @param field
601      *            The Field to test.
602      * @return Whether or not to append the given {@link Field}.
603      */
604     protected boolean accept(final Field field) {
605         if (field.getName().indexOf(ClassUtils.INNER_CLASS_SEPARATOR_CHAR) != -1) {
606             // Reject field from inner class.
607             return false;
608         }
609         if (Modifier.isTransient(field.getModifiers()) && !this.isAppendTransients()) {
610             // Reject transient fields.
611             return false;
612         }
613         if (Modifier.isStatic(field.getModifiers()) && !this.isAppendStatics()) {
614             // Reject static fields.
615             return false;
616         }
617 
618         if (this.excludeFieldNames != null
619             && Arrays.binarySearch(this.excludeFieldNames, field.getName()) >= 0) {
620             // Reject fields from the getExcludeFieldNames list.
621             return false;
622         }
623 
624         if (ArrayUtils.isNotEmpty(includeFieldNames)) {
625             // Accept fields from the getIncludeFieldNames list. {@code null} or empty means all fields are included. All fields are included by default.
626             return Arrays.binarySearch(this.includeFieldNames, field.getName()) >= 0;
627         }
628 
629         return !field.isAnnotationPresent(ToStringExclude.class);
630     }
631 
632     /**
633      * Appends the fields and values defined by the given object of the given Class.
634      *
635      * <p>
636      * If a cycle is detected as an object is &quot;toString()'ed&quot;, such an object is rendered as if
637      * {@code Object.toString()} had been called and not implemented by the object.
638      * </p>
639      *
640      * @param clazz
641      *            The class of object parameter
642      */
643     protected void appendFieldsIn(final Class<?> clazz) {
644         if (clazz.isArray()) {
645             this.reflectionAppendArray(this.getObject());
646             return;
647         }
648         // The elements in the returned array are not sorted and are not in any particular order.
649         final Field[] fields = ArraySorter.sort(clazz.getDeclaredFields(), Comparator.comparing(Field::getName));
650         AccessibleObject.setAccessible(fields, true);
651         for (final Field field : fields) {
652             final String fieldName = field.getName();
653             if (this.accept(field)) {
654                 try {
655                     // Warning: Field.get(Object) creates wrappers objects
656                     // for primitive types.
657                     final Object fieldValue = this.getValue(field);
658                     if (!excludeNullValues || fieldValue != null) {
659                         this.append(fieldName, fieldValue, !field.isAnnotationPresent(ToStringSummary.class));
660                     }
661                 } catch (final IllegalAccessException e) {
662                     // this can't happen. Would get a Security exception instead throw a runtime exception in case the
663                     // impossible happens.
664                     throw new IllegalStateException(e);
665                 }
666             }
667         }
668     }
669 
670     /**
671      * Gets the excludeFieldNames.
672      *
673      * @return the excludeFieldNames.
674      */
675     public String[] getExcludeFieldNames() {
676         return this.excludeFieldNames.clone();
677     }
678 
679     /**
680      * Gets the includeFieldNames
681      *
682      * @return the includeFieldNames.
683      * @since 3.13.0
684      */
685     public String[] getIncludeFieldNames() {
686         return this.includeFieldNames.clone();
687     }
688 
689     /**
690      * Gets the last super class to stop appending fields for.
691      *
692      * @return The last super class to stop appending fields for.
693      */
694     public Class<?> getUpToClass() {
695         return this.upToClass;
696     }
697 
698     /**
699      * Calls {@code java.lang.reflect.Field.get(Object)}.
700      *
701      * @param field
702      *            The Field to query.
703      * @return The Object from the given Field.
704      *
705      * @throws IllegalArgumentException
706      *             see {@link java.lang.reflect.Field#get(Object)}
707      * @throws IllegalAccessException
708      *             see {@link java.lang.reflect.Field#get(Object)}
709      *
710      * @see java.lang.reflect.Field#get(Object)
711      */
712     protected Object getValue(final Field field) throws IllegalAccessException {
713         return field.get(this.getObject());
714     }
715 
716     /**
717      * Gets whether or not to append static fields.
718      *
719      * @return Whether or not to append static fields.
720      * @since 2.1
721      */
722     public boolean isAppendStatics() {
723         return this.appendStatics;
724     }
725 
726     /**
727      * Gets whether or not to append transient fields.
728      *
729      * @return Whether or not to append transient fields.
730      */
731     public boolean isAppendTransients() {
732         return this.appendTransients;
733     }
734 
735     /**
736      * Gets whether or not to append fields whose values are null.
737      *
738      * @return Whether or not to append fields whose values are null.
739      * @since 3.6
740      */
741     public boolean isExcludeNullValues() {
742         return this.excludeNullValues;
743     }
744 
745     /**
746      * Appends to the {@code toString} an {@link Object} array.
747      *
748      * @param array
749      *            the array to add to the {@code toString}
750      * @return this
751      */
752     public ReflectionToStringBuilder reflectionAppendArray(final Object array) {
753         this.getStyle().reflectionAppendArrayDetail(this.getStringBuffer(), null, array);
754         return this;
755     }
756 
757     /**
758      * Sets whether or not to append static fields.
759      *
760      * @param appendStatics
761      *            Whether or not to append static fields.
762      * @since 2.1
763      */
764     public void setAppendStatics(final boolean appendStatics) {
765         this.appendStatics = appendStatics;
766     }
767 
768     /**
769      * Sets whether or not to append transient fields.
770      *
771      * @param appendTransients
772      *            Whether or not to append transient fields.
773      */
774     public void setAppendTransients(final boolean appendTransients) {
775         this.appendTransients = appendTransients;
776     }
777 
778     /**
779      * Sets the field names to exclude.
780      *
781      * @param excludeFieldNamesParam
782      *            The excludeFieldNames to excluding from toString or {@code null}.
783      * @return {@code this}
784      */
785     public ReflectionToStringBuilder setExcludeFieldNames(final String... excludeFieldNamesParam) {
786         if (excludeFieldNamesParam == null) {
787             this.excludeFieldNames = null;
788         } else {
789             // clone and remove nulls
790             this.excludeFieldNames = ArraySorter.sort(toNoNullStringArray(excludeFieldNamesParam));
791         }
792         return this;
793     }
794 
795     /**
796      * Sets whether or not to append fields whose values are null.
797      *
798      * @param excludeNullValues
799      *            Whether or not to append fields whose values are null.
800      * @since 3.6
801      */
802     public void setExcludeNullValues(final boolean excludeNullValues) {
803         this.excludeNullValues = excludeNullValues;
804     }
805 
806     /**
807      * 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.
808      *
809      * @param includeFieldNamesParam
810      *            The includeFieldNames that must be on toString or {@code null}.
811      * @return {@code this}
812      * @since 3.13.0
813      */
814     public ReflectionToStringBuilder setIncludeFieldNames(final String... includeFieldNamesParam) {
815         if (includeFieldNamesParam == null) {
816             this.includeFieldNames = null;
817         } else {
818             // clone and remove nulls
819             this.includeFieldNames = ArraySorter.sort(toNoNullStringArray(includeFieldNamesParam));
820         }
821         return this;
822     }
823 
824     /**
825      * Sets the last super class to stop appending fields for.
826      *
827      * @param clazz
828      *            The last super class to stop appending fields for.
829      */
830     public void setUpToClass(final Class<?> clazz) {
831         if (clazz != null) {
832             final Object object = getObject();
833             if (object != null && !clazz.isInstance(object)) {
834                 throw new IllegalArgumentException("Specified class is not a superclass of the object");
835             }
836         }
837         this.upToClass = clazz;
838     }
839 
840     /**
841      * Gets the String built by this builder.
842      *
843      * @return the built string
844      */
845     @Override
846     public String toString() {
847         if (this.getObject() == null) {
848             return this.getStyle().getNullText();
849         }
850 
851         validate();
852 
853         Class<?> clazz = this.getObject().getClass();
854         this.appendFieldsIn(clazz);
855         while (clazz.getSuperclass() != null && clazz != this.getUpToClass()) {
856             clazz = clazz.getSuperclass();
857             this.appendFieldsIn(clazz);
858         }
859         return super.toString();
860     }
861 
862     /**
863      * Validates that include and exclude names do not intersect.
864      */
865     private void validate() {
866         if (ArrayUtils.containsAny(this.excludeFieldNames, (Object[]) this.includeFieldNames)) {
867             ToStringStyle.unregister(this.getObject());
868             throw new IllegalStateException("includeFieldNames and excludeFieldNames must not intersect");
869         }
870     }
871 
872 }