001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * https://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.lang3.reflect; 018 019import java.lang.annotation.Annotation; 020import java.lang.reflect.AccessibleObject; 021import java.lang.reflect.Field; 022import java.lang.reflect.Modifier; 023import java.util.ArrayList; 024import java.util.Collections; 025import java.util.List; 026import java.util.Objects; 027import java.util.stream.Collectors; 028 029import org.apache.commons.lang3.ArrayUtils; 030import org.apache.commons.lang3.ClassUtils; 031import org.apache.commons.lang3.JavaVersion; 032import org.apache.commons.lang3.StringUtils; 033import org.apache.commons.lang3.SystemUtils; 034import org.apache.commons.lang3.Validate; 035 036/** 037 * Utilities for working with {@link Field}s by reflection. Adapted and refactored from the dormant [reflect] Commons 038 * sandbox component. 039 * <p> 040 * The ability is provided to break the scoping restrictions coded by the programmer. This can allow fields to be 041 * changed that shouldn't be. This facility should be used with care. 042 * </p> 043 * @since 2.5 044 */ 045public class FieldUtils { 046 047 /** 048 * Gets all fields of the given class and its parents (if any). 049 * 050 * @param cls 051 * the {@link Class} to query 052 * @return an array of Fields (possibly empty). 053 * @throws NullPointerException 054 * if the class is {@code null}. 055 * @since 3.2 056 */ 057 public static Field[] getAllFields(final Class<?> cls) { 058 return getAllFieldsList(cls).toArray(ArrayUtils.EMPTY_FIELD_ARRAY); 059 } 060 061 /** 062 * Gets all fields of the given class and its parents (if any). 063 * 064 * @param cls 065 * the {@link Class} to query 066 * @return a list of Fields (possibly empty). 067 * @throws NullPointerException 068 * if the class is {@code null}. 069 * @since 3.2 070 */ 071 public static List<Field> getAllFieldsList(final Class<?> cls) { 072 Objects.requireNonNull(cls, "cls"); 073 final List<Field> allFields = new ArrayList<>(); 074 Class<?> currentClass = cls; 075 while (currentClass != null) { 076 final Field[] declaredFields = currentClass.getDeclaredFields(); 077 Collections.addAll(allFields, declaredFields); 078 currentClass = currentClass.getSuperclass(); 079 } 080 return allFields; 081 } 082 083 /** 084 * Gets an accessible {@link Field} by name respecting scope. Only the specified class will be considered. 085 * 086 * @param cls 087 * the {@link Class} to reflect, must not be {@code null} 088 * @param fieldName 089 * the field name to obtain. 090 * @return the Field object. 091 * @throws NullPointerException 092 * if the class is {@code null}. 093 * @throws IllegalArgumentException 094 * if the field name is {@code null}, blank, or empty. 095 * @throws SecurityException if an underlying accessible object's method denies the request. 096 * @see SecurityManager#checkPermission 097 */ 098 public static Field getDeclaredField(final Class<?> cls, final String fieldName) { 099 return getDeclaredField(cls, fieldName, false); 100 } 101 102 /** 103 * Gets an accessible {@link Field} by name, breaking scope if requested. Only the specified class will be 104 * considered. 105 * 106 * @param cls 107 * the {@link Class} to reflect, must not be {@code null}. 108 * @param fieldName 109 * the field name to obtain. 110 * @param forceAccess 111 * whether to break scope restrictions using the 112 * {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only 113 * match {@code public} fields. 114 * @return the Field object 115 * @throws NullPointerException 116 * if the class is {@code null}. 117 * @throws IllegalArgumentException 118 * if the field name is {@code null}, blank, or empty. 119 * @throws SecurityException 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 * if the class is {@code null}. 151 * @throws IllegalArgumentException 152 * if the field name is {@code null}, blank, or empty 153 * @throws SecurityException if an underlying accessible object's method denies the request. 154 * @see SecurityManager#checkPermission 155 */ 156 public static Field getField(final Class<?> cls, final String fieldName) { 157 return MemberUtils.setAccessibleWorkaround(getField(cls, fieldName, false)); 158 } 159 160 /** 161 * Gets an accessible {@link Field} by name, breaking scope if requested. Superclasses/interfaces will be 162 * considered. 163 * 164 * @param cls 165 * the {@link Class} to reflect, must not be {@code null}. 166 * @param fieldName 167 * the field name to obtain. 168 * @param forceAccess 169 * whether to break scope restrictions using the 170 * {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only 171 * match {@code public} fields. 172 * @return the Field object. 173 * @throws NullPointerException if the class is {@code null}. 174 * @throws IllegalArgumentException if the field name is blank or empty or is matched at multiple places 175 * in the inheritance hierarchy. 176 * @throws SecurityException if an underlying accessible object's method denies the request. 177 * @see SecurityManager#checkPermission 178 */ 179 public static Field getField(final Class<?> cls, final String fieldName, final boolean forceAccess) { 180 Objects.requireNonNull(cls, "cls"); 181 Validate.isTrue(StringUtils.isNotBlank(fieldName), "The field name must not be blank/empty"); 182 // FIXME is this workaround still needed? lang requires Java 6 183 // Sun Java 1.3 has a bugged implementation of getField hence we write the 184 // code ourselves 185 186 // getField() will return the Field object with the declaring class 187 // set correctly to the class that declares the field. Thus requesting the 188 // field on a subclass will return the field from the superclass. 189 // 190 // priority order for lookup: 191 // searchclass private/protected/package/public 192 // superclass protected/package/public 193 // private/different package blocks access to further superclasses 194 // implementedinterface public 195 196 // check up the superclass hierarchy 197 for (Class<?> acls = cls; acls != null; acls = acls.getSuperclass()) { 198 try { 199 final Field field = acls.getDeclaredField(fieldName); 200 // getDeclaredField checks for non-public scopes as well 201 // and it returns accurate results 202 if (!MemberUtils.isPublic(field)) { 203 if (!forceAccess) { 204 continue; 205 } 206 field.setAccessible(true); 207 } 208 return field; 209 } catch (final NoSuchFieldException ignored) { 210 // ignore 211 } 212 } 213 // check the public interface case. This must be manually searched for 214 // incase there is a public supersuperclass field hidden by a private/package 215 // superclass field. 216 Field match = null; 217 for (final Class<?> class1 : ClassUtils.getAllInterfaces(cls)) { 218 try { 219 final Field test = class1.getField(fieldName); 220 Validate.isTrue(match == null, 221 "Reference to field %s is ambiguous relative to %s; a matching field exists on two or more implemented interfaces.", fieldName, cls); 222 match = test; 223 } catch (final NoSuchFieldException ignored) { 224 // ignore 225 } 226 } 227 return match; 228 } 229 230 /** 231 * Gets all fields of the given class and its parents (if any) that are annotated with the given annotation. 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 * 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 * @param cls 249 * the {@link Class} to query. 250 * @param annotationCls 251 * the {@link Annotation} that must be present on a field to be matched 252 * @return an array of Fields (possibly empty). 253 * @throws NullPointerException 254 * if the class or annotation are {@code null}. 255 * @since 3.4 256 */ 257 public static Field[] getFieldsWithAnnotation(final Class<?> cls, final Class<? extends Annotation> annotationCls) { 258 return getFieldsListWithAnnotation(cls, annotationCls).toArray(ArrayUtils.EMPTY_FIELD_ARRAY); 259 } 260 261 /** 262 * Reads the named {@code public} {@link Field}. Only the class of the specified object will be considered. 263 * 264 * @param target 265 * the object to reflect, must not be {@code null}. 266 * @param fieldName 267 * the field name to obtain. 268 * @return the value of the field. 269 * @throws NullPointerException 270 * if {@code target} is {@code null}. 271 * @throws IllegalArgumentException 272 * if {@code fieldName} is {@code null}, blank or empty, or could not be found. 273 * @throws IllegalAccessException 274 * if the named field is not {@code public} 275 * @throws SecurityException 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 * if {@code target} is {@code null}. 296 * @throws IllegalArgumentException 297 * if {@code fieldName} is {@code null}, blank or empty, or could not be found. 298 * @throws IllegalAccessException 299 * if the field is not made accessible. 300 * @throws SecurityException 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 * if the class is {@code null}, or the field could not be found. 323 * @throws IllegalArgumentException 324 * if the field name is {@code null}, blank, empty, or is not {@code static}. 325 * @throws IllegalAccessException 326 * if the field is not accessible 327 * @throws SecurityException if an underlying accessible object's method denies the request. 328 * @see SecurityManager#checkPermission 329 */ 330 public static Object readDeclaredStaticField(final Class<?> cls, final String fieldName) throws IllegalAccessException { 331 return readDeclaredStaticField(cls, fieldName, false); 332 } 333 334 /** 335 * Gets the value of a {@code static} {@link Field} by name. Only the specified class will be considered. 336 * 337 * @param cls 338 * the {@link Class} to reflect, must not be {@code null}. 339 * @param fieldName 340 * the field name to obtain. 341 * @param forceAccess 342 * whether to break scope restrictions using the 343 * {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only 344 * match {@code public} fields. 345 * @return the Field object 346 * @throws NullPointerException 347 * if the class is {@code null}, or the field could not be found. 348 * @throws IllegalArgumentException 349 * if the field name is blank or empty, is not {@code static}. 350 * @throws IllegalAccessException 351 * if the field is not made accessible 352 * @throws SecurityException if an underlying accessible object's method denies the request. 353 * @see SecurityManager#checkPermission 354 */ 355 public static Object readDeclaredStaticField(final Class<?> cls, final String fieldName, final boolean forceAccess) throws IllegalAccessException { 356 final Field field = getDeclaredField(cls, fieldName, forceAccess); 357 Validate.notNull(field, "Cannot locate declared field %s.%s", cls.getName(), fieldName); 358 // already forced access above, don't repeat it here: 359 return readStaticField(field, false); 360 } 361 362 /** 363 * Reads an accessible {@link Field}. 364 * 365 * @param field 366 * the field to use. 367 * @param target 368 * the object to call on, may be {@code null} for {@code static} fields. 369 * @return the field value 370 * @throws NullPointerException 371 * if the field is {@code null}. 372 * @throws IllegalAccessException 373 * if the field is not accessible. 374 * @throws SecurityException if an underlying accessible object's method denies the request. 375 * @see SecurityManager#checkPermission 376 */ 377 public static Object readField(final Field field, final Object target) throws IllegalAccessException { 378 return readField(field, target, false); 379 } 380 381 /** 382 * Reads a {@link Field}. 383 * 384 * @param field 385 * the field to use. 386 * @param target 387 * the object to call on, may be {@code null} for {@code static} fields. 388 * @param forceAccess 389 * whether to break scope restrictions using the 390 * {@link AccessibleObject#setAccessible(boolean)} method. 391 * @return the field value 392 * @throws NullPointerException 393 * if the field is {@code null}. 394 * @throws IllegalAccessException 395 * if the field is not made accessible. 396 * @throws SecurityException if an underlying accessible object's method denies the request. 397 * @see SecurityManager#checkPermission 398 * @throws SecurityException if an underlying accessible object's method denies the request. 399 * @see SecurityManager#checkPermission 400 */ 401 public static Object readField(final Field field, final Object target, final boolean forceAccess) throws IllegalAccessException { 402 Objects.requireNonNull(field, "field"); 403 if (forceAccess && !field.isAccessible()) { 404 field.setAccessible(true); 405 } else { 406 MemberUtils.setAccessibleWorkaround(field); 407 } 408 return field.get(target); 409 } 410 411 /** 412 * Reads the named {@code public} {@link Field}. Superclasses will be considered. 413 * 414 * @param target 415 * the object to reflect, must not be {@code null}. 416 * @param fieldName 417 * the field name to obtain. 418 * @return the value of the field. 419 * @throws NullPointerException 420 * if the target is {@code null}. 421 * @throws IllegalArgumentException 422 * if the field name is {@code null}, blank, empty, or could not be found. 423 * @throws IllegalAccessException 424 * if the named field is not {@code public}. 425 * @throws SecurityException if an underlying accessible object's method denies the request. 426 * @see SecurityManager#checkPermission 427 */ 428 public static Object readField(final Object target, final String fieldName) throws IllegalAccessException { 429 return readField(target, fieldName, false); 430 } 431 432 /** 433 * Reads the named {@link Field}. Superclasses will be considered. 434 * 435 * @param target 436 * the object to reflect, must not be {@code null}. 437 * @param fieldName 438 * the field name to obtain. 439 * @param forceAccess 440 * whether to break scope restrictions using the 441 * {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only 442 * match {@code public} fields. 443 * @return the field value 444 * @throws NullPointerException 445 * if {@code target} is {@code null}. 446 * @throws IllegalArgumentException 447 * if the field name is {@code null}, blank, empty, or could not be found. 448 * @throws IllegalAccessException 449 * if the named field is not made accessible. 450 * @throws SecurityException if an underlying accessible object's method denies the request. 451 * @see SecurityManager#checkPermission 452 */ 453 public static Object readField(final Object target, final String fieldName, final boolean forceAccess) throws IllegalAccessException { 454 Objects.requireNonNull(target, "target"); 455 final Class<?> cls = target.getClass(); 456 final Field field = getField(cls, fieldName, forceAccess); 457 Validate.isTrue(field != null, "Cannot locate field %s on %s", fieldName, cls); 458 // already forced access above, don't repeat it here: 459 return readField(field, target, false); 460 } 461 462 /** 463 * Reads the named {@code public static} {@link Field}. Superclasses will be considered. 464 * 465 * @param cls 466 * the {@link Class} to reflect, must not be {@code null}. 467 * @param fieldName 468 * the field name to obtain. 469 * @return the value of the field. 470 * @throws NullPointerException 471 * if the class is {@code null}, or the field could not be found. 472 * @throws IllegalArgumentException 473 * if the field name is {@code null}, blank or empty, or is not {@code static}. 474 * @throws IllegalAccessException 475 * if the field is not accessible. 476 * @throws SecurityException if an underlying accessible object's method denies the request. 477 * @see SecurityManager#checkPermission 478 */ 479 public static Object readStaticField(final Class<?> cls, final String fieldName) throws IllegalAccessException { 480 return readStaticField(cls, fieldName, false); 481 } 482 483 /** 484 * Reads the named {@code static} {@link Field}. Superclasses will be considered. 485 * 486 * @param cls 487 * the {@link Class} to reflect, must not be {@code null}. 488 * @param fieldName 489 * the field name to obtain. 490 * @param forceAccess 491 * whether to break scope restrictions using the 492 * {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only 493 * match {@code public} fields. 494 * @return the Field object. 495 * @throws NullPointerException 496 * if the class is {@code null}, or the field could not be found. 497 * @throws IllegalArgumentException 498 * if the field name is {@code null}, blank or empty, or is not {@code static}. 499 * @throws IllegalAccessException 500 * if the field is not made accessible. 501 * @throws SecurityException if an underlying accessible object's method denies the request. 502 * @see SecurityManager#checkPermission 503 */ 504 public static Object readStaticField(final Class<?> cls, final String fieldName, final boolean forceAccess) throws IllegalAccessException { 505 final Field field = getField(cls, fieldName, forceAccess); 506 Validate.notNull(field, "Cannot locate field '%s' on %s", fieldName, cls); 507 // already forced access above, don't repeat it here: 508 return readStaticField(field, false); 509 } 510 511 /** 512 * Reads an accessible {@code static} {@link Field}. 513 * 514 * @param field 515 * to read. 516 * @return the field value. 517 * @throws NullPointerException 518 * if the field is {@code null}. 519 * @throws IllegalArgumentException 520 * if the field is not {@code static}. 521 * @throws IllegalAccessException 522 * if the field is not accessible 523 * @throws SecurityException if an underlying accessible object's method denies the request. 524 * @see SecurityManager#checkPermission 525 */ 526 public static Object readStaticField(final Field field) throws IllegalAccessException { 527 return readStaticField(field, false); 528 } 529 530 /** 531 * Reads a static {@link Field}. 532 * 533 * @param field 534 * to read. 535 * @param forceAccess 536 * whether to break scope restrictions using the 537 * {@link AccessibleObject#setAccessible(boolean)} method. 538 * @return the field value. 539 * @throws NullPointerException 540 * if the field is {@code null}. 541 * @throws IllegalArgumentException 542 * if the field is not {@code static}. 543 * @throws IllegalAccessException 544 * if the field is not made accessible. 545 * @throws SecurityException if an underlying accessible object's method denies the request. 546 * @see SecurityManager#checkPermission 547 */ 548 public static Object readStaticField(final Field field, final boolean forceAccess) throws IllegalAccessException { 549 Objects.requireNonNull(field, "field"); 550 Validate.isTrue(MemberUtils.isStatic(field), "The field '%s' is not static", field.getName()); 551 return readField(field, (Object) null, forceAccess); 552 } 553 554 /** 555 * Removes the final modifier from a {@link Field}. 556 * 557 * @param field 558 * to remove the final modifier. 559 * @throws NullPointerException 560 * if the field is {@code null}. 561 * @throws SecurityException if an underlying accessible object's method denies the request. 562 * @see SecurityManager#checkPermission 563 * @since 3.2 564 */ 565 public static void removeFinalModifier(final Field field) { 566 removeFinalModifier(field, true); 567 } 568 569 /** 570 * Removes the final modifier from a {@link Field}. 571 * 572 * @param field 573 * to remove the final modifier. 574 * @param forceAccess 575 * whether to break scope restrictions using the 576 * {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only 577 * match {@code public} fields. 578 * @throws NullPointerException 579 * if the field is {@code null}. 580 * @throws SecurityException if an underlying accessible object's method denies the request. 581 * @see SecurityManager#checkPermission 582 * @deprecated As of Java 12, we can no longer drop the {@code final} modifier, thus 583 * rendering this method obsolete. The JDK discussion about this change can be found 584 * here: https://mail.openjdk.java.net/pipermail/core-libs-dev/2018-November/056486.html 585 * @since 3.3 586 */ 587 @Deprecated 588 public static void removeFinalModifier(final Field field, final boolean forceAccess) { 589 Objects.requireNonNull(field, "field"); 590 591 try { 592 if (Modifier.isFinal(field.getModifiers())) { 593 // Do all JREs implement Field with a private ivar called "modifiers"? 594 final Field modifiersField = Field.class.getDeclaredField("modifiers"); 595 final boolean doForceAccess = forceAccess && !modifiersField.isAccessible(); 596 if (doForceAccess) { 597 modifiersField.setAccessible(true); 598 } 599 try { 600 modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); 601 } finally { 602 if (doForceAccess) { 603 modifiersField.setAccessible(false); 604 } 605 } 606 } 607 } catch (final NoSuchFieldException | IllegalAccessException e) { 608 if (SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_12)) { 609 throw new UnsupportedOperationException( 610 "In java 12+ final cannot be removed.", 611 e 612 ); 613 } 614 // else no exception is thrown because we can modify final. 615 } 616 } 617 618 /** 619 * Writes a {@code public} {@link Field}. Only the specified class will be considered. 620 * 621 * @param target 622 * the object to reflect, must not be {@code null}. 623 * @param fieldName 624 * the field name to obtain. 625 * @param value 626 * the new value. 627 * @throws NullPointerException 628 * if {@code target} is {@code null}. 629 * @throws IllegalArgumentException 630 * if {@code fieldName} is {@code null}, blank or empty, or could not be found, 631 * or {@code value} is not assignable. 632 * @throws IllegalAccessException 633 * if the field is not made accessible 634 * @throws SecurityException if an underlying accessible object's method denies the request. 635 * @see SecurityManager#checkPermission 636 */ 637 public static void writeDeclaredField(final Object target, final String fieldName, final Object value) throws IllegalAccessException { 638 writeDeclaredField(target, fieldName, value, false); 639 } 640 641 /** 642 * Writes a {@code public} {@link Field}. Only the specified class will be considered. 643 * 644 * @param target 645 * the object to reflect, must not be {@code null}. 646 * @param fieldName 647 * the field name to obtain. 648 * @param value 649 * the new value. 650 * @param forceAccess 651 * whether to break scope restrictions using the 652 * {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only 653 * match {@code public} fields. 654 * @throws IllegalArgumentException 655 * if {@code fieldName} is {@code null}, blank or empty, or could not be found, 656 * or {@code value} is not assignable 657 * @throws IllegalAccessException 658 * if the field is not made accessible 659 * @throws SecurityException if an underlying accessible object's method denies the request. 660 * @see SecurityManager#checkPermission 661 */ 662 public static void writeDeclaredField(final Object target, final String fieldName, final Object value, final boolean forceAccess) 663 throws IllegalAccessException { 664 Objects.requireNonNull(target, "target"); 665 final Class<?> cls = target.getClass(); 666 final Field field = getDeclaredField(cls, fieldName, forceAccess); 667 Validate.isTrue(field != null, "Cannot locate declared field %s.%s", cls.getName(), fieldName); 668 // already forced access above, don't repeat it here: 669 writeField(field, target, value, false); 670 } 671 672 /** 673 * Writes a named {@code public static} {@link Field}. Only the specified class will be considered. 674 * 675 * @param cls 676 * {@link Class} on which the field is to be found. 677 * @param fieldName 678 * to write. 679 * @param value 680 * the new value. 681 * @throws NullPointerException 682 * if {@code cls} is {@code null} or the field cannot be located. 683 * @throws IllegalArgumentException 684 * if the field name is {@code null}, blank, empty, not {@code static}, or {@code value} is not assignable. 685 * @throws IllegalAccessException 686 * if the field is not {@code public} or is {@code final} 687 * @throws SecurityException if an underlying accessible object's method denies the request. 688 * @see SecurityManager#checkPermission 689 */ 690 public static void writeDeclaredStaticField(final Class<?> cls, final String fieldName, final Object value) throws IllegalAccessException { 691 writeDeclaredStaticField(cls, fieldName, value, false); 692 } 693 694 /** 695 * Writes a named {@code static} {@link Field}. Only the specified class will be considered. 696 * 697 * @param cls 698 * {@link Class} on which the field is to be found. 699 * @param fieldName 700 * to write 701 * @param value 702 * the new value. 703 * @param forceAccess 704 * whether to break scope restrictions using the {@code AccessibleObject#setAccessible(boolean)} method. 705 * {@code false} will only match {@code public} fields. 706 * @throws NullPointerException 707 * if {@code cls} is {@code null} or the field cannot be located. 708 * @throws IllegalArgumentException 709 * if the field name is {@code null}, blank, empty, not {@code static}, or {@code value} is not assignable. 710 * @throws IllegalAccessException 711 * if the field is not made accessible or is {@code final} 712 * @throws SecurityException if an underlying accessible object's method denies the request. 713 * @see SecurityManager#checkPermission 714 */ 715 public static void writeDeclaredStaticField(final Class<?> cls, final String fieldName, final Object value, final boolean forceAccess) 716 throws IllegalAccessException { 717 final Field field = getDeclaredField(cls, fieldName, forceAccess); 718 Validate.notNull(field, "Cannot locate declared field %s.%s", cls.getName(), fieldName); 719 // already forced access above, don't repeat it here: 720 writeField(field, (Object) null, value, false); 721 } 722 723 /** 724 * Writes an accessible {@link Field}. 725 * 726 * @param field 727 * to write. 728 * @param target 729 * the object to call on, may be {@code null} for {@code static} fields. 730 * @param value 731 * the new value. 732 * @throws NullPointerException 733 * if the field is {@code null}. 734 * @throws IllegalArgumentException 735 * if {@code value} is not assignable. 736 * @throws IllegalAccessException 737 * if the field is not accessible or is {@code final}. 738 * @throws SecurityException if an underlying accessible object's method denies the request. 739 * @see SecurityManager#checkPermission 740 */ 741 public static void writeField(final Field field, final Object target, final Object value) throws IllegalAccessException { 742 writeField(field, target, value, false); 743 } 744 745 /** 746 * Writes a {@link Field}. 747 * 748 * @param field 749 * to write. 750 * @param target 751 * the object to call on, may be {@code null} for {@code static} fields 752 * @param value 753 * the new value. 754 * @param forceAccess 755 * whether to break scope restrictions using the 756 * {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only 757 * match {@code public} fields. 758 * @throws NullPointerException 759 * if the field is {@code null}. 760 * @throws IllegalArgumentException 761 * if {@code value} is not assignable. 762 * @throws IllegalAccessException 763 * if the field is not made accessible or is {@code final} 764 * @throws SecurityException if an underlying accessible object's method denies the request. 765 * @see SecurityManager#checkPermission 766 */ 767 public static void writeField(final Field field, final Object target, final Object value, final boolean forceAccess) 768 throws IllegalAccessException { 769 Objects.requireNonNull(field, "field"); 770 if (forceAccess && !field.isAccessible()) { 771 field.setAccessible(true); 772 } else { 773 MemberUtils.setAccessibleWorkaround(field); 774 } 775 field.set(target, value); 776 } 777 778 /** 779 * Writes a {@code public} {@link Field}. Superclasses will be considered. 780 * 781 * @param target 782 * the object to reflect, must not be {@code null}. 783 * @param fieldName 784 * the field name to obtain. 785 * @param value 786 * the new value. 787 * @throws NullPointerException 788 * if {@code target} is {@code null}. 789 * @throws IllegalArgumentException 790 * if {@code fieldName} is {@code null}, blank, empty, or could not be found, 791 * or {@code value} is not assignable. 792 * @throws IllegalAccessException 793 * if the field is not accessible. 794 * @throws SecurityException if an underlying accessible object's method denies the request. 795 * @see SecurityManager#checkPermission 796 */ 797 public static void writeField(final Object target, final String fieldName, final Object value) throws IllegalAccessException { 798 writeField(target, fieldName, value, false); 799 } 800 801 /** 802 * Writes a {@link Field}. Superclasses will be considered. 803 * 804 * @param target 805 * the object to reflect, must not be {@code null}. 806 * @param fieldName 807 * the field name to obtain. 808 * @param value 809 * the new value. 810 * @param forceAccess 811 * whether to break scope restrictions using the 812 * {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only 813 * match {@code public} fields. 814 * @throws NullPointerException 815 * if {@code target} is {@code null}. 816 * @throws IllegalArgumentException 817 * if {@code fieldName} is {@code null}, blank, empty, or could not be found, 818 * or {@code value} is not assignable. 819 * @throws IllegalAccessException 820 * if the field is not made accessible. 821 * @throws SecurityException if an underlying accessible object's method denies the request. 822 * @see SecurityManager#checkPermission 823 */ 824 public static void writeField(final Object target, final String fieldName, final Object value, final boolean forceAccess) 825 throws IllegalAccessException { 826 Objects.requireNonNull(target, "target"); 827 final Class<?> cls = target.getClass(); 828 final Field field = getField(cls, fieldName, forceAccess); 829 Validate.isTrue(field != null, "Cannot locate declared field %s.%s", cls.getName(), fieldName); 830 // already forced access above, don't repeat it here: 831 writeField(field, target, value, false); 832 } 833 834 /** 835 * Writes a named {@code public static} {@link Field}. Superclasses will be considered. 836 * 837 * @param cls 838 * {@link Class} on which the field is to be found. 839 * @param fieldName 840 * to write. 841 * @param value 842 * the new value. 843 * @throws NullPointerException 844 * if {@code target} is {@code null}. 845 * @throws IllegalArgumentException 846 * if {@code fieldName} is {@code null}, blank or empty, the field cannot be located or is 847 * not {@code static}, or {@code value} is not assignable. 848 * @throws IllegalAccessException 849 * if the field is not {@code public} or is {@code final} 850 * @throws SecurityException if an underlying accessible object's method denies the request. 851 * @see SecurityManager#checkPermission 852 */ 853 public static void writeStaticField(final Class<?> cls, final String fieldName, final Object value) throws IllegalAccessException { 854 writeStaticField(cls, fieldName, value, false); 855 } 856 857 /** 858 * Writes a named {@code static} {@link Field}. Superclasses will be considered. 859 * 860 * @param cls 861 * {@link Class} on which the field is to be found. 862 * @param fieldName 863 * to write. 864 * @param value 865 * the new value. 866 * @param forceAccess 867 * whether to break scope restrictions using the 868 * {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only 869 * match {@code public} fields. 870 * @throws NullPointerException 871 * if {@code cls} is {@code null} or the field cannot be located. 872 * @throws IllegalArgumentException 873 * if {@code fieldName} is {@code null}, blank or empty, the field not {@code static}, or {@code value} is not assignable. 874 * @throws IllegalAccessException 875 * if the field is not made accessible or is {@code final}. 876 * @throws SecurityException if an underlying accessible object's method denies the request. 877 * @see SecurityManager#checkPermission 878 */ 879 public static void writeStaticField(final Class<?> cls, final String fieldName, final Object value, final boolean forceAccess) 880 throws IllegalAccessException { 881 final Field field = getField(cls, fieldName, forceAccess); 882 Validate.notNull(field, "Cannot locate field %s on %s", fieldName, cls); 883 // already forced access above, don't repeat it here: 884 writeStaticField(field, value, false); 885 } 886 887 /** 888 * Writes a {@code public static} {@link Field}. 889 * 890 * @param field 891 * to write. 892 * @param value 893 * the new value. 894 * @throws NullPointerException 895 * if the field is {@code null}. 896 * @throws IllegalArgumentException 897 * if the field is not {@code static}, or {@code value} is not assignable. 898 * @throws IllegalAccessException 899 * if the field is not {@code public} or is {@code final}. 900 * @throws SecurityException if an underlying accessible object's method denies the request. 901 * @see SecurityManager#checkPermission 902 */ 903 public static void writeStaticField(final Field field, final Object value) throws IllegalAccessException { 904 writeStaticField(field, value, false); 905 } 906 907 /** 908 * Writes a static {@link Field}. 909 * 910 * @param field 911 * to write. 912 * @param value 913 * the new value. 914 * @param forceAccess 915 * whether to break scope restrictions using the 916 * {@link AccessibleObject#setAccessible(boolean)} method. {@code false} will only 917 * match {@code public} fields. 918 * @throws NullPointerException 919 * if the field is {@code null}. 920 * @throws IllegalArgumentException 921 * if the field is not {@code static}, or {@code value} is not assignable. 922 * @throws IllegalAccessException 923 * if the field is not made accessible or is {@code final} 924 * @throws SecurityException if an underlying accessible object's method denies the request. 925 * @see SecurityManager#checkPermission 926 */ 927 public static void writeStaticField(final Field field, final Object value, final boolean forceAccess) throws IllegalAccessException { 928 Objects.requireNonNull(field, "field"); 929 Validate.isTrue(MemberUtils.isStatic(field), "The field %s.%s is not static", field.getDeclaringClass().getName(), 930 field.getName()); 931 writeField(field, (Object) null, value, forceAccess); 932 } 933 934 /** 935 * {@link FieldUtils} instances should NOT be constructed in standard programming. 936 * <p> 937 * This constructor is {@code public} to permit tools that require a JavaBean instance to operate. 938 * </p> 939 * 940 * @deprecated TODO Make private in 4.0. 941 */ 942 @Deprecated 943 public FieldUtils() { 944 // empty 945 } 946}