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  package org.apache.commons.lang3.reflect;
18  
19  import java.lang.annotation.Annotation;
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.Collections;
25  import java.util.List;
26  import java.util.Objects;
27  import java.util.stream.Collectors;
28  
29  import org.apache.commons.lang3.ArrayUtils;
30  import org.apache.commons.lang3.ClassUtils;
31  import org.apache.commons.lang3.JavaVersion;
32  import org.apache.commons.lang3.StringUtils;
33  import org.apache.commons.lang3.SystemUtils;
34  import org.apache.commons.lang3.Validate;
35  
36  /**
37   * Utilities for working with {@link Field}s by reflection. Adapted and refactored from the dormant [reflect] Commons
38   * sandbox component.
39   * <p>
40   * The ability is provided to break the scoping restrictions coded by the programmer. This can allow fields to be
41   * changed that shouldn't be. This facility should be used with care.
42   * </p>
43   * @since 2.5
44   */
45  public class FieldUtils {
46  
47      /**
48       * Gets all fields of the given class and its parents (if any).
49       *
50       * @param cls
51       *            the {@link Class} to query
52       * @return an array of Fields (possibly empty).
53       * @throws NullPointerException
54       *             if the class is {@code null}.
55       * @since 3.2
56       */
57      public static Field[] getAllFields(final Class<?> cls) {
58          return getAllFieldsList(cls).toArray(ArrayUtils.EMPTY_FIELD_ARRAY);
59      }
60  
61      /**
62       * Gets all fields of the given class and its parents (if any).
63       *
64       * @param cls
65       *            the {@link Class} to query
66       * @return a list of Fields (possibly empty).
67       * @throws NullPointerException
68       *             if the class is {@code null}.
69       * @since 3.2
70       */
71      public static List<Field> getAllFieldsList(final Class<?> cls) {
72          Objects.requireNonNull(cls, "cls");
73          final List<Field> allFields = new ArrayList<>();
74          Class<?> currentClass = cls;
75          while (currentClass != null) {
76              Collections.addAll(allFields, currentClass.getDeclaredFields());
77              currentClass = currentClass.getSuperclass();
78          }
79          return allFields;
80      }
81  
82      /**
83       * Gets an accessible {@link Field} by name respecting scope. Only the specified class will be considered.
84       *
85       * @param cls
86       *            the {@link Class} to reflect, must not be {@code null}
87       * @param fieldName
88       *            the field name to obtain.
89       * @return the Field object.
90       * @throws NullPointerException
91       *             if the class is {@code null}.
92       * @throws IllegalArgumentException
93       *             if the field name is {@code null}, blank, or empty.
94       * @throws SecurityException if an underlying accessible object's method denies the request.
95       * @see SecurityManager#checkPermission
96       */
97      public static Field getDeclaredField(final Class<?> cls, final String fieldName) {
98          return getDeclaredField(cls, fieldName, false);
99      }
100 
101     /**
102      * Gets an accessible {@link Field} by name, breaking scope if requested. Only the specified class will be
103      * considered.
104      *
105      * @param cls
106      *            the {@link Class} to reflect, must not be {@code null}.
107      * @param fieldName
108      *            the field name to obtain.
109      * @param forceAccess
110      *            whether to break scope restrictions using the
111      *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
112      *            match {@code public} fields.
113      * @return the Field object
114      * @throws NullPointerException
115      *             if the class is {@code null}.
116      * @throws IllegalArgumentException
117      *             if the field name is {@code null}, blank, or empty.
118      * @throws SecurityException if an underlying accessible object's method denies the request.
119      * @see SecurityManager#checkPermission
120      */
121     public static Field getDeclaredField(final Class<?> cls, final String fieldName, final boolean forceAccess) {
122         Objects.requireNonNull(cls, "cls");
123         Validate.isTrue(StringUtils.isNotBlank(fieldName), "The field name must not be blank/empty");
124         try {
125             // only consider the specified class by using getDeclaredField()
126             final Field field = cls.getDeclaredField(fieldName);
127             if (!MemberUtils.isAccessible(field)) {
128                 if (!forceAccess) {
129                     return null;
130                 }
131                 field.setAccessible(true);
132             }
133             return field;
134         } catch (final NoSuchFieldException ignored) {
135             // ignore
136         }
137         return null;
138     }
139 
140     /**
141      * Gets an accessible {@link Field} by name respecting scope. Superclasses/interfaces will be considered.
142      *
143      * @param cls
144      *            the {@link Class} to reflect, must not be {@code null}.
145      * @param fieldName
146      *            the field name to obtain.
147      * @return the Field object.
148      * @throws NullPointerException
149      *             if the class is {@code null}.
150      * @throws IllegalArgumentException
151      *             if the field name is {@code null}, blank, or empty
152      * @throws SecurityException if an underlying accessible object's method denies the request.
153      * @see SecurityManager#checkPermission
154      */
155     public static Field getField(final Class<?> cls, final String fieldName) {
156         return MemberUtils.setAccessibleWorkaround(getField(cls, fieldName, false));
157     }
158 
159     /**
160      * Gets an accessible {@link Field} by name, breaking scope if requested. Superclasses/interfaces will be
161      * considered.
162      *
163      * @param cls
164      *            the {@link Class} to reflect, must not be {@code null}.
165      * @param fieldName
166      *            the field name to obtain.
167      * @param forceAccess
168      *            whether to break scope restrictions using the
169      *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
170      *            match {@code public} fields.
171      * @return the Field object.
172      * @throws NullPointerException if the class is {@code null}.
173      * @throws IllegalArgumentException if the field name is blank or empty or is matched at multiple places
174      * in the inheritance hierarchy.
175      * @throws SecurityException if an underlying accessible object's method denies the request.
176      * @see SecurityManager#checkPermission
177      */
178     public static Field getField(final Class<?> cls, final String fieldName, final boolean forceAccess) {
179         Objects.requireNonNull(cls, "cls");
180         Validate.isTrue(StringUtils.isNotBlank(fieldName), "The field name must not be blank/empty");
181         // FIXME is this workaround still needed? lang requires Java 6
182         // Sun Java 1.3 has a bugged implementation of getField hence we write the
183         // code ourselves
184 
185         // getField() will return the Field object with the declaring class
186         // set correctly to the class that declares the field. Thus requesting the
187         // field on a subclass will return the field from the superclass.
188         //
189         // priority order for lookup:
190         // searchclass private/protected/package/public
191         // superclass protected/package/public
192         // private/different package blocks access to further superclasses
193         // implementedinterface public
194 
195         // check up the superclass hierarchy
196         for (Class<?> acls = cls; acls != null; acls = acls.getSuperclass()) {
197             try {
198                 final Field field = acls.getDeclaredField(fieldName);
199                 // getDeclaredField checks for non-public scopes as well
200                 // and it returns accurate results
201                 if (!MemberUtils.isPublic(field)) {
202                     if (!forceAccess) {
203                         continue;
204                     }
205                     field.setAccessible(true);
206                 }
207                 return field;
208             } catch (final NoSuchFieldException ignored) {
209                 // ignore
210             }
211         }
212         // check the public interface case. This must be manually searched for
213         // incase there is a public supersuperclass field hidden by a private/package
214         // superclass field.
215         Field match = null;
216         for (final Class<?> class1 : ClassUtils.getAllInterfaces(cls)) {
217             try {
218                 final Field test = class1.getField(fieldName);
219                 Validate.isTrue(match == null,
220                         "Reference to field %s is ambiguous relative to %s; a matching field exists on two or more implemented interfaces.", fieldName, cls);
221                 match = test;
222             } catch (final NoSuchFieldException ignored) {
223                 // ignore
224             }
225         }
226         return match;
227     }
228 
229     /**
230      * Gets all fields of the given class and its parents (if any) that are annotated with the given annotation.
231      * @param cls
232      *            the {@link Class} to query.
233      * @param annotationCls
234      *            the {@link Annotation} that must be present on a field to be matched.
235      * @return a list of Fields (possibly empty).
236      * @throws NullPointerException
237      *            if the class or annotation are {@code null}.
238      * @since 3.4
239      */
240     public static List<Field> getFieldsListWithAnnotation(final Class<?> cls, final Class<? extends Annotation> annotationCls) {
241         Objects.requireNonNull(annotationCls, "annotationCls");
242         return getAllFieldsList(cls).stream().filter(field -> field.getAnnotation(annotationCls) != null).collect(Collectors.toList());
243     }
244 
245     /**
246      * Gets all fields of the given class and its parents (if any) that are annotated with the given annotation.
247      * @param cls
248      *            the {@link Class} to query.
249      * @param annotationCls
250      *            the {@link Annotation} that must be present on a field to be matched
251      * @return an array of Fields (possibly empty).
252      * @throws NullPointerException
253      *            if the class or annotation are {@code null}.
254      * @since 3.4
255      */
256     public static Field[] getFieldsWithAnnotation(final Class<?> cls, final Class<? extends Annotation> annotationCls) {
257         return getFieldsListWithAnnotation(cls, annotationCls).toArray(ArrayUtils.EMPTY_FIELD_ARRAY);
258     }
259 
260     /**
261      * Reads the named {@code public} {@link Field}. Only the class of the specified object will be considered.
262      *
263      * @param target
264      *            the object to reflect, must not be {@code null}.
265      * @param fieldName
266      *            the field name to obtain.
267      * @return the value of the field.
268      * @throws NullPointerException
269      *             if {@code target} is {@code null}.
270      * @throws IllegalArgumentException
271      *             if {@code fieldName} is {@code null}, blank or empty, or could not be found.
272      * @throws IllegalAccessException
273      *             if the named field is not {@code public}
274      * @throws SecurityException if an underlying accessible object's method denies the request.
275      * @see SecurityManager#checkPermission
276      */
277     public static Object readDeclaredField(final Object target, final String fieldName) throws IllegalAccessException {
278         return readDeclaredField(target, fieldName, false);
279     }
280 
281     /**
282      * Gets a {@link Field} value by name. Only the class of the specified object will be considered.
283      *
284      * @param target
285      *            the object to reflect, must not be {@code null}.
286      * @param fieldName
287      *            the field name to obtain.
288      * @param forceAccess
289      *            whether to break scope restrictions using the
290      *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
291      *            match public fields.
292      * @return the Field object.
293      * @throws NullPointerException
294      *             if {@code target} is {@code null}.
295      * @throws IllegalArgumentException
296      *             if {@code fieldName} is {@code null}, blank or empty, or could not be found.
297      * @throws IllegalAccessException
298      *             if the field is not made accessible.
299      * @throws SecurityException if an underlying accessible object's method denies the request.
300      * @see SecurityManager#checkPermission
301      */
302     public static Object readDeclaredField(final Object target, final String fieldName, final boolean forceAccess) throws IllegalAccessException {
303         Objects.requireNonNull(target, "target");
304         final Class<?> cls = target.getClass();
305         final Field field = getDeclaredField(cls, fieldName, forceAccess);
306         Validate.isTrue(field != null, "Cannot locate declared field %s.%s", cls, fieldName);
307         // already forced access above, don't repeat it here:
308         return readField(field, target, false);
309     }
310 
311     /**
312      * Gets the value of a {@code static} {@link Field} by name. The field must be {@code public}. Only the specified
313      * class will be considered.
314      *
315      * @param cls
316      *            the {@link Class} to reflect, must not be {@code null}.
317      * @param fieldName
318      *            the field name to obtain.
319      * @return the value of the field.
320      * @throws NullPointerException
321      *             if the class is {@code null}, or the field could not be found.
322      * @throws IllegalArgumentException
323      *             if the field name is {@code null}, blank, empty, or is not {@code static}.
324      * @throws IllegalAccessException
325      *             if the field is not accessible
326      * @throws SecurityException if an underlying accessible object's method denies the request.
327      * @see SecurityManager#checkPermission
328      */
329     public static Object readDeclaredStaticField(final Class<?> cls, final String fieldName) throws IllegalAccessException {
330         return readDeclaredStaticField(cls, fieldName, false);
331     }
332 
333     /**
334      * Gets the value of a {@code static} {@link Field} by name. Only the specified class will be considered.
335      *
336      * @param cls
337      *            the {@link Class} to reflect, must not be {@code null}.
338      * @param fieldName
339      *            the field name to obtain.
340      * @param forceAccess
341      *            whether to break scope restrictions using the
342      *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
343      *            match {@code public} fields.
344      * @return the Field object
345      * @throws NullPointerException
346      *             if the class is {@code null}, or the field could not be found.
347      * @throws IllegalArgumentException
348      *             if the field name is blank or empty, is not {@code static}.
349      * @throws IllegalAccessException
350      *             if the field is not made accessible
351      * @throws SecurityException if an underlying accessible object's method denies the request.
352      * @see SecurityManager#checkPermission
353      */
354     public static Object readDeclaredStaticField(final Class<?> cls, final String fieldName, final boolean forceAccess) throws IllegalAccessException {
355         final Field field = getDeclaredField(cls, fieldName, forceAccess);
356         Validate.notNull(field, "Cannot locate declared field %s.%s", cls.getName(), fieldName);
357         // already forced access above, don't repeat it here:
358         return readStaticField(field, false);
359     }
360 
361     /**
362      * Reads an accessible {@link Field}.
363      *
364      * @param field
365      *            the field to use.
366      * @param target
367      *            the object to call on, may be {@code null} for {@code static} fields.
368      * @return the field value
369      * @throws NullPointerException
370      *             if the field is {@code null}.
371      * @throws IllegalAccessException
372      *             if the field is not accessible.
373      * @throws SecurityException if an underlying accessible object's method denies the request.
374      * @see SecurityManager#checkPermission
375      */
376     public static Object readField(final Field field, final Object target) throws IllegalAccessException {
377         return readField(field, target, false);
378     }
379 
380     /**
381      * Reads a {@link Field}.
382      *
383      * @param field
384      *            the field to use.
385      * @param target
386      *            the object to call on, may be {@code null} for {@code static} fields.
387      * @param forceAccess
388      *            whether to break scope restrictions using the
389      *            {@link AccessibleObject#setAccessible(boolean)} method.
390      * @return the field value
391      * @throws NullPointerException
392      *             if the field is {@code null}.
393      * @throws IllegalAccessException
394      *             if the field is not made accessible.
395      * @throws SecurityException if an underlying accessible object's method denies the request.
396      * @see SecurityManager#checkPermission
397      * @throws SecurityException if an underlying accessible object's method denies the request.
398      * @see SecurityManager#checkPermission
399      */
400     public static Object readField(final Field field, final Object target, final boolean forceAccess) throws IllegalAccessException {
401         Objects.requireNonNull(field, "field");
402         return setAccessible(field, forceAccess).get(target);
403     }
404 
405     /**
406      * Reads the named {@code public} {@link Field}. Superclasses will be considered.
407      *
408      * @param target
409      *            the object to reflect, must not be {@code null}.
410      * @param fieldName
411      *            the field name to obtain.
412      * @return the value of the field.
413      * @throws NullPointerException
414      *             if the target is {@code null}.
415      * @throws IllegalArgumentException
416      *             if the field name is {@code null}, blank, empty, or could not be found.
417      * @throws IllegalAccessException
418      *             if the named field is not {@code public}.
419      * @throws SecurityException if an underlying accessible object's method denies the request.
420      * @see SecurityManager#checkPermission
421      */
422     public static Object readField(final Object target, final String fieldName) throws IllegalAccessException {
423         return readField(target, fieldName, false);
424     }
425 
426     /**
427      * Reads the named {@link Field}. Superclasses will be considered.
428      *
429      * @param target
430      *            the object to reflect, must not be {@code null}.
431      * @param fieldName
432      *            the field name to obtain.
433      * @param forceAccess
434      *            whether to break scope restrictions using the
435      *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
436      *            match {@code public} fields.
437      * @return the field value
438      * @throws NullPointerException
439      *             if {@code target} is {@code null}.
440      * @throws IllegalArgumentException
441      *             if the field name is {@code null}, blank, empty, or could not be found.
442      * @throws IllegalAccessException
443      *             if the named field is not made accessible.
444      * @throws SecurityException if an underlying accessible object's method denies the request.
445      * @see SecurityManager#checkPermission
446      */
447     public static Object readField(final Object target, final String fieldName, final boolean forceAccess) throws IllegalAccessException {
448         Objects.requireNonNull(target, "target");
449         final Class<?> cls = target.getClass();
450         final Field field = getField(cls, fieldName, forceAccess);
451         Validate.isTrue(field != null, "Cannot locate field %s on %s", fieldName, cls);
452         // already forced access above, don't repeat it here:
453         return readField(field, target, false);
454     }
455 
456     /**
457      * Reads the named {@code public static} {@link Field}. Superclasses will be considered.
458      *
459      * @param cls
460      *            the {@link Class} to reflect, must not be {@code null}.
461      * @param fieldName
462      *            the field name to obtain.
463      * @return the value of the field.
464      * @throws NullPointerException
465      *             if the class is {@code null}, or the field could not be found.
466      * @throws IllegalArgumentException
467      *             if the field name is {@code null}, blank or empty, or is not {@code static}.
468      * @throws IllegalAccessException
469      *             if the field is not accessible.
470      * @throws SecurityException if an underlying accessible object's method denies the request.
471      * @see SecurityManager#checkPermission
472      */
473     public static Object readStaticField(final Class<?> cls, final String fieldName) throws IllegalAccessException {
474         return readStaticField(cls, fieldName, false);
475     }
476 
477     /**
478      * Reads the named {@code static} {@link Field}. Superclasses will be considered.
479      *
480      * @param cls
481      *            the {@link Class} to reflect, must not be {@code null}.
482      * @param fieldName
483      *            the field name to obtain.
484      * @param forceAccess
485      *            whether to break scope restrictions using the
486      *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
487      *            match {@code public} fields.
488      * @return the Field object.
489      * @throws NullPointerException
490      *             if the class is {@code null}, or the field could not be found.
491      * @throws IllegalArgumentException
492      *             if the field name is {@code null}, blank or empty, or is not {@code static}.
493      * @throws IllegalAccessException
494      *             if the field is not made accessible.
495      * @throws SecurityException if an underlying accessible object's method denies the request.
496      * @see SecurityManager#checkPermission
497      */
498     public static Object readStaticField(final Class<?> cls, final String fieldName, final boolean forceAccess) throws IllegalAccessException {
499         final Field field = getField(cls, fieldName, forceAccess);
500         Validate.notNull(field, "Cannot locate field '%s' on %s", fieldName, cls);
501         // already forced access above, don't repeat it here:
502         return readStaticField(field, false);
503     }
504 
505     /**
506      * Reads an accessible {@code static} {@link Field}.
507      *
508      * @param field
509      *            to read.
510      * @return the field value.
511      * @throws NullPointerException
512      *             if the field is {@code null}.
513      * @throws IllegalArgumentException
514      *             if the field is not {@code static}.
515      * @throws IllegalAccessException
516      *             if the field is not accessible
517      * @throws SecurityException if an underlying accessible object's method denies the request.
518      * @see SecurityManager#checkPermission
519      */
520     public static Object readStaticField(final Field field) throws IllegalAccessException {
521         return readStaticField(field, false);
522     }
523 
524     /**
525      * Reads a static {@link Field}.
526      *
527      * @param field
528      *            to read.
529      * @param forceAccess
530      *            whether to break scope restrictions using the
531      *            {@link AccessibleObject#setAccessible(boolean)} method.
532      * @return the field value.
533      * @throws NullPointerException
534      *             if the field is {@code null}.
535      * @throws IllegalArgumentException
536      *             if the field is not {@code static}.
537      * @throws IllegalAccessException
538      *             if the field is not made accessible.
539      * @throws SecurityException if an underlying accessible object's method denies the request.
540      * @see SecurityManager#checkPermission
541      */
542     public static Object readStaticField(final Field field, final boolean forceAccess) throws IllegalAccessException {
543         Objects.requireNonNull(field, "field");
544         Validate.isTrue(MemberUtils.isStatic(field), "The field '%s' is not static", field.getName());
545         return readField(field, (Object) null, forceAccess);
546     }
547 
548     /**
549      * Removes the final modifier from a {@link Field}.
550      *
551      * @param field
552      *            to remove the final modifier.
553      * @throws NullPointerException
554      *             if the field is {@code null}.
555      * @throws SecurityException if an underlying accessible object's method denies the request.
556      * @see SecurityManager#checkPermission
557      * @since 3.2
558      */
559     public static void removeFinalModifier(final Field field) {
560         removeFinalModifier(field, true);
561     }
562 
563     /**
564      * Removes the final modifier from a {@link Field}.
565      *
566      * @param field
567      *            to remove the final modifier.
568      * @param forceAccess
569      *            whether to break scope restrictions using the
570      *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
571      *            match {@code public} fields.
572      * @throws NullPointerException
573      *             if the field is {@code null}.
574      * @throws SecurityException if an underlying accessible object's method denies the request.
575      * @see SecurityManager#checkPermission
576      * @deprecated As of Java 12, we can no longer drop the {@code final} modifier, thus
577      *             rendering this method obsolete. The JDK discussion about this change can be found
578      *             here: https://mail.openjdk.java.net/pipermail/core-libs-dev/2018-November/056486.html
579      * @since 3.3
580      */
581     @Deprecated
582     public static void removeFinalModifier(final Field field, final boolean forceAccess) {
583         Objects.requireNonNull(field, "field");
584         try {
585             if (Modifier.isFinal(field.getModifiers())) {
586                 // Do all JREs implement Field with a private ivar called "modifiers"?
587                 final Field modifiersField = Field.class.getDeclaredField("modifiers");
588                 final boolean doForceAccess = forceAccess && !modifiersField.isAccessible();
589                 if (doForceAccess) {
590                     modifiersField.setAccessible(true);
591                 }
592                 try {
593                     modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
594                 } finally {
595                     if (doForceAccess) {
596                         modifiersField.setAccessible(false);
597                     }
598                 }
599             }
600         } catch (final NoSuchFieldException | IllegalAccessException e) {
601             if (SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_12)) {
602                 throw new UnsupportedOperationException("In java 12+ final cannot be removed.", e);
603             }
604             // else no exception is thrown because we can modify final.
605         }
606     }
607 
608     static Field setAccessible(final Field field, final boolean forceAccess) {
609         if (forceAccess && !field.isAccessible()) {
610             field.setAccessible(true);
611         } else {
612             MemberUtils.setAccessibleWorkaround(field);
613         }
614         return field;
615     }
616 
617     /**
618      * Writes a {@code public} {@link Field}. Only the specified class will be considered.
619      *
620      * @param target
621      *            the object to reflect, must not be {@code null}.
622      * @param fieldName
623      *            the field name to obtain.
624      * @param value
625      *            the new value.
626      * @throws NullPointerException
627      *             if {@code target} is {@code null}.
628      * @throws IllegalArgumentException
629      *             if {@code fieldName} is {@code null}, blank or empty, or could not be found,
630      *             or {@code value} is not assignable.
631      * @throws IllegalAccessException
632      *             if the field is not made accessible
633      * @throws SecurityException if an underlying accessible object's method denies the request.
634      * @see SecurityManager#checkPermission
635      */
636     public static void writeDeclaredField(final Object target, final String fieldName, final Object value) throws IllegalAccessException {
637         writeDeclaredField(target, fieldName, value, false);
638     }
639 
640     /**
641      * Writes a {@code public} {@link Field}. Only the specified class will be considered.
642      *
643      * @param target
644      *            the object to reflect, must not be {@code null}.
645      * @param fieldName
646      *            the field name to obtain.
647      * @param value
648      *            the new value.
649      * @param forceAccess
650      *            whether to break scope restrictions using the
651      *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
652      *            match {@code public} fields.
653      * @throws IllegalArgumentException
654      *             if {@code fieldName} is {@code null}, blank or empty, or could not be found,
655      *             or {@code value} is not assignable
656      * @throws IllegalAccessException
657      *             if the field is not made accessible
658      * @throws SecurityException if an underlying accessible object's method denies the request.
659      * @see SecurityManager#checkPermission
660      */
661     public static void writeDeclaredField(final Object target, final String fieldName, final Object value, final boolean forceAccess)
662             throws IllegalAccessException {
663         Objects.requireNonNull(target, "target");
664         final Class<?> cls = target.getClass();
665         final Field field = getDeclaredField(cls, fieldName, forceAccess);
666         Validate.isTrue(field != null, "Cannot locate declared field %s.%s", cls.getName(), fieldName);
667         // already forced access above, don't repeat it here:
668         writeField(field, target, value, false);
669     }
670 
671     /**
672      * Writes a named {@code public static} {@link Field}. Only the specified class will be considered.
673      *
674      * @param cls
675      *            {@link Class} on which the field is to be found.
676      * @param fieldName
677      *            to write.
678      * @param value
679      *            the new value.
680      * @throws NullPointerException
681      *             if {@code cls} is {@code null} or the field cannot be located.
682      * @throws IllegalArgumentException
683      *             if the field name is {@code null}, blank, empty, not {@code static}, or {@code value} is not assignable.
684      * @throws IllegalAccessException
685      *             if the field is not {@code public} or is {@code final}
686      * @throws SecurityException if an underlying accessible object's method denies the request.
687      * @see SecurityManager#checkPermission
688      */
689     public static void writeDeclaredStaticField(final Class<?> cls, final String fieldName, final Object value) throws IllegalAccessException {
690         writeDeclaredStaticField(cls, fieldName, value, false);
691     }
692 
693     /**
694      * Writes a named {@code static} {@link Field}. Only the specified class will be considered.
695      *
696      * @param cls
697      *            {@link Class} on which the field is to be found.
698      * @param fieldName
699      *            to write
700      * @param value
701      *            the new value.
702      * @param forceAccess
703      *            whether to break scope restrictions using the {@code AccessibleObject#setAccessible(boolean)} method.
704      *            {@code false} will only match {@code public} fields.
705      * @throws NullPointerException
706      *             if {@code cls} is {@code null} or the field cannot be located.
707      * @throws IllegalArgumentException
708      *             if the field name is {@code null}, blank, empty, not {@code static}, or {@code value} is not assignable.
709      * @throws IllegalAccessException
710      *             if the field is not made accessible or is {@code final}
711      * @throws SecurityException if an underlying accessible object's method denies the request.
712      * @see SecurityManager#checkPermission
713      */
714     public static void writeDeclaredStaticField(final Class<?> cls, final String fieldName, final Object value, final boolean forceAccess)
715             throws IllegalAccessException {
716         final Field field = getDeclaredField(cls, fieldName, forceAccess);
717         Validate.notNull(field, "Cannot locate declared field %s.%s", cls.getName(), fieldName);
718         // already forced access above, don't repeat it here:
719         writeField(field, (Object) null, value, false);
720     }
721 
722     /**
723      * Writes an accessible {@link Field}.
724      *
725      * @param field
726      *            to write.
727      * @param target
728      *            the object to call on, may be {@code null} for {@code static} fields.
729      * @param value
730      *            the new value.
731      * @throws NullPointerException
732      *             if the field is {@code null}.
733      * @throws IllegalArgumentException
734      *             if {@code value} is not assignable.
735      * @throws IllegalAccessException
736      *             if the field is not accessible or is {@code final}.
737      * @throws SecurityException if an underlying accessible object's method denies the request.
738      * @see SecurityManager#checkPermission
739      */
740     public static void writeField(final Field field, final Object target, final Object value) throws IllegalAccessException {
741         writeField(field, target, value, false);
742     }
743 
744     /**
745      * Writes a {@link Field}.
746      *
747      * @param field
748      *            to write.
749      * @param target
750      *            the object to call on, may be {@code null} for {@code static} fields
751      * @param value
752      *            the new value.
753      * @param forceAccess
754      *            whether to break scope restrictions using the
755      *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
756      *            match {@code public} fields.
757      * @throws NullPointerException
758      *             if the field is {@code null}.
759      * @throws IllegalArgumentException
760      *             if {@code value} is not assignable.
761      * @throws IllegalAccessException
762      *             if the field is not made accessible or is {@code final}
763      * @throws SecurityException if an underlying accessible object's method denies the request.
764      * @see SecurityManager#checkPermission
765      */
766     public static void writeField(final Field field, final Object target, final Object value, final boolean forceAccess)
767             throws IllegalAccessException {
768         Objects.requireNonNull(field, "field");
769         setAccessible(field, forceAccess).set(target, value);
770     }
771 
772     /**
773      * Writes a {@code public} {@link Field}. Superclasses will be considered.
774      *
775      * @param target
776      *            the object to reflect, must not be {@code null}.
777      * @param fieldName
778      *            the field name to obtain.
779      * @param value
780      *            the new value.
781      * @throws NullPointerException
782      *             if {@code target} is {@code null}.
783      * @throws IllegalArgumentException
784      *             if {@code fieldName} is {@code null}, blank, empty, or could not be found,
785      *             or {@code value} is not assignable.
786      * @throws IllegalAccessException
787      *             if the field is not accessible.
788      * @throws SecurityException if an underlying accessible object's method denies the request.
789      * @see SecurityManager#checkPermission
790      */
791     public static void writeField(final Object target, final String fieldName, final Object value) throws IllegalAccessException {
792         writeField(target, fieldName, value, false);
793     }
794 
795     /**
796      * Writes a {@link Field}. Superclasses will be considered.
797      *
798      * @param target
799      *            the object to reflect, must not be {@code null}.
800      * @param fieldName
801      *            the field name to obtain.
802      * @param value
803      *            the new value.
804      * @param forceAccess
805      *            whether to break scope restrictions using the
806      *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
807      *            match {@code public} fields.
808      * @throws NullPointerException
809      *             if {@code target} is {@code null}.
810      * @throws IllegalArgumentException
811      *             if {@code fieldName} is {@code null}, blank, empty, or could not be found,
812      *             or {@code value} is not assignable.
813      * @throws IllegalAccessException
814      *             if the field is not made accessible.
815      * @throws SecurityException if an underlying accessible object's method denies the request.
816      * @see SecurityManager#checkPermission
817      */
818     public static void writeField(final Object target, final String fieldName, final Object value, final boolean forceAccess)
819             throws IllegalAccessException {
820         Objects.requireNonNull(target, "target");
821         final Class<?> cls = target.getClass();
822         final Field field = getField(cls, fieldName, forceAccess);
823         Validate.isTrue(field != null, "Cannot locate declared field %s.%s", cls.getName(), fieldName);
824         // already forced access above, don't repeat it here:
825         writeField(field, target, value, false);
826     }
827 
828     /**
829      * Writes a named {@code public static} {@link Field}. Superclasses will be considered.
830      *
831      * @param cls
832      *            {@link Class} on which the field is to be found.
833      * @param fieldName
834      *            to write.
835      * @param value
836      *            the new value.
837      * @throws NullPointerException
838      *             if {@code target} is {@code null}.
839      * @throws IllegalArgumentException
840      *             if {@code fieldName} is {@code null}, blank or empty, the field cannot be located or is
841      *             not {@code static}, or {@code value} is not assignable.
842      * @throws IllegalAccessException
843      *             if the field is not {@code public} or is {@code final}
844      * @throws SecurityException if an underlying accessible object's method denies the request.
845      * @see SecurityManager#checkPermission
846      */
847     public static void writeStaticField(final Class<?> cls, final String fieldName, final Object value) throws IllegalAccessException {
848         writeStaticField(cls, fieldName, value, false);
849     }
850 
851     /**
852      * Writes a named {@code static} {@link Field}. Superclasses will be considered.
853      *
854      * @param cls
855      *            {@link Class} on which the field is to be found.
856      * @param fieldName
857      *            to write.
858      * @param value
859      *            the new value.
860      * @param forceAccess
861      *            whether to break scope restrictions using the
862      *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
863      *            match {@code public} fields.
864      * @throws NullPointerException
865      *             if {@code cls} is {@code null} or the field cannot be located.
866      * @throws IllegalArgumentException
867      *             if {@code fieldName} is {@code null}, blank or empty, the field not {@code static}, or {@code value} is not assignable.
868      * @throws IllegalAccessException
869      *             if the field is not made accessible or is {@code final}.
870      * @throws SecurityException if an underlying accessible object's method denies the request.
871      * @see SecurityManager#checkPermission
872      */
873     public static void writeStaticField(final Class<?> cls, final String fieldName, final Object value, final boolean forceAccess)
874             throws IllegalAccessException {
875         final Field field = getField(cls, fieldName, forceAccess);
876         Validate.notNull(field, "Cannot locate field %s on %s", fieldName, cls);
877         // already forced access above, don't repeat it here:
878         writeStaticField(field, value, false);
879     }
880 
881     /**
882      * Writes a {@code public static} {@link Field}.
883      *
884      * @param field
885      *            to write.
886      * @param value
887      *            the new value.
888      * @throws NullPointerException
889      *              if the field is {@code null}.
890      * @throws IllegalArgumentException
891      *              if the field is not {@code static}, or {@code value} is not assignable.
892      * @throws IllegalAccessException
893      *             if the field is not {@code public} or is {@code final}.
894      * @throws SecurityException if an underlying accessible object's method denies the request.
895      * @see SecurityManager#checkPermission
896      */
897     public static void writeStaticField(final Field field, final Object value) throws IllegalAccessException {
898         writeStaticField(field, value, false);
899     }
900 
901     /**
902      * Writes a static {@link Field}.
903      *
904      * @param field
905      *            to write.
906      * @param value
907      *            the new value.
908      * @param forceAccess
909      *            whether to break scope restrictions using the
910      *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
911      *            match {@code public} fields.
912      * @throws NullPointerException
913      *              if the field is {@code null}.
914      * @throws IllegalArgumentException
915      *              if the field is not {@code static}, or {@code value} is not assignable.
916      * @throws IllegalAccessException
917      *             if the field is not made accessible or is {@code final}
918      * @throws SecurityException if an underlying accessible object's method denies the request.
919      * @see SecurityManager#checkPermission
920      */
921     public static void writeStaticField(final Field field, final Object value, final boolean forceAccess) throws IllegalAccessException {
922         Objects.requireNonNull(field, "field");
923         Validate.isTrue(MemberUtils.isStatic(field), "The field %s.%s is not static", field.getDeclaringClass().getName(),
924                 field.getName());
925         writeField(field, (Object) null, value, forceAccess);
926     }
927 
928     /**
929      * {@link FieldUtils} instances should NOT be constructed in standard programming.
930      * <p>
931      * This constructor is {@code public} to permit tools that require a JavaBean instance to operate.
932      * </p>
933      *
934      * @deprecated TODO Make private in 4.0.
935      */
936     @Deprecated
937     public FieldUtils() {
938         // empty
939     }
940 }