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 }