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