001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      https://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.lang3.reflect;
018
019import java.lang.annotation.Annotation;
020import java.lang.reflect.AccessibleObject;
021import java.lang.reflect.Field;
022import java.lang.reflect.Modifier;
023import java.util.ArrayList;
024import java.util.Collections;
025import java.util.List;
026import java.util.Objects;
027import java.util.stream.Collectors;
028
029import org.apache.commons.lang3.ArrayUtils;
030import org.apache.commons.lang3.ClassUtils;
031import org.apache.commons.lang3.JavaVersion;
032import org.apache.commons.lang3.StringUtils;
033import org.apache.commons.lang3.SystemUtils;
034import org.apache.commons.lang3.Validate;
035
036/**
037 * Utilities for working with {@link Field}s by reflection. Adapted and refactored from the dormant [reflect] Commons
038 * sandbox component.
039 * <p>
040 * The ability is provided to break the scoping restrictions coded by the programmer. This can allow fields to be
041 * changed that shouldn't be. This facility should be used with care.
042 * </p>
043 *
044 * @since 2.5
045 */
046public class FieldUtils {
047
048    /**
049     * Gets all fields of the given class and its parents (if any).
050     *
051     * @param cls
052     *            the {@link Class} to query
053     * @return An array of Fields (possibly empty).
054     * @throws NullPointerException
055     *             Thrown if the class is {@code null}.
056     * @since 3.2
057     */
058    public static Field[] getAllFields(final Class<?> cls) {
059        return getAllFieldsList(cls).toArray(ArrayUtils.EMPTY_FIELD_ARRAY);
060    }
061
062    /**
063     * Gets all fields of the given class and its parents (if any).
064     *
065     * @param cls
066     *            the {@link Class} to query
067     * @return A list of Fields (possibly empty).
068     * @throws NullPointerException
069     *             Thrown if the class is {@code null}.
070     * @since 3.2
071     */
072    public static List<Field> getAllFieldsList(final Class<?> cls) {
073        Objects.requireNonNull(cls, "cls");
074        final List<Field> allFields = new ArrayList<>();
075        Class<?> currentClass = cls;
076        while (currentClass != null) {
077            Collections.addAll(allFields, currentClass.getDeclaredFields());
078            currentClass = currentClass.getSuperclass();
079        }
080        return allFields;
081    }
082
083    /**
084     * Gets an accessible {@link Field} by name respecting scope. Only the specified class will be considered.
085     *
086     * @param cls
087     *            the {@link Class} to reflect, must not be {@code null}
088     * @param fieldName
089     *            the field name to obtain.
090     * @return The Field object.
091     * @throws NullPointerException
092     *             Thrown if the class is {@code null}.
093     * @throws IllegalArgumentException
094     *             Thrown if the field name is {@code null}, blank, or empty.
095     * @throws SecurityException Thrown if an underlying accessible object's method denies the request.
096     * @see SecurityManager#checkPermission
097     */
098    public static Field getDeclaredField(final Class<?> cls, final String fieldName) {
099        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}