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