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