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 }