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 * http://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 org.apache.commons.lang3.ClassUtils; 020import org.apache.commons.lang3.StringUtils; 021import org.apache.commons.lang3.Validate; 022 023import java.lang.reflect.Field; 024import java.lang.reflect.Modifier; 025import java.util.ArrayList; 026import java.util.List; 027 028/** 029 * Utilities for working with {@link Field}s by reflection. Adapted and refactored from the dormant [reflect] Commons sandbox 030 * component. 031 * <p> 032 * The ability is provided to break the scoping restrictions coded by the programmer. This can allow fields to be 033 * changed that shouldn't be. This facility should be used with care. 034 * 035 * @since 2.5 036 * @version $Id: FieldUtils.java 1546799 2013-12-01 10:34:02Z mcucchiara $ 037 */ 038public class FieldUtils { 039 040 /** 041 * {@link FieldUtils} instances should NOT be constructed in standard programming. 042 * <p> 043 * This constructor is {@code public} to permit tools that require a JavaBean instance to operate.</p> 044 */ 045 public FieldUtils() { 046 super(); 047 } 048 049 /** 050 * Gets an accessible {@link Field} by name respecting scope. Superclasses/interfaces will be considered. 051 * 052 * @param cls 053 * the {@link Class} to reflect, must not be {@code null} 054 * @param fieldName 055 * the field name to obtain 056 * @return the Field object 057 * @throws IllegalArgumentException 058 * if the class is {@code null}, or the field name is blank or empty 059 */ 060 public static Field getField(final Class<?> cls, final String fieldName) { 061 final Field field = getField(cls, fieldName, false); 062 MemberUtils.setAccessibleWorkaround(field); 063 return field; 064 } 065 066 /** 067 * Gets an accessible {@link Field} by name, breaking scope if requested. Superclasses/interfaces will be 068 * considered. 069 * 070 * @param cls 071 * the {@link Class} to reflect, must not be {@code null} 072 * @param fieldName 073 * the field name to obtain 074 * @param forceAccess 075 * whether to break scope restrictions using the 076 * {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. 077 * {@code false} will only match {@code public} fields. 078 * @return the Field object 079 * @throws IllegalArgumentException 080 * if the class is {@code null}, or the field name is blank or empty or is matched at 081 * multiple places in the inheritance hierarchy 082 */ 083 public static Field getField(final Class<?> cls, final String fieldName, final boolean forceAccess) { 084 Validate.isTrue(cls != null, "The class must not be null"); 085 Validate.isTrue(StringUtils.isNotBlank(fieldName), "The field name must not be blank/empty"); 086 // Sun Java 1.3 has a bugged implementation of getField hence we write the 087 // code ourselves 088 089 // getField() will return the Field object with the declaring class 090 // set correctly to the class that declares the field. Thus requesting the 091 // field on a subclass will return the field from the superclass. 092 // 093 // priority order for lookup: 094 // searchclass private/protected/package/public 095 // superclass protected/package/public 096 // private/different package blocks access to further superclasses 097 // implementedinterface public 098 099 // check up the superclass hierarchy 100 for (Class<?> acls = cls; acls != null; acls = acls.getSuperclass()) { 101 try { 102 final Field field = acls.getDeclaredField(fieldName); 103 // getDeclaredField checks for non-public scopes as well 104 // and it returns accurate results 105 if (!Modifier.isPublic(field.getModifiers())) { 106 if (forceAccess) { 107 field.setAccessible(true); 108 } else { 109 continue; 110 } 111 } 112 return field; 113 } catch (final NoSuchFieldException ex) { // NOPMD 114 // ignore 115 } 116 } 117 // check the public interface case. This must be manually searched for 118 // incase there is a public supersuperclass field hidden by a private/package 119 // superclass field. 120 Field match = null; 121 for (final Class<?> class1 : ClassUtils.getAllInterfaces(cls)) { 122 try { 123 final Field test = class1.getField(fieldName); 124 Validate.isTrue(match == null, "Reference to field %s is ambiguous relative to %s" 125 + "; a matching field exists on two or more implemented interfaces.", fieldName, cls); 126 match = test; 127 } catch (final NoSuchFieldException ex) { // NOPMD 128 // ignore 129 } 130 } 131 return match; 132 } 133 134 /** 135 * Gets an accessible {@link Field} by name respecting scope. Only the specified class will be considered. 136 * 137 * @param cls 138 * the {@link Class} to reflect, must not be {@code null} 139 * @param fieldName 140 * the field name to obtain 141 * @return the Field object 142 * @throws IllegalArgumentException 143 * if the class is {@code null}, or the field name is blank or empty 144 */ 145 public static Field getDeclaredField(final Class<?> cls, final String fieldName) { 146 return getDeclaredField(cls, fieldName, false); 147 } 148 149 /** 150 * Gets an accessible {@link Field} by name, breaking scope if requested. Only the specified class will be 151 * considered. 152 * 153 * @param cls 154 * the {@link Class} to reflect, must not be {@code null} 155 * @param fieldName 156 * the field name to obtain 157 * @param forceAccess 158 * whether to break scope restrictions using the 159 * {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. 160 * {@code false} will only match {@code public} fields. 161 * @return the Field object 162 * @throws IllegalArgumentException 163 * if the class is {@code null}, or the field name is blank or empty 164 */ 165 public static Field getDeclaredField(final Class<?> cls, final String fieldName, final boolean forceAccess) { 166 Validate.isTrue(cls != null, "The class must not be null"); 167 Validate.isTrue(StringUtils.isNotBlank(fieldName), "The field name must not be blank/empty"); 168 try { 169 // only consider the specified class by using getDeclaredField() 170 final Field field = cls.getDeclaredField(fieldName); 171 if (!MemberUtils.isAccessible(field)) { 172 if (forceAccess) { 173 field.setAccessible(true); 174 } else { 175 return null; 176 } 177 } 178 return field; 179 } catch (final NoSuchFieldException e) { // NOPMD 180 // ignore 181 } 182 return null; 183 } 184 185 /** 186 * Gets all fields of the given class and its parents (if any). 187 * 188 * @param cls 189 * the {@link Class} to query 190 * @return an array of Fields (possibly empty). 191 * @throws IllegalArgumentException 192 * if the class is {@code null} 193 * @since 3.2 194 */ 195 public static Field[] getAllFields(Class<?> cls) { 196 final List<Field> allFieldsList = getAllFieldsList(cls); 197 return allFieldsList.toArray(new Field[allFieldsList.size()]); 198 } 199 200 /** 201 * Gets all fields of the given class and its parents (if any). 202 * 203 * @param cls 204 * the {@link Class} to query 205 * @return an array of Fields (possibly empty). 206 * @throws IllegalArgumentException 207 * if the class is {@code null} 208 * @since 3.2 209 */ 210 public static List<Field> getAllFieldsList(Class<?> cls) { 211 Validate.isTrue(cls != null, "The class must not be null"); 212 final List<Field> allFields = new ArrayList<Field>(); 213 Class<?> currentClass = cls; 214 while (currentClass != null) { 215 final Field[] declaredFields = currentClass.getDeclaredFields(); 216 for (Field field : declaredFields) { 217 allFields.add(field); 218 } 219 currentClass = currentClass.getSuperclass(); 220 } 221 return allFields; 222 } 223 224 /** 225 * Reads an accessible {@code static} {@link Field}. 226 * 227 * @param field 228 * to read 229 * @return the field value 230 * @throws IllegalArgumentException 231 * if the field is {@code null}, or not {@code static} 232 * @throws IllegalAccessException 233 * if the field is not accessible 234 */ 235 public static Object readStaticField(final Field field) throws IllegalAccessException { 236 return readStaticField(field, false); 237 } 238 239 /** 240 * Reads a static {@link Field}. 241 * 242 * @param field 243 * to read 244 * @param forceAccess 245 * whether to break scope restrictions using the 246 * {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. 247 * @return the field value 248 * @throws IllegalArgumentException 249 * if the field is {@code null} or not {@code static} 250 * @throws IllegalAccessException 251 * if the field is not made accessible 252 */ 253 public static Object readStaticField(final Field field, final boolean forceAccess) throws IllegalAccessException { 254 Validate.isTrue(field != null, "The field must not be null"); 255 Validate.isTrue(Modifier.isStatic(field.getModifiers()), "The field '%s' is not static", field.getName()); 256 return readField(field, (Object) null, forceAccess); 257 } 258 259 /** 260 * Reads the named {@code public static} {@link Field}. Superclasses will be considered. 261 * 262 * @param cls 263 * the {@link Class} to reflect, must not be {@code null} 264 * @param fieldName 265 * the field name to obtain 266 * @return the value of the field 267 * @throws IllegalArgumentException 268 * if the class is {@code null}, or the field name is blank or empty, 269 * is not {@code static}, or could not be found 270 * @throws IllegalAccessException 271 * if the field is not accessible 272 */ 273 public static Object readStaticField(final Class<?> cls, final String fieldName) throws IllegalAccessException { 274 return readStaticField(cls, fieldName, false); 275 } 276 277 /** 278 * Reads the named {@code static} {@link Field}. Superclasses will be considered. 279 * 280 * @param cls 281 * the {@link Class} to reflect, must not be {@code null} 282 * @param fieldName 283 * the field name to obtain 284 * @param forceAccess 285 * whether to break scope restrictions using the 286 * {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. 287 * {@code false} will only match {@code public} fields. 288 * @return the Field object 289 * @throws IllegalArgumentException 290 * if the class is {@code null}, or the field name is blank or empty, 291 * is not {@code static}, or could not be found 292 * @throws IllegalAccessException 293 * if the field is not made accessible 294 */ 295 public static Object readStaticField(final Class<?> cls, final String fieldName, final boolean forceAccess) throws IllegalAccessException { 296 final Field field = getField(cls, fieldName, forceAccess); 297 Validate.isTrue(field != null, "Cannot locate field '%s' on %s", fieldName, cls); 298 // already forced access above, don't repeat it here: 299 return readStaticField(field, false); 300 } 301 302 /** 303 * Gets the value of a {@code static} {@link Field} by name. The field must be {@code public}. 304 * Only the specified class will be considered. 305 * 306 * @param cls 307 * the {@link Class} to reflect, must not be {@code null} 308 * @param fieldName 309 * the field name to obtain 310 * @return the value of the field 311 * @throws IllegalArgumentException 312 * if the class is {@code null}, or the field name is blank or empty, 313 * is not {@code static}, or could not be found 314 * @throws IllegalAccessException 315 * if the field is not accessible 316 */ 317 public static Object readDeclaredStaticField(final Class<?> cls, final String fieldName) throws IllegalAccessException { 318 return readDeclaredStaticField(cls, fieldName, false); 319 } 320 321 /** 322 * Gets the value of a {@code static} {@link Field} by name. 323 * Only the specified class will be considered. 324 * 325 * @param cls 326 * the {@link Class} to reflect, must not be {@code null} 327 * @param fieldName 328 * the field name to obtain 329 * @param forceAccess 330 * whether to break scope restrictions using the 331 * {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. 332 * {@code false} will only match {@code public} fields. 333 * @return the Field object 334 * @throws IllegalArgumentException 335 * if the class is {@code null}, or the field name is blank or empty, 336 * is not {@code static}, or could not be found 337 * @throws IllegalAccessException 338 * if the field is not made accessible 339 */ 340 public static Object readDeclaredStaticField(final Class<?> cls, final String fieldName, final boolean forceAccess) throws IllegalAccessException { 341 final Field field = getDeclaredField(cls, fieldName, forceAccess); 342 Validate.isTrue(field != null, "Cannot locate declared field %s.%s", cls.getName(), fieldName); 343 // already forced access above, don't repeat it here: 344 return readStaticField(field, false); 345 } 346 347 /** 348 * Reads an accessible {@link Field}. 349 * 350 * @param field 351 * the field to use 352 * @param target 353 * the object to call on, may be {@code null} for {@code static} fields 354 * @return the field value 355 * @throws IllegalArgumentException 356 * if the field is {@code null} 357 * @throws IllegalAccessException 358 * if the field is not accessible 359 */ 360 public static Object readField(final Field field, final Object target) throws IllegalAccessException { 361 return readField(field, target, false); 362 } 363 364 /** 365 * Reads a {@link Field}. 366 * 367 * @param field 368 * the field to use 369 * @param target 370 * the object to call on, may be {@code null} for {@code static} fields 371 * @param forceAccess 372 * whether to break scope restrictions using the 373 * {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. 374 * @return the field value 375 * @throws IllegalArgumentException 376 * if the field is {@code null} 377 * @throws IllegalAccessException 378 * if the field is not made accessible 379 */ 380 public static Object readField(final Field field, final Object target, final boolean forceAccess) throws IllegalAccessException { 381 Validate.isTrue(field != null, "The field must not be null"); 382 if (forceAccess && !field.isAccessible()) { 383 field.setAccessible(true); 384 } else { 385 MemberUtils.setAccessibleWorkaround(field); 386 } 387 return field.get(target); 388 } 389 390 /** 391 * Reads the named {@code public} {@link Field}. Superclasses will be considered. 392 * 393 * @param target 394 * the object to reflect, must not be {@code null} 395 * @param fieldName 396 * the field name to obtain 397 * @return the value of the field 398 * @throws IllegalArgumentException 399 * if the class is {@code null}, or 400 * the field name is blank or empty or could not be found 401 * @throws IllegalAccessException 402 * if the named field is not {@code public} 403 */ 404 public static Object readField(final Object target, final String fieldName) throws IllegalAccessException { 405 return readField(target, fieldName, false); 406 } 407 408 /** 409 * Reads the named {@link Field}. Superclasses will be considered. 410 * 411 * @param target 412 * the object to reflect, must not be {@code null} 413 * @param fieldName 414 * the field name to obtain 415 * @param forceAccess 416 * whether to break scope restrictions using the 417 * {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. 418 * {@code false} will only match {@code public} fields. 419 * @return the field value 420 * @throws IllegalArgumentException 421 * if {@code target} is {@code null}, or 422 * the field name is blank or empty or could not be found 423 * @throws IllegalAccessException 424 * if the named field is not made accessible 425 */ 426 public static Object readField(final Object target, final String fieldName, final boolean forceAccess) throws IllegalAccessException { 427 Validate.isTrue(target != null, "target object must not be null"); 428 final Class<?> cls = target.getClass(); 429 final Field field = getField(cls, fieldName, forceAccess); 430 Validate.isTrue(field != null, "Cannot locate field %s on %s" , fieldName, cls); 431 // already forced access above, don't repeat it here: 432 return readField(field, target); 433 } 434 435 /** 436 * Reads the named {@code public} {@link Field}. Only the class of the specified object will be considered. 437 * 438 * @param target 439 * the object to reflect, must not be {@code null} 440 * @param fieldName 441 * the field name to obtain 442 * @return the value of the field 443 * @throws IllegalArgumentException 444 * if {@code target} is {@code null}, or 445 * the field name is blank or empty or could not be found 446 * @throws IllegalAccessException 447 * if the named field is not {@code public} 448 */ 449 public static Object readDeclaredField(final Object target, final String fieldName) throws IllegalAccessException { 450 return readDeclaredField(target, fieldName, false); 451 } 452 453 /** 454 * <p<>Gets a {@link Field} value by name. Only the class of the specified object will be considered. 455 * 456 * @param target 457 * the object to reflect, must not be {@code null} 458 * @param fieldName 459 * the field name to obtain 460 * @param forceAccess 461 * whether to break scope restrictions using the 462 * {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. 463 * {@code false} will only match public fields. 464 * @return the Field object 465 * @throws IllegalArgumentException 466 * if {@code target} is {@code null}, or 467 * the field name is blank or empty or could not be found 468 * @throws IllegalAccessException 469 * if the field is not made accessible 470 */ 471 public static Object readDeclaredField(final Object target, final String fieldName, final boolean forceAccess) throws IllegalAccessException { 472 Validate.isTrue(target != null, "target object must not be null"); 473 final Class<?> cls = target.getClass(); 474 final Field field = getDeclaredField(cls, fieldName, forceAccess); 475 Validate.isTrue(field != null, "Cannot locate declared field %s.%s" , cls, fieldName); 476 // already forced access above, don't repeat it here: 477 return readField(field, target); 478 } 479 480 /** 481 * Writes a {@code public static} {@link Field}. 482 * 483 * @param field 484 * to write 485 * @param value 486 * to set 487 * @throws IllegalArgumentException 488 * if the field is {@code null} or not {@code static}, 489 * or {@code value} is not assignable 490 * @throws IllegalAccessException 491 * if the field is not {@code public} or is {@code final} 492 */ 493 public static void writeStaticField(final Field field, final Object value) throws IllegalAccessException { 494 writeStaticField(field, value, false); 495 } 496 497 /** 498 * Writes a static {@link Field}. 499 * 500 * @param field 501 * to write 502 * @param value 503 * to set 504 * @param forceAccess 505 * whether to break scope restrictions using the 506 * {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. {@code false} 507 * will only match {@code public} fields. 508 * @throws IllegalArgumentException 509 * if the field is {@code null} or not {@code static}, 510 * or {@code value} is not assignable 511 * @throws IllegalAccessException 512 * if the field is not made accessible or is {@code final} 513 */ 514 public static void writeStaticField(final Field field, final Object value, final boolean forceAccess) throws IllegalAccessException { 515 Validate.isTrue(field != null, "The field must not be null"); 516 Validate.isTrue(Modifier.isStatic(field.getModifiers()), "The field %s.%s is not static", 517 field.getDeclaringClass().getName(), field.getName()); 518 writeField(field, (Object) null, value, forceAccess); 519 } 520 521 /** 522 * Writes a named {@code public static} {@link Field}. Superclasses will be considered. 523 * 524 * @param cls 525 * {@link Class} on which the field is to be found 526 * @param fieldName 527 * to write 528 * @param value 529 * to set 530 * @throws IllegalArgumentException 531 * if {@code cls} is {@code null}, 532 * the field name is blank or empty, 533 * the field cannot be located or is not {@code static}, or 534 * {@code value} is not assignable 535 * @throws IllegalAccessException 536 * if the field is not {@code public} or is {@code final} 537 */ 538 public static void writeStaticField(final Class<?> cls, final String fieldName, final Object value) throws IllegalAccessException { 539 writeStaticField(cls, fieldName, value, false); 540 } 541 542 /** 543 * Writes a named {@code static} {@link Field}. Superclasses will be considered. 544 * 545 * @param cls 546 * {@link Class} on which the field is to be found 547 * @param fieldName 548 * to write 549 * @param value 550 * to set 551 * @param forceAccess 552 * whether to break scope restrictions using the 553 * {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. 554 * {@code false} will only match {@code public} fields. 555 * @throws IllegalArgumentException 556 * if {@code cls} is {@code null}, 557 * the field name is blank or empty, 558 * the field cannot be located or is not {@code static}, or 559 * {@code value} is not assignable 560 * @throws IllegalAccessException 561 * if the field is not made accessible or is {@code final} 562 */ 563 public static void writeStaticField(final Class<?> cls, final String fieldName, final Object value, final boolean forceAccess) 564 throws IllegalAccessException { 565 final Field field = getField(cls, fieldName, forceAccess); 566 Validate.isTrue(field != null, "Cannot locate field %s on %s", fieldName, cls); 567 // already forced access above, don't repeat it here: 568 writeStaticField(field, value); 569 } 570 571 /** 572 * Writes a named {@code public static} {@link Field}. Only the specified class will be considered. 573 * 574 * @param cls 575 * {@link Class} on which the field is to be found 576 * @param fieldName 577 * to write 578 * @param value 579 * to set 580 * @throws IllegalArgumentException 581 * if {@code cls} is {@code null}, 582 * the field name is blank or empty, 583 * the field cannot be located or is not {@code static}, or 584 * {@code value} is not assignable 585 * @throws IllegalAccessException 586 * if the field is not {@code public} or is {@code final} 587 */ 588 public static void writeDeclaredStaticField(final Class<?> cls, final String fieldName, final Object value) throws IllegalAccessException { 589 writeDeclaredStaticField(cls, fieldName, value, false); 590 } 591 592 /** 593 * Writes a named {@code static} {@link Field}. Only the specified class will be considered. 594 * 595 * @param cls 596 * {@link Class} on which the field is to be found 597 * @param fieldName 598 * to write 599 * @param value 600 * to set 601 * @param forceAccess 602 * whether to break scope restrictions using the {@code AccessibleObject#setAccessible(boolean)} method. 603 * {@code false} will only match {@code public} fields. 604 * @throws IllegalArgumentException 605 * if {@code cls} is {@code null}, 606 * the field name is blank or empty, 607 * the field cannot be located or is not {@code static}, or 608 * {@code value} is not assignable 609 * @throws IllegalAccessException 610 * if the field is not made accessible or is {@code final} 611 */ 612 public static void writeDeclaredStaticField(final Class<?> cls, final String fieldName, final Object value, final boolean forceAccess) 613 throws IllegalAccessException { 614 final Field field = getDeclaredField(cls, fieldName, forceAccess); 615 Validate.isTrue(field != null, "Cannot locate declared field %s.%s", cls.getName(), fieldName); 616 // already forced access above, don't repeat it here: 617 writeField(field, (Object) null, value); 618 } 619 620 /** 621 * Writes an accessible {@link Field}. 622 * 623 * @param field 624 * to write 625 * @param target 626 * the object to call on, may be {@code null} for {@code static} fields 627 * @param value 628 * to set 629 * @throws IllegalAccessException 630 * if the field or target is {@code null}, 631 * the field is not accessible or is {@code final}, or 632 * {@code value} is not assignable 633 */ 634 public static void writeField(final Field field, final Object target, final Object value) throws IllegalAccessException { 635 writeField(field, target, value, false); 636 } 637 638 /** 639 * Writes a {@link Field}. 640 * 641 * @param field 642 * to write 643 * @param target 644 * the object to call on, may be {@code null} for {@code static} fields 645 * @param value 646 * to set 647 * @param forceAccess 648 * whether to break scope restrictions using the 649 * {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. 650 * {@code false} will only match {@code public} fields. 651 * @throws IllegalArgumentException 652 * if the field is {@code null} or 653 * {@code value} is not assignable 654 * @throws IllegalAccessException 655 * if the field is not made accessible or is {@code final} 656 */ 657 public static void writeField(final Field field, final Object target, final Object value, final boolean forceAccess) 658 throws IllegalAccessException { 659 Validate.isTrue(field != null, "The field must not be null"); 660 if (forceAccess && !field.isAccessible()) { 661 field.setAccessible(true); 662 } else { 663 MemberUtils.setAccessibleWorkaround(field); 664 } 665 field.set(target, value); 666 } 667 668 /** 669 * Remove the final modifier from a {@link Field} 670 * @param field to remove the final modifier 671 * @throws IllegalArgumentException 672 * if the field is {@code null} 673 */ 674 public static void removeFinalModifier(Field field) { 675 Validate.isTrue(field != null, "The field must not be null"); 676 677 try { 678 if(Modifier.isFinal(field.getModifiers())){ 679 Field modifiersField = Field.class.getDeclaredField("modifiers"); 680 modifiersField.setAccessible(true); 681 modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); 682 } 683 } catch (NoSuchFieldException ignored) { 684 // The field class contains always a modifiers field 685 } catch (IllegalAccessException ignored) { 686 // The modifiers field is made accessible 687 } 688 } 689 690 /** 691 * Writes a {@code public} {@link Field}. Superclasses will be considered. 692 * 693 * @param target 694 * the object to reflect, must not be {@code null} 695 * @param fieldName 696 * the field name to obtain 697 * @param value 698 * to set 699 * @throws IllegalArgumentException 700 * if {@code target} is {@code null}, 701 * {@code fieldName} is blank or empty or could not be found, 702 * or {@code value} is not assignable 703 * @throws IllegalAccessException 704 * if the field is not accessible 705 */ 706 public static void writeField(final Object target, final String fieldName, final Object value) throws IllegalAccessException { 707 writeField(target, fieldName, value, false); 708 } 709 710 /** 711 * Writes a {@link Field}. Superclasses will be considered. 712 * 713 * @param target 714 * the object to reflect, must not be {@code null} 715 * @param fieldName 716 * the field name to obtain 717 * @param value 718 * to set 719 * @param forceAccess 720 * whether to break scope restrictions using the 721 * {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. {@code false} 722 * will only match {@code public} fields. 723 * @throws IllegalArgumentException 724 * if {@code target} is {@code null}, 725 * {@code fieldName} is blank or empty or could not be found, 726 * or {@code value} is not assignable 727 * @throws IllegalAccessException 728 * if the field is not made accessible 729 */ 730 public static void writeField(final Object target, final String fieldName, final Object value, final boolean forceAccess) 731 throws IllegalAccessException { 732 Validate.isTrue(target != null, "target object must not be null"); 733 final Class<?> cls = target.getClass(); 734 final Field field = getField(cls, fieldName, forceAccess); 735 Validate.isTrue(field != null, "Cannot locate declared field %s.%s", cls.getName(), fieldName); 736 // already forced access above, don't repeat it here: 737 writeField(field, target, value); 738 } 739 740 /** 741 * Writes a {@code public} {@link Field}. Only the specified class will be considered. 742 * 743 * @param target 744 * the object to reflect, must not be {@code null} 745 * @param fieldName 746 * the field name to obtain 747 * @param value 748 * to set 749 * @throws IllegalArgumentException 750 * if {@code target} is {@code null}, 751 * {@code fieldName} is blank or empty or could not be found, 752 * or {@code value} is not assignable 753 * @throws IllegalAccessException 754 * if the field is not made accessible 755 */ 756 public static void writeDeclaredField(final Object target, final String fieldName, final Object value) throws IllegalAccessException { 757 writeDeclaredField(target, fieldName, value, false); 758 } 759 760 /** 761 * Writes a {@code public} {@link Field}. Only the specified class will be considered. 762 * 763 * @param target 764 * the object to reflect, must not be {@code null} 765 * @param fieldName 766 * the field name to obtain 767 * @param value 768 * to set 769 * @param forceAccess 770 * whether to break scope restrictions using the 771 * {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. 772 * {@code false} will only match {@code public} fields. 773 * @throws IllegalArgumentException 774 * if {@code target} is {@code null}, 775 * {@code fieldName} is blank or empty or could not be found, 776 * or {@code value} is not assignable 777 * @throws IllegalAccessException 778 * if the field is not made accessible 779 */ 780 public static void writeDeclaredField(final Object target, final String fieldName, final Object value, final boolean forceAccess) 781 throws IllegalAccessException { 782 Validate.isTrue(target != null, "target object must not be null"); 783 final Class<?> cls = target.getClass(); 784 final Field field = getDeclaredField(cls, fieldName, forceAccess); 785 Validate.isTrue(field != null, "Cannot locate declared field %s.%s", cls.getName(), fieldName); 786 // already forced access above, don't repeat it here: 787 writeField(field, target, value); 788 } 789}