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   *
44   * @since 2.5
45   */
46  public class FieldUtils {
47  
48      /**
49       * Gets all fields of the given class and its parents (if any).
50       *
51       * @param cls
52       *            the {@link Class} to query
53       * @return An array of Fields (possibly empty).
54       * @throws NullPointerException
55       *             Thrown if the class is {@code null}.
56       * @since 3.2
57       */
58      public static Field[] getAllFields(final Class<?> cls) {
59          return getAllFieldsList(cls).toArray(ArrayUtils.EMPTY_FIELD_ARRAY);
60      }
61  
62      /**
63       * Gets all fields of the given class and its parents (if any).
64       *
65       * @param cls
66       *            the {@link Class} to query
67       * @return A list of Fields (possibly empty).
68       * @throws NullPointerException
69       *             Thrown if the class is {@code null}.
70       * @since 3.2
71       */
72      public static List<Field> getAllFieldsList(final Class<?> cls) {
73          Objects.requireNonNull(cls, "cls");
74          final List<Field> allFields = new ArrayList<>();
75          Class<?> currentClass = cls;
76          while (currentClass != null) {
77              Collections.addAll(allFields, currentClass.getDeclaredFields());
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       *             Thrown if the class is {@code null}.
93       * @throws IllegalArgumentException
94       *             Thrown if the field name is {@code null}, blank, or empty.
95       * @throws SecurityException Thrown 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      *             Thrown if the class is {@code null}.
117      * @throws IllegalArgumentException
118      *             Thrown if the field name is {@code null}, blank, or empty.
119      * @throws SecurityException Thrown 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      *             Thrown if the class is {@code null}.
151      * @throws IllegalArgumentException Thrown if the field name is {@code null}, blank, or empty.
152      * @throws SecurityException Thrown 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 Thrown if the class is {@code null}.
173      * @throws IllegalArgumentException Thrown if the field name is blank or empty or is matched at multiple places
174      * in the inheritance hierarchy.
175      * @throws SecurityException Thrown 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         // in case 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 || match.equals(test),
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      *
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      *            Thrown 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      *
249      * @param cls
250      *            the {@link Class} to query.
251      * @param annotationCls
252      *            the {@link Annotation} that must be present on a field to be matched
253      * @return An array of Fields (possibly empty).
254      * @throws NullPointerException
255      *            Thrown if the class or annotation are {@code null}.
256      * @since 3.4
257      */
258     public static Field[] getFieldsWithAnnotation(final Class<?> cls, final Class<? extends Annotation> annotationCls) {
259         return getFieldsListWithAnnotation(cls, annotationCls).toArray(ArrayUtils.EMPTY_FIELD_ARRAY);
260     }
261 
262     /**
263      * Reads the named {@code public} {@link Field}. Only the class of the specified object will be considered.
264      *
265      * @param target
266      *            the object to reflect, must not be {@code null}.
267      * @param fieldName
268      *            the field name to obtain.
269      * @return The value of the field.
270      * @throws NullPointerException
271      *             Thrown if {@code target} is {@code null}.
272      * @throws IllegalArgumentException
273      *             Thrown if {@code fieldName} is {@code null}, blank or empty, or could not be found.
274      * @throws IllegalAccessException Thrown if the named field is not {@code public}.
275      * @throws SecurityException Thrown 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      *             Thrown if {@code target} is {@code null}.
296      * @throws IllegalArgumentException
297      *             Thrown if {@code fieldName} is {@code null}, blank or empty, or could not be found.
298      * @throws IllegalAccessException
299      *             Thrown if the field is not made accessible.
300      * @throws SecurityException Thrown 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      *             Thrown if the class is {@code null}, or the field could not be found.
323      * @throws IllegalArgumentException
324      *             Thrown if the field name is {@code null}, blank, empty, or is not {@code static}.
325      * @throws IllegalAccessException Thrown if the field is not accessible.
326      * @throws SecurityException Thrown 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      *             Thrown if the class is {@code null}, or the field could not be found.
347      * @throws IllegalArgumentException
348      *             Thrown if the field name is blank or empty, is not {@code static}.
349      * @throws IllegalAccessException Thrown if the field is not made accessible.
350      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
351      * @see SecurityManager#checkPermission
352      */
353     public static Object readDeclaredStaticField(final Class<?> cls, final String fieldName, final boolean forceAccess) throws IllegalAccessException {
354         final Field field = getDeclaredField(cls, fieldName, forceAccess);
355         Validate.notNull(field, "Cannot locate declared field %s.%s", cls.getName(), fieldName);
356         // already forced access above, don't repeat it here:
357         return readStaticField(field, false);
358     }
359 
360     /**
361      * Reads an accessible {@link Field}.
362      *
363      * @param field
364      *            the field to use.
365      * @param target
366      *            the object to call on, may be {@code null} for {@code static} fields.
367      * @return The field value
368      * @throws NullPointerException
369      *             Thrown if the field is {@code null}.
370      * @throws IllegalAccessException
371      *             Thrown if the field is not accessible.
372      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
373      * @see SecurityManager#checkPermission
374      */
375     public static Object readField(final Field field, final Object target) throws IllegalAccessException {
376         return readField(field, target, false);
377     }
378 
379     /**
380      * Reads a {@link Field}.
381      *
382      * @param field
383      *            the field to use.
384      * @param target
385      *            the object to call on, may be {@code null} for {@code static} fields.
386      * @param forceAccess
387      *            whether to break scope restrictions using the
388      *            {@link AccessibleObject#setAccessible(boolean)} method.
389      * @return The field value
390      * @throws NullPointerException
391      *             Thrown if the field is {@code null}.
392      * @throws IllegalAccessException
393      *             Thrown if the field is not made accessible.
394      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
395      * @see SecurityManager#checkPermission
396      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
397      * @see SecurityManager#checkPermission
398      */
399     public static Object readField(final Field field, final Object target, final boolean forceAccess) throws IllegalAccessException {
400         Objects.requireNonNull(field, "field");
401         return setAccessible(field, forceAccess).get(target);
402     }
403 
404     /**
405      * Reads the named {@code public} {@link Field}. Superclasses will be considered.
406      *
407      * @param target
408      *            the object to reflect, must not be {@code null}.
409      * @param fieldName
410      *            the field name to obtain.
411      * @return The value of the field.
412      * @throws NullPointerException
413      *             Thrown if the target is {@code null}.
414      * @throws IllegalArgumentException
415      *             Thrown if the field name is {@code null}, blank, empty, or could not be found.
416      * @throws IllegalAccessException
417      *             Thrown if the named field is not {@code public}.
418      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
419      * @see SecurityManager#checkPermission
420      */
421     public static Object readField(final Object target, final String fieldName) throws IllegalAccessException {
422         return readField(target, fieldName, false);
423     }
424 
425     /**
426      * Reads the named {@link Field}. Superclasses will be considered.
427      *
428      * @param target
429      *            the object to reflect, must not be {@code null}.
430      * @param fieldName
431      *            the field name to obtain.
432      * @param forceAccess
433      *            whether to break scope restrictions using the
434      *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
435      *            match {@code public} fields.
436      * @return The field value
437      * @throws NullPointerException
438      *             Thrown if {@code target} is {@code null}.
439      * @throws IllegalArgumentException
440      *             Thrown if the field name is {@code null}, blank, empty, or could not be found.
441      * @throws IllegalAccessException
442      *             Thrown if the named field is not made accessible.
443      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
444      * @see SecurityManager#checkPermission
445      */
446     public static Object readField(final Object target, final String fieldName, final boolean forceAccess) throws IllegalAccessException {
447         Objects.requireNonNull(target, "target");
448         final Class<?> cls = target.getClass();
449         final Field field = getField(cls, fieldName, forceAccess);
450         Validate.isTrue(field != null, "Cannot locate field %s on %s", fieldName, cls);
451         // already forced access above, don't repeat it here:
452         return readField(field, target, false);
453     }
454 
455     /**
456      * Reads the named {@code public static} {@link Field}. Superclasses will be considered.
457      *
458      * @param cls
459      *            the {@link Class} to reflect, must not be {@code null}.
460      * @param fieldName
461      *            the field name to obtain.
462      * @return The value of the field.
463      * @throws NullPointerException
464      *             Thrown if the class is {@code null}, or the field could not be found.
465      * @throws IllegalArgumentException
466      *             Thrown if the field name is {@code null}, blank or empty, or is not {@code static}.
467      * @throws IllegalAccessException
468      *             Thrown if the field is not accessible.
469      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
470      * @see SecurityManager#checkPermission
471      */
472     public static Object readStaticField(final Class<?> cls, final String fieldName) throws IllegalAccessException {
473         return readStaticField(cls, fieldName, false);
474     }
475 
476     /**
477      * Reads the named {@code static} {@link Field}. Superclasses will be considered.
478      *
479      * @param cls
480      *            the {@link Class} to reflect, must not be {@code null}.
481      * @param fieldName
482      *            the field name to obtain.
483      * @param forceAccess
484      *            whether to break scope restrictions using the
485      *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
486      *            match {@code public} fields.
487      * @return The Field object.
488      * @throws NullPointerException
489      *             Thrown if the class is {@code null}, or the field could not be found.
490      * @throws IllegalArgumentException
491      *             Thrown if the field name is {@code null}, blank or empty, or is not {@code static}.
492      * @throws IllegalAccessException
493      *             Thrown if the field is not made accessible.
494      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
495      * @see SecurityManager#checkPermission
496      */
497     public static Object readStaticField(final Class<?> cls, final String fieldName, final boolean forceAccess) throws IllegalAccessException {
498         final Field field = getField(cls, fieldName, forceAccess);
499         Validate.notNull(field, "Cannot locate field '%s' on %s", fieldName, cls);
500         // already forced access above, don't repeat it here:
501         return readStaticField(field, false);
502     }
503 
504     /**
505      * Reads an accessible {@code static} {@link Field}.
506      *
507      * @param field
508      *            to read.
509      * @return The field value.
510      * @throws NullPointerException
511      *             Thrown if the field is {@code null}.
512      * @throws IllegalArgumentException
513      *             Thrown if the field is not {@code static}.
514      * @throws IllegalAccessException Thrown if the field is not accessible.
515      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
516      * @see SecurityManager#checkPermission
517      */
518     public static Object readStaticField(final Field field) throws IllegalAccessException {
519         return readStaticField(field, false);
520     }
521 
522     /**
523      * Reads a static {@link Field}.
524      *
525      * @param field
526      *            to read.
527      * @param forceAccess
528      *            whether to break scope restrictions using the
529      *            {@link AccessibleObject#setAccessible(boolean)} method.
530      * @return The field value.
531      * @throws NullPointerException
532      *             Thrown if the field is {@code null}.
533      * @throws IllegalArgumentException
534      *             Thrown if the field is not {@code static}.
535      * @throws IllegalAccessException
536      *             Thrown if the field is not made accessible.
537      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
538      * @see SecurityManager#checkPermission
539      */
540     public static Object readStaticField(final Field field, final boolean forceAccess) throws IllegalAccessException {
541         Objects.requireNonNull(field, "field");
542         Validate.isTrue(MemberUtils.isStatic(field), "The field '%s' is not static", field.getName());
543         return readField(field, (Object) null, forceAccess);
544     }
545 
546     /**
547      * Removes the final modifier from a {@link Field}.
548      *
549      * @param field
550      *            to remove the final modifier.
551      * @throws NullPointerException
552      *             Thrown if the field is {@code null}.
553      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
554      * @see SecurityManager#checkPermission
555      * @since 3.2
556      */
557     public static void removeFinalModifier(final Field field) {
558         removeFinalModifier(field, true);
559     }
560 
561     /**
562      * Removes the final modifier from a {@link Field}.
563      *
564      * @param field
565      *            to remove the final modifier.
566      * @param forceAccess
567      *            whether to break scope restrictions using the
568      *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
569      *            match {@code public} fields.
570      * @throws NullPointerException
571      *             Thrown if the field is {@code null}.
572      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
573      * @see SecurityManager#checkPermission
574      * @since 3.3
575      * @deprecated As of Java 12, we can no longer drop the {@code final} modifier, thus
576      *             rendering this method obsolete. The JDK discussion about this change can be found
577      *             here: https://mail.openjdk.java.net/pipermail/core-libs-dev/2018-November/056486.html
578      */
579     @Deprecated
580     public static void removeFinalModifier(final Field field, final boolean forceAccess) {
581         Objects.requireNonNull(field, "field");
582         try {
583             if (Modifier.isFinal(field.getModifiers())) {
584                 // Do all JREs implement Field with a private ivar called "modifiers"?
585                 final Field modifiersField = Field.class.getDeclaredField("modifiers");
586                 final boolean doForceAccess = forceAccess && !modifiersField.isAccessible();
587                 if (doForceAccess) {
588                     modifiersField.setAccessible(true);
589                 }
590                 try {
591                     modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
592                 } finally {
593                     if (doForceAccess) {
594                         modifiersField.setAccessible(false);
595                     }
596                 }
597             }
598         } catch (final NoSuchFieldException | IllegalAccessException e) {
599             if (SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_12)) {
600                 throw new UnsupportedOperationException("In java 12+ final cannot be removed.", e);
601             }
602             // else no exception is thrown because we can modify final.
603         }
604     }
605 
606     static Field setAccessible(final Field field, final boolean forceAccess) {
607         if (forceAccess && !field.isAccessible()) {
608             field.setAccessible(true);
609         } else {
610             MemberUtils.setAccessibleWorkaround(field);
611         }
612         return field;
613     }
614 
615     /**
616      * Writes a {@code public} {@link Field}. Only the specified class will be considered.
617      *
618      * @param target
619      *            the object to reflect, must not be {@code null}.
620      * @param fieldName
621      *            the field name to obtain.
622      * @param value
623      *            the new value.
624      * @throws NullPointerException
625      *             Thrown if {@code target} is {@code null}.
626      * @throws IllegalArgumentException
627      *             Thrown if {@code fieldName} is {@code null}, blank or empty, or could not be found,
628      *             or {@code value} is not assignable.
629      * @throws IllegalAccessException Thrown if the field is not made accessible.
630      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
631      * @see SecurityManager#checkPermission
632      */
633     public static void writeDeclaredField(final Object target, final String fieldName, final Object value) throws IllegalAccessException {
634         writeDeclaredField(target, fieldName, value, false);
635     }
636 
637     /**
638      * Writes a {@code public} {@link Field}. Only the specified class will be considered.
639      *
640      * @param target
641      *            the object to reflect, must not be {@code null}.
642      * @param fieldName
643      *            the field name to obtain.
644      * @param value
645      *            the new value.
646      * @param forceAccess
647      *            whether to break scope restrictions using the
648      *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
649      *            match {@code public} fields.
650      * @throws IllegalArgumentException Thrown if {@code fieldName} is {@code null}, blank or empty, or could not be found, or {@code value} is not assignable.
651      * @throws IllegalAccessException Thrown if the field is not made accessible.
652      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
653      * @see SecurityManager#checkPermission
654      */
655     public static void writeDeclaredField(final Object target, final String fieldName, final Object value, final boolean forceAccess)
656             throws IllegalAccessException {
657         Objects.requireNonNull(target, "target");
658         final Class<?> cls = target.getClass();
659         final Field field = getDeclaredField(cls, fieldName, forceAccess);
660         Validate.isTrue(field != null, "Cannot locate declared field %s.%s", cls.getName(), fieldName);
661         // already forced access above, don't repeat it here:
662         writeField(field, target, value, false);
663     }
664 
665     /**
666      * Writes a named {@code public static} {@link Field}. Only the specified class will be considered.
667      *
668      * @param cls
669      *            {@link Class} on which the field is to be found.
670      * @param fieldName
671      *            to write.
672      * @param value
673      *            the new value.
674      * @throws NullPointerException
675      *             Thrown if {@code cls} is {@code null} or the field cannot be located.
676      * @throws IllegalArgumentException
677      *             Thrown if the field name is {@code null}, blank, empty, not {@code static}, or {@code value} is not assignable.
678      * @throws IllegalAccessException Thrown if the field is not {@code public} or is {@code final}.
679      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
680      * @see SecurityManager#checkPermission
681      */
682     public static void writeDeclaredStaticField(final Class<?> cls, final String fieldName, final Object value) throws IllegalAccessException {
683         writeDeclaredStaticField(cls, fieldName, value, false);
684     }
685 
686     /**
687      * Writes a named {@code static} {@link Field}. Only the specified class will be considered.
688      *
689      * @param cls
690      *            {@link Class} on which the field is to be found.
691      * @param fieldName
692      *            to write
693      * @param value
694      *            the new value.
695      * @param forceAccess
696      *            whether to break scope restrictions using the {@code AccessibleObject#setAccessible(boolean)} method.
697      *            {@code false} will only match {@code public} fields.
698      * @throws NullPointerException
699      *             Thrown if {@code cls} is {@code null} or the field cannot be located.
700      * @throws IllegalArgumentException
701      *             Thrown if the field name is {@code null}, blank, empty, not {@code static}, or {@code value} is not assignable.
702      * @throws IllegalAccessException Thrown if the field is not made accessible or is {@code final}.
703      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
704      * @see SecurityManager#checkPermission
705      */
706     public static void writeDeclaredStaticField(final Class<?> cls, final String fieldName, final Object value, final boolean forceAccess)
707             throws IllegalAccessException {
708         final Field field = getDeclaredField(cls, fieldName, forceAccess);
709         Validate.notNull(field, "Cannot locate declared field %s.%s", cls.getName(), fieldName);
710         // already forced access above, don't repeat it here:
711         writeField(field, (Object) null, value, false);
712     }
713 
714     /**
715      * Writes an accessible {@link Field}.
716      *
717      * @param field
718      *            to write.
719      * @param target
720      *            the object to call on, may be {@code null} for {@code static} fields.
721      * @param value
722      *            the new value.
723      * @throws NullPointerException
724      *             Thrown if the field is {@code null}.
725      * @throws IllegalArgumentException
726      *             Thrown if {@code value} is not assignable.
727      * @throws IllegalAccessException
728      *             Thrown if the field is not accessible or is {@code final}.
729      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
730      * @see SecurityManager#checkPermission
731      */
732     public static void writeField(final Field field, final Object target, final Object value) throws IllegalAccessException {
733         writeField(field, target, value, false);
734     }
735 
736     /**
737      * Writes a {@link Field}.
738      *
739      * @param field
740      *            to write.
741      * @param target
742      *            the object to call on, may be {@code null} for {@code static} fields
743      * @param value
744      *            the new value.
745      * @param forceAccess
746      *            whether to break scope restrictions using the
747      *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
748      *            match {@code public} fields.
749      * @throws NullPointerException
750      *             Thrown if the field is {@code null}.
751      * @throws IllegalArgumentException
752      *             Thrown if {@code value} is not assignable.
753      * @throws IllegalAccessException Thrown if the field is not made accessible or is {@code final}.
754      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
755      * @see SecurityManager#checkPermission
756      */
757     public static void writeField(final Field field, final Object target, final Object value, final boolean forceAccess)
758             throws IllegalAccessException {
759         Objects.requireNonNull(field, "field");
760         setAccessible(field, forceAccess).set(target, value);
761     }
762 
763     /**
764      * Writes a {@code public} {@link Field}. Superclasses will be considered.
765      *
766      * @param target
767      *            the object to reflect, must not be {@code null}.
768      * @param fieldName
769      *            the field name to obtain.
770      * @param value
771      *            the new value.
772      * @throws NullPointerException
773      *             Thrown if {@code target} is {@code null}.
774      * @throws IllegalArgumentException
775      *             Thrown if {@code fieldName} is {@code null}, blank, empty, or could not be found,
776      *             or {@code value} is not assignable.
777      * @throws IllegalAccessException
778      *             Thrown if the field is not accessible.
779      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
780      * @see SecurityManager#checkPermission
781      */
782     public static void writeField(final Object target, final String fieldName, final Object value) throws IllegalAccessException {
783         writeField(target, fieldName, value, false);
784     }
785 
786     /**
787      * Writes a {@link Field}. Superclasses will be considered.
788      *
789      * @param target
790      *            the object to reflect, must not be {@code null}.
791      * @param fieldName
792      *            the field name to obtain.
793      * @param value
794      *            the new value.
795      * @param forceAccess
796      *            whether to break scope restrictions using the
797      *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
798      *            match {@code public} fields.
799      * @throws NullPointerException
800      *             Thrown if {@code target} is {@code null}.
801      * @throws IllegalArgumentException
802      *             Thrown if {@code fieldName} is {@code null}, blank, empty, or could not be found,
803      *             or {@code value} is not assignable.
804      * @throws IllegalAccessException
805      *             Thrown if the field is not made accessible.
806      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
807      * @see SecurityManager#checkPermission
808      */
809     public static void writeField(final Object target, final String fieldName, final Object value, final boolean forceAccess)
810             throws IllegalAccessException {
811         Objects.requireNonNull(target, "target");
812         final Class<?> cls = target.getClass();
813         final Field field = getField(cls, fieldName, forceAccess);
814         Validate.isTrue(field != null, "Cannot locate declared field %s.%s", cls.getName(), fieldName);
815         // already forced access above, don't repeat it here:
816         writeField(field, target, value, false);
817     }
818 
819     /**
820      * Writes a named {@code public static} {@link Field}. Superclasses will be considered.
821      *
822      * @param cls
823      *            {@link Class} on which the field is to be found.
824      * @param fieldName
825      *            to write.
826      * @param value
827      *            the new value.
828      * @throws NullPointerException
829      *             Thrown if {@code target} is {@code null}.
830      * @throws IllegalArgumentException
831      *             Thrown if {@code fieldName} is {@code null}, blank or empty, the field cannot be located or is
832      *             not {@code static}, or {@code value} is not assignable.
833      * @throws IllegalAccessException Thrown if the field is not {@code public} or is {@code final}.
834      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
835      * @see SecurityManager#checkPermission
836      */
837     public static void writeStaticField(final Class<?> cls, final String fieldName, final Object value) throws IllegalAccessException {
838         writeStaticField(cls, fieldName, value, false);
839     }
840 
841     /**
842      * Writes a named {@code static} {@link Field}. Superclasses will be considered.
843      *
844      * @param cls
845      *            {@link Class} on which the field is to be found.
846      * @param fieldName
847      *            to write.
848      * @param value
849      *            the new value.
850      * @param forceAccess
851      *            whether to break scope restrictions using the
852      *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
853      *            match {@code public} fields.
854      * @throws NullPointerException
855      *             Thrown if {@code cls} is {@code null} or the field cannot be located.
856      * @throws IllegalArgumentException
857      *             Thrown if {@code fieldName} is {@code null}, blank or empty, the field not {@code static}, or {@code value} is not assignable.
858      * @throws IllegalAccessException
859      *             Thrown if the field is not made accessible or is {@code final}.
860      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
861      * @see SecurityManager#checkPermission
862      */
863     public static void writeStaticField(final Class<?> cls, final String fieldName, final Object value, final boolean forceAccess)
864             throws IllegalAccessException {
865         final Field field = getField(cls, fieldName, forceAccess);
866         Validate.notNull(field, "Cannot locate field %s on %s", fieldName, cls);
867         // already forced access above, don't repeat it here:
868         writeStaticField(field, value, false);
869     }
870 
871     /**
872      * Writes a {@code public static} {@link Field}.
873      *
874      * @param field
875      *            to write.
876      * @param value
877      *            the new value.
878      * @throws NullPointerException
879      *              Thrown if the field is {@code null}.
880      * @throws IllegalArgumentException
881      *              Thrown if the field is not {@code static}, or {@code value} is not assignable.
882      * @throws IllegalAccessException
883      *             Thrown if the field is not {@code public} or is {@code final}.
884      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
885      * @see SecurityManager#checkPermission
886      */
887     public static void writeStaticField(final Field field, final Object value) throws IllegalAccessException {
888         writeStaticField(field, value, false);
889     }
890 
891     /**
892      * Writes a static {@link Field}.
893      *
894      * @param field
895      *            to write.
896      * @param value
897      *            the new value.
898      * @param forceAccess
899      *            whether to break scope restrictions using the
900      *            {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only
901      *            match {@code public} fields.
902      * @throws NullPointerException
903      *              Thrown if the field is {@code null}.
904      * @throws IllegalArgumentException
905      *              Thrown if the field is not {@code static}, or {@code value} is not assignable.
906      * @throws IllegalAccessException Thrown if the field is not made accessible or is {@code final}.
907      * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
908      * @see SecurityManager#checkPermission
909      */
910     public static void writeStaticField(final Field field, final Object value, final boolean forceAccess) throws IllegalAccessException {
911         Objects.requireNonNull(field, "field");
912         Validate.isTrue(MemberUtils.isStatic(field), "The field %s.%s is not static", field.getDeclaringClass().getName(),
913                 field.getName());
914         writeField(field, (Object) null, value, forceAccess);
915     }
916 
917     /**
918      * {@link FieldUtils} instances should NOT be constructed in standard programming.
919      * <p>
920      * This constructor is {@code public} to permit tools that require a JavaBean instance to operate.
921      * </p>
922      *
923      * @deprecated TODO Make private in 4.0.
924      */
925     @Deprecated
926     public FieldUtils() {
927         // empty
928     }
929 }