[LANG-961] org.apache.commons.lang3.reflect.FieldUtils.removeFinalModifier(Field) does not clean up after itself.
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/lang/trunk@1562991 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
8c04a90ec5
commit
2eecc96a53
|
@ -22,6 +22,7 @@
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<release version="3.3" date="TBA" description="Bugfix and Feature release">
|
<release version="3.3" date="TBA" description="Bugfix and Feature release">
|
||||||
|
<action issue="LANG-961" type="update" dev="ggregory">org.apache.commons.lang3.reflect.FieldUtils.removeFinalModifier(Field) does not clean up after itself</action>
|
||||||
<action issue="LANG-958" type="update" dev="chas">FastDateParser javadoc incorrectly states that SimpleDateFormat is used internally</action>
|
<action issue="LANG-958" type="update" dev="chas">FastDateParser javadoc incorrectly states that SimpleDateFormat is used internally</action>
|
||||||
<action issue="LANG-637" type="add" dev="djones">There should be a DifferenceBuilder with a ReflectionDifferenceBuilder implementation</action>
|
<action issue="LANG-637" type="add" dev="djones">There should be a DifferenceBuilder with a ReflectionDifferenceBuilder implementation</action>
|
||||||
<action issue="LANG-954" type="fix" due-to="Michael Keppler" dev="sebb">uncaught PatternSyntaxException in FastDateFormat on Android</action>
|
<action issue="LANG-954" type="fix" due-to="Michael Keppler" dev="sebb">uncaught PatternSyntaxException in FastDateFormat on Android</action>
|
||||||
|
|
|
@ -26,8 +26,8 @@
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utilities for working with {@link Field}s by reflection. Adapted and refactored from the dormant [reflect] Commons sandbox
|
* Utilities for working with {@link Field}s by reflection. Adapted and refactored from the dormant [reflect] Commons
|
||||||
* component.
|
* sandbox component.
|
||||||
* <p>
|
* <p>
|
||||||
* The ability is provided to break the scoping restrictions coded by the programmer. This can allow fields to be
|
* The ability is provided to break the scoping restrictions coded by the programmer. This can allow fields to be
|
||||||
* changed that shouldn't be. This facility should be used with care.
|
* changed that shouldn't be. This facility should be used with care.
|
||||||
|
@ -40,7 +40,8 @@ public class FieldUtils {
|
||||||
/**
|
/**
|
||||||
* {@link FieldUtils} instances should NOT be constructed in standard programming.
|
* {@link FieldUtils} instances should NOT be constructed in standard programming.
|
||||||
* <p>
|
* <p>
|
||||||
* This constructor is {@code public} to permit tools that require a JavaBean instance to operate.</p>
|
* This constructor is {@code public} to permit tools that require a JavaBean instance to operate.
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
public FieldUtils() {
|
public FieldUtils() {
|
||||||
super();
|
super();
|
||||||
|
@ -73,12 +74,12 @@ public static Field getField(final Class<?> cls, final String fieldName) {
|
||||||
* the field name to obtain
|
* the field name to obtain
|
||||||
* @param forceAccess
|
* @param forceAccess
|
||||||
* whether to break scope restrictions using the
|
* whether to break scope restrictions using the
|
||||||
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method.
|
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. {@code false} will only
|
||||||
* {@code false} will only match {@code public} fields.
|
* match {@code public} fields.
|
||||||
* @return the Field object
|
* @return the Field object
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if the class is {@code null}, or the field name is blank or empty or is matched at
|
* if the class is {@code null}, or the field name is blank or empty or is matched at multiple places
|
||||||
* multiple places in the inheritance hierarchy
|
* in the inheritance hierarchy
|
||||||
*/
|
*/
|
||||||
public static Field getField(final Class<?> cls, final String fieldName, final boolean forceAccess) {
|
public static Field getField(final Class<?> cls, final String fieldName, final boolean forceAccess) {
|
||||||
Validate.isTrue(cls != null, "The class must not be null");
|
Validate.isTrue(cls != null, "The class must not be null");
|
||||||
|
@ -156,8 +157,8 @@ public static Field getDeclaredField(final Class<?> cls, final String fieldName)
|
||||||
* the field name to obtain
|
* the field name to obtain
|
||||||
* @param forceAccess
|
* @param forceAccess
|
||||||
* whether to break scope restrictions using the
|
* whether to break scope restrictions using the
|
||||||
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method.
|
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. {@code false} will only
|
||||||
* {@code false} will only match {@code public} fields.
|
* match {@code public} fields.
|
||||||
* @return the Field object
|
* @return the Field object
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if the class is {@code null}, or the field name is blank or empty
|
* if the class is {@code null}, or the field name is blank or empty
|
||||||
|
@ -265,8 +266,8 @@ public static Object readStaticField(final Field field, final boolean forceAcces
|
||||||
* the field name to obtain
|
* the field name to obtain
|
||||||
* @return the value of the field
|
* @return the value of the field
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if the class is {@code null}, or the field name is blank or empty,
|
* if the class is {@code null}, or the field name is blank or empty, is not {@code static}, or could
|
||||||
* is not {@code static}, or could not be found
|
* not be found
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* if the field is not accessible
|
* if the field is not accessible
|
||||||
*/
|
*/
|
||||||
|
@ -283,12 +284,12 @@ public static Object readStaticField(final Class<?> cls, final String fieldName)
|
||||||
* the field name to obtain
|
* the field name to obtain
|
||||||
* @param forceAccess
|
* @param forceAccess
|
||||||
* whether to break scope restrictions using the
|
* whether to break scope restrictions using the
|
||||||
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method.
|
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. {@code false} will only
|
||||||
* {@code false} will only match {@code public} fields.
|
* match {@code public} fields.
|
||||||
* @return the Field object
|
* @return the Field object
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if the class is {@code null}, or the field name is blank or empty,
|
* if the class is {@code null}, or the field name is blank or empty, is not {@code static}, or could
|
||||||
* is not {@code static}, or could not be found
|
* not be found
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* if the field is not made accessible
|
* if the field is not made accessible
|
||||||
*/
|
*/
|
||||||
|
@ -300,8 +301,8 @@ public static Object readStaticField(final Class<?> cls, final String fieldName,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value of a {@code static} {@link Field} by name. The field must be {@code public}.
|
* Gets the value of a {@code static} {@link Field} by name. The field must be {@code public}. Only the specified
|
||||||
* Only the specified class will be considered.
|
* class will be considered.
|
||||||
*
|
*
|
||||||
* @param cls
|
* @param cls
|
||||||
* the {@link Class} to reflect, must not be {@code null}
|
* the {@link Class} to reflect, must not be {@code null}
|
||||||
|
@ -309,8 +310,8 @@ public static Object readStaticField(final Class<?> cls, final String fieldName,
|
||||||
* the field name to obtain
|
* the field name to obtain
|
||||||
* @return the value of the field
|
* @return the value of the field
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if the class is {@code null}, or the field name is blank or empty,
|
* if the class is {@code null}, or the field name is blank or empty, is not {@code static}, or could
|
||||||
* is not {@code static}, or could not be found
|
* not be found
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* if the field is not accessible
|
* if the field is not accessible
|
||||||
*/
|
*/
|
||||||
|
@ -319,8 +320,7 @@ public static Object readDeclaredStaticField(final Class<?> cls, final String fi
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value of a {@code static} {@link Field} by name.
|
* Gets the value of a {@code static} {@link Field} by name. Only the specified class will be considered.
|
||||||
* Only the specified class will be considered.
|
|
||||||
*
|
*
|
||||||
* @param cls
|
* @param cls
|
||||||
* the {@link Class} to reflect, must not be {@code null}
|
* the {@link Class} to reflect, must not be {@code null}
|
||||||
|
@ -328,12 +328,12 @@ public static Object readDeclaredStaticField(final Class<?> cls, final String fi
|
||||||
* the field name to obtain
|
* the field name to obtain
|
||||||
* @param forceAccess
|
* @param forceAccess
|
||||||
* whether to break scope restrictions using the
|
* whether to break scope restrictions using the
|
||||||
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method.
|
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. {@code false} will only
|
||||||
* {@code false} will only match {@code public} fields.
|
* match {@code public} fields.
|
||||||
* @return the Field object
|
* @return the Field object
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if the class is {@code null}, or the field name is blank or empty,
|
* if the class is {@code null}, or the field name is blank or empty, is not {@code static}, or could
|
||||||
* is not {@code static}, or could not be found
|
* not be found
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* if the field is not made accessible
|
* if the field is not made accessible
|
||||||
*/
|
*/
|
||||||
|
@ -396,8 +396,7 @@ public static Object readField(final Field field, final Object target, final boo
|
||||||
* the field name to obtain
|
* the field name to obtain
|
||||||
* @return the value of the field
|
* @return the value of the field
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if the class is {@code null}, or
|
* if the class is {@code null}, or the field name is blank or empty or could not be found
|
||||||
* the field name is blank or empty or could not be found
|
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* if the named field is not {@code public}
|
* if the named field is not {@code public}
|
||||||
*/
|
*/
|
||||||
|
@ -414,12 +413,11 @@ public static Object readField(final Object target, final String fieldName) thro
|
||||||
* the field name to obtain
|
* the field name to obtain
|
||||||
* @param forceAccess
|
* @param forceAccess
|
||||||
* whether to break scope restrictions using the
|
* whether to break scope restrictions using the
|
||||||
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method.
|
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. {@code false} will only
|
||||||
* {@code false} will only match {@code public} fields.
|
* match {@code public} fields.
|
||||||
* @return the field value
|
* @return the field value
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if {@code target} is {@code null}, or
|
* if {@code target} is {@code null}, or the field name is blank or empty or could not be found
|
||||||
* the field name is blank or empty or could not be found
|
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* if the named field is not made accessible
|
* if the named field is not made accessible
|
||||||
*/
|
*/
|
||||||
|
@ -427,7 +425,7 @@ public static Object readField(final Object target, final String fieldName, fina
|
||||||
Validate.isTrue(target != null, "target object must not be null");
|
Validate.isTrue(target != null, "target object must not be null");
|
||||||
final Class<?> cls = target.getClass();
|
final Class<?> cls = target.getClass();
|
||||||
final Field field = getField(cls, fieldName, forceAccess);
|
final Field field = getField(cls, fieldName, forceAccess);
|
||||||
Validate.isTrue(field != null, "Cannot locate field %s on %s" , fieldName, cls);
|
Validate.isTrue(field != null, "Cannot locate field %s on %s", fieldName, cls);
|
||||||
// already forced access above, don't repeat it here:
|
// already forced access above, don't repeat it here:
|
||||||
return readField(field, target, false);
|
return readField(field, target, false);
|
||||||
}
|
}
|
||||||
|
@ -441,8 +439,7 @@ public static Object readField(final Object target, final String fieldName, fina
|
||||||
* the field name to obtain
|
* the field name to obtain
|
||||||
* @return the value of the field
|
* @return the value of the field
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if {@code target} is {@code null}, or
|
* if {@code target} is {@code null}, or the field name is blank or empty or could not be found
|
||||||
* the field name is blank or empty or could not be found
|
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* if the named field is not {@code public}
|
* if the named field is not {@code public}
|
||||||
*/
|
*/
|
||||||
|
@ -459,12 +456,11 @@ public static Object readDeclaredField(final Object target, final String fieldNa
|
||||||
* the field name to obtain
|
* the field name to obtain
|
||||||
* @param forceAccess
|
* @param forceAccess
|
||||||
* whether to break scope restrictions using the
|
* whether to break scope restrictions using the
|
||||||
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method.
|
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. {@code false} will only
|
||||||
* {@code false} will only match public fields.
|
* match public fields.
|
||||||
* @return the Field object
|
* @return the Field object
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if {@code target} is {@code null}, or
|
* if {@code target} is {@code null}, or the field name is blank or empty or could not be found
|
||||||
* the field name is blank or empty or could not be found
|
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* if the field is not made accessible
|
* if the field is not made accessible
|
||||||
*/
|
*/
|
||||||
|
@ -472,7 +468,7 @@ public static Object readDeclaredField(final Object target, final String fieldNa
|
||||||
Validate.isTrue(target != null, "target object must not be null");
|
Validate.isTrue(target != null, "target object must not be null");
|
||||||
final Class<?> cls = target.getClass();
|
final Class<?> cls = target.getClass();
|
||||||
final Field field = getDeclaredField(cls, fieldName, forceAccess);
|
final Field field = getDeclaredField(cls, fieldName, forceAccess);
|
||||||
Validate.isTrue(field != null, "Cannot locate declared field %s.%s" , cls, fieldName);
|
Validate.isTrue(field != null, "Cannot locate declared field %s.%s", cls, fieldName);
|
||||||
// already forced access above, don't repeat it here:
|
// already forced access above, don't repeat it here:
|
||||||
return readField(field, target, false);
|
return readField(field, target, false);
|
||||||
}
|
}
|
||||||
|
@ -485,8 +481,7 @@ public static Object readDeclaredField(final Object target, final String fieldNa
|
||||||
* @param value
|
* @param value
|
||||||
* to set
|
* to set
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if the field is {@code null} or not {@code static},
|
* if the field is {@code null} or not {@code static}, or {@code value} is not assignable
|
||||||
* or {@code value} is not assignable
|
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* if the field is not {@code public} or is {@code final}
|
* if the field is not {@code public} or is {@code final}
|
||||||
*/
|
*/
|
||||||
|
@ -503,18 +498,17 @@ public static void writeStaticField(final Field field, final Object value) throw
|
||||||
* to set
|
* to set
|
||||||
* @param forceAccess
|
* @param forceAccess
|
||||||
* whether to break scope restrictions using the
|
* whether to break scope restrictions using the
|
||||||
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. {@code false}
|
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. {@code false} will only
|
||||||
* will only match {@code public} fields.
|
* match {@code public} fields.
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if the field is {@code null} or not {@code static},
|
* if the field is {@code null} or not {@code static}, or {@code value} is not assignable
|
||||||
* or {@code value} is not assignable
|
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* if the field is not made accessible or is {@code final}
|
* if the field is not made accessible or is {@code final}
|
||||||
*/
|
*/
|
||||||
public static void writeStaticField(final Field field, final Object value, final boolean forceAccess) throws IllegalAccessException {
|
public static void writeStaticField(final Field field, final Object value, final boolean forceAccess) throws IllegalAccessException {
|
||||||
Validate.isTrue(field != null, "The field must not be null");
|
Validate.isTrue(field != null, "The field must not be null");
|
||||||
Validate.isTrue(Modifier.isStatic(field.getModifiers()), "The field %s.%s is not static",
|
Validate.isTrue(Modifier.isStatic(field.getModifiers()), "The field %s.%s is not static", field.getDeclaringClass().getName(),
|
||||||
field.getDeclaringClass().getName(), field.getName());
|
field.getName());
|
||||||
writeField(field, (Object) null, value, forceAccess);
|
writeField(field, (Object) null, value, forceAccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -528,10 +522,8 @@ public static void writeStaticField(final Field field, final Object value, final
|
||||||
* @param value
|
* @param value
|
||||||
* to set
|
* to set
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if {@code cls} is {@code null},
|
* if {@code cls} is {@code null}, the field name is blank or empty, the field cannot be located or is
|
||||||
* the field name is blank or empty,
|
* not {@code static}, or {@code value} is not assignable
|
||||||
* the field cannot be located or is not {@code static}, or
|
|
||||||
* {@code value} is not assignable
|
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* if the field is not {@code public} or is {@code final}
|
* if the field is not {@code public} or is {@code final}
|
||||||
*/
|
*/
|
||||||
|
@ -550,13 +542,11 @@ public static void writeStaticField(final Class<?> cls, final String fieldName,
|
||||||
* to set
|
* to set
|
||||||
* @param forceAccess
|
* @param forceAccess
|
||||||
* whether to break scope restrictions using the
|
* whether to break scope restrictions using the
|
||||||
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method.
|
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. {@code false} will only
|
||||||
* {@code false} will only match {@code public} fields.
|
* match {@code public} fields.
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if {@code cls} is {@code null},
|
* if {@code cls} is {@code null}, the field name is blank or empty, the field cannot be located or is
|
||||||
* the field name is blank or empty,
|
* not {@code static}, or {@code value} is not assignable
|
||||||
* the field cannot be located or is not {@code static}, or
|
|
||||||
* {@code value} is not assignable
|
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* if the field is not made accessible or is {@code final}
|
* if the field is not made accessible or is {@code final}
|
||||||
*/
|
*/
|
||||||
|
@ -578,10 +568,8 @@ public static void writeStaticField(final Class<?> cls, final String fieldName,
|
||||||
* @param value
|
* @param value
|
||||||
* to set
|
* to set
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if {@code cls} is {@code null},
|
* if {@code cls} is {@code null}, the field name is blank or empty, the field cannot be located or is
|
||||||
* the field name is blank or empty,
|
* not {@code static}, or {@code value} is not assignable
|
||||||
* the field cannot be located or is not {@code static}, or
|
|
||||||
* {@code value} is not assignable
|
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* if the field is not {@code public} or is {@code final}
|
* if the field is not {@code public} or is {@code final}
|
||||||
*/
|
*/
|
||||||
|
@ -602,10 +590,8 @@ public static void writeDeclaredStaticField(final Class<?> cls, final String fie
|
||||||
* whether to break scope restrictions using the {@code AccessibleObject#setAccessible(boolean)} method.
|
* whether to break scope restrictions using the {@code AccessibleObject#setAccessible(boolean)} method.
|
||||||
* {@code false} will only match {@code public} fields.
|
* {@code false} will only match {@code public} fields.
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if {@code cls} is {@code null},
|
* if {@code cls} is {@code null}, the field name is blank or empty, the field cannot be located or is
|
||||||
* the field name is blank or empty,
|
* not {@code static}, or {@code value} is not assignable
|
||||||
* the field cannot be located or is not {@code static}, or
|
|
||||||
* {@code value} is not assignable
|
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* if the field is not made accessible or is {@code final}
|
* if the field is not made accessible or is {@code final}
|
||||||
*/
|
*/
|
||||||
|
@ -627,8 +613,7 @@ public static void writeDeclaredStaticField(final Class<?> cls, final String fie
|
||||||
* @param value
|
* @param value
|
||||||
* to set
|
* to set
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* if the field or target is {@code null},
|
* if the field or target is {@code null}, the field is not accessible or is {@code final}, or
|
||||||
* the field is not accessible or is {@code final}, or
|
|
||||||
* {@code value} is not assignable
|
* {@code value} is not assignable
|
||||||
*/
|
*/
|
||||||
public static void writeField(final Field field, final Object target, final Object value) throws IllegalAccessException {
|
public static void writeField(final Field field, final Object target, final Object value) throws IllegalAccessException {
|
||||||
|
@ -646,11 +631,10 @@ public static void writeField(final Field field, final Object target, final Obje
|
||||||
* to set
|
* to set
|
||||||
* @param forceAccess
|
* @param forceAccess
|
||||||
* whether to break scope restrictions using the
|
* whether to break scope restrictions using the
|
||||||
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method.
|
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. {@code false} will only
|
||||||
* {@code false} will only match {@code public} fields.
|
* match {@code public} fields.
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if the field is {@code null} or
|
* if the field is {@code null} or {@code value} is not assignable
|
||||||
* {@code value} is not assignable
|
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* if the field is not made accessible or is {@code final}
|
* if the field is not made accessible or is {@code final}
|
||||||
*/
|
*/
|
||||||
|
@ -674,23 +658,44 @@ public static void writeField(final Field field, final Object target, final Obje
|
||||||
* if the field is {@code null}
|
* if the field is {@code null}
|
||||||
*/
|
*/
|
||||||
public static void removeFinalModifier(Field field) {
|
public static void removeFinalModifier(Field field) {
|
||||||
|
removeFinalModifier(field, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the final modifier from a {@link Field}.
|
||||||
|
*
|
||||||
|
* @param field
|
||||||
|
* to remove the final modifier
|
||||||
|
* @param forceAccess
|
||||||
|
* whether to break scope restrictions using the
|
||||||
|
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. {@code false} will only
|
||||||
|
* match {@code public} fields.
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
* if the field is {@code null}
|
||||||
|
*/
|
||||||
|
public static void removeFinalModifier(Field field, boolean forceAccess) {
|
||||||
Validate.isTrue(field != null, "The field must not be null");
|
Validate.isTrue(field != null, "The field must not be null");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (Modifier.isFinal(field.getModifiers())) {
|
if (Modifier.isFinal(field.getModifiers())) {
|
||||||
// Do all JREs implement Field with a private ivar called "modifiers"?
|
// Do all JREs implement Field with a private ivar called "modifiers"?
|
||||||
Field modifiersField = Field.class.getDeclaredField("modifiers");
|
Field modifiersField = Field.class.getDeclaredField("modifiers");
|
||||||
modifiersField.setAccessible(true);
|
final boolean doForceAccess = forceAccess && !modifiersField.isAccessible();
|
||||||
|
if (doForceAccess) {
|
||||||
|
modifiersField.setAccessible(true);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
|
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
|
||||||
} finally {
|
} finally {
|
||||||
modifiersField.setAccessible(false);
|
if (doForceAccess) {
|
||||||
|
modifiersField.setAccessible(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (NoSuchFieldException ignored) {
|
} catch (NoSuchFieldException ignored) {
|
||||||
// The field class contains always a modifiers field
|
// The field class contains always a modifiers field
|
||||||
} catch (IllegalAccessException ignored) {
|
} catch (IllegalAccessException ignored) {
|
||||||
// The modifiers field is made accessible
|
// The modifiers field is made accessible
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -704,9 +709,8 @@ public static void removeFinalModifier(Field field) {
|
||||||
* @param value
|
* @param value
|
||||||
* to set
|
* to set
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if {@code target} is {@code null},
|
* if {@code target} is {@code null}, {@code fieldName} is blank or empty or could not be found, or
|
||||||
* {@code fieldName} is blank or empty or could not be found,
|
* {@code value} is not assignable
|
||||||
* or {@code value} is not assignable
|
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* if the field is not accessible
|
* if the field is not accessible
|
||||||
*/
|
*/
|
||||||
|
@ -725,12 +729,11 @@ public static void writeField(final Object target, final String fieldName, final
|
||||||
* to set
|
* to set
|
||||||
* @param forceAccess
|
* @param forceAccess
|
||||||
* whether to break scope restrictions using the
|
* whether to break scope restrictions using the
|
||||||
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. {@code false}
|
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. {@code false} will only
|
||||||
* will only match {@code public} fields.
|
* match {@code public} fields.
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if {@code target} is {@code null},
|
* if {@code target} is {@code null}, {@code fieldName} is blank or empty or could not be found, or
|
||||||
* {@code fieldName} is blank or empty or could not be found,
|
* {@code value} is not assignable
|
||||||
* or {@code value} is not assignable
|
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* if the field is not made accessible
|
* if the field is not made accessible
|
||||||
*/
|
*/
|
||||||
|
@ -754,9 +757,8 @@ public static void writeField(final Object target, final String fieldName, final
|
||||||
* @param value
|
* @param value
|
||||||
* to set
|
* to set
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if {@code target} is {@code null},
|
* if {@code target} is {@code null}, {@code fieldName} is blank or empty or could not be found, or
|
||||||
* {@code fieldName} is blank or empty or could not be found,
|
* {@code value} is not assignable
|
||||||
* or {@code value} is not assignable
|
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* if the field is not made accessible
|
* if the field is not made accessible
|
||||||
*/
|
*/
|
||||||
|
@ -775,12 +777,11 @@ public static void writeDeclaredField(final Object target, final String fieldNam
|
||||||
* to set
|
* to set
|
||||||
* @param forceAccess
|
* @param forceAccess
|
||||||
* whether to break scope restrictions using the
|
* whether to break scope restrictions using the
|
||||||
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method.
|
* {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} method. {@code false} will only
|
||||||
* {@code false} will only match {@code public} fields.
|
* match {@code public} fields.
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if {@code target} is {@code null},
|
* if {@code target} is {@code null}, {@code fieldName} is blank or empty or could not be found, or
|
||||||
* {@code fieldName} is blank or empty or could not be found,
|
* {@code value} is not assignable
|
||||||
* or {@code value} is not assignable
|
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* if the field is not made accessible
|
* if the field is not made accessible
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1256,8 +1256,10 @@ public void testAmbig() {
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveFinalModifier() throws Exception {
|
public void testRemoveFinalModifier() throws Exception {
|
||||||
Field field = StaticContainer.class.getDeclaredField("IMMUTABLE_PRIVATE_2");
|
Field field = StaticContainer.class.getDeclaredField("IMMUTABLE_PRIVATE_2");
|
||||||
|
assertFalse(field.isAccessible());
|
||||||
assertTrue(Modifier.isFinal(field.getModifiers()));
|
assertTrue(Modifier.isFinal(field.getModifiers()));
|
||||||
FieldUtils.removeFinalModifier(field);
|
FieldUtils.removeFinalModifier(field);
|
||||||
assertFalse(Modifier.isFinal(field.getModifiers()));
|
assertFalse(Modifier.isFinal(field.getModifiers()));
|
||||||
|
assertFalse(field.isAccessible());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue