Download the JDK
Search the Tutorials
Hide the TOC
Trail: The Reflection API
Lesson: Members
Section: Fields
Members
Fields
Obtaining Field Types
Retrieving and Parsing Field Modifiers
Getting and Setting Field Values
Troubleshooting
Methods
Obtaining Method Type Information
Retrieving and Parsing Method Modifiers
Invoking Methods
Troubleshooting
Constructors
Finding Constructors
Retrieving and Parsing Constructor Modifiers
Creating New Class Instances
Troubleshooting
Home Page > The Reflection API > Members
Troubleshooting

> Here are a few common problems encountered by developers with explanations for why the occur and how to resolve them.

> ### IllegalArgumentException due to Inconvertible Types

> The ``FieldTrouble`` example will generate an `IllegalArgumentException`. `Field.setInt()` is invoked to set a field that is of the reference type `Integer` with a value of primitive type. In the non-reflection equivalent `Integer val = 42`, the compiler would convert (or box) the primitive type `42` to a reference type as `new Integer(42)` so that its type checking will accept the statement. When using reflection, type checking only occurs at runtime so there is no opportunity to box the value.

> >     import java.lang.reflect.Field;

> >     public class FieldTrouble {
> >         public Integer val;

> >         public static void main(String... args) {
> >     	FieldTrouble ft = new FieldTrouble();
> >     	try {
> >     	    Class<?> c = ft.getClass();
> >     	    Field f = c.getDeclaredField("val");
> >       	    f.setInt(ft, 42);               // IllegalArgumentException

> >             // production code should handle these exceptions more gracefully
> >     	} catch (NoSuchFieldException x) {
> >     	    x.printStackTrace();
> >      	} catch (IllegalAccessException x) {
> >      	    x.printStackTrace();
> >     	}
> >         }
> >     }

> >     $ java FieldTrouble
> >     Exception in thread "main" java.lang.IllegalArgumentException: Can not set
> >     java.lang.Object field FieldTrouble.val to (long)42
> >             at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
> >             at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:174)
> >             at sun.reflect.UnsafeObjectFieldAccessorImpl.setLong(UnsafeObjectFieldAccessorImpl.java:102)
> >             at java.lang.reflect.Field.setLong(Field.java:831)
> >             at FieldTrouble.main(FieldTrouble.java:11)

> To eliminate this exception, the problematic line should be replaced by the following invocation of `Field.set(Object obj, Object value)`:

> >     f.set(ft, new Integer(43));

> > Tip: When using reflection to set or get a field, the compiler does not have an opportunity to perform boxing. It can only convert types that are related as described by the specification for `Class.isAssignableFrom()`. The example is expected to fail because `isAssignableFrom()` will return `false` in this test which can be used programmatically to verify whether a particular conversion is possible:

> > >     Integer.class.isAssignableFrom(int.class) == false

> > Similarly, automatic conversion from primitive to reference type is also impossible in reflection.

> > >     int.class.isAssignableFrom(Integer.class) == false

> ### NoSuchFieldException for Non-Public Fields

> The astute reader may notice that if the ``FieldSpy`` example shown earlier is used to get information on a non-public field, it will fail:

> >     $ java FieldSpy java.lang.String count
> >     java.lang.NoSuchFieldException: count
> >             at java.lang.Class.getField(Class.java:1519)
> >             at FieldSpy.main(FieldSpy.java:12)

> > Tip: The `Class.getField()` and `Class.getFields()` methods return the public member field(s) of the class, enum, or interface represented by the `Class` object. To retrieve all fields declared (but not inherited) in the `Class`, use the `Class.getDeclaredFields()` method.

> ### IllegalAccessException when Modifying Final Fields

> An `IllegalAccessException` may be thrown if an attempt is made to get or set the value of a `private` or otherwise inaccessible field or to set the value of a `final` field (regardless of its access modifiers).

> The ``FieldTroubleToo`` example illustrates the type of stack trace which results from attempting to set a final field.

> >     import java.lang.reflect.Field;

> >     public class FieldTroubleToo {
> >         public final boolean b = true;

> >         public static void main(String... args) {
> >     	FieldTroubleToo ft = new FieldTroubleToo();
> >     	try {
> >     	    Class<?> c = ft.getClass();
> >     	    Field f = c.getDeclaredField("b");
> >     // 	    f.setAccessible(true);  // solution
> >     	    f.setBoolean(ft, Boolean.FALSE);   // IllegalAccessException

> >             // production code should handle these exceptions more gracefully
> >     	} catch (NoSuchFieldException x) {
> >     	    x.printStackTrace();
> >     	} catch (IllegalArgumentException x) {
> >     	    x.printStackTrace();
> >     	} catch (IllegalAccessException x) {
> >     	    x.printStackTrace();
> >     	}
> >         }
> >     }

> >     $ java FieldTroubleToo
> >     java.lang.IllegalAccessException: Can not set final boolean field FieldTroubleToo.b to (boolean)false
> >             at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:55)
> >             at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:63)
> >             at sun.reflect.UnsafeQualifiedBooleanFieldAccessorImpl.setBoolean(UnsafeQualifiedBooleanFieldAccessorImpl.java:78)
> >             at java.lang.reflect.Field.setBoolean(Field.java:686)
> >             at FieldTroubleToo.main(FieldTroubleToo.java:12)

> > Tip: An access restriction exists which prevents `final` fields from being set after initialization of the class. However, `Field` is declared to extend `AccessibleObject` which provides the ability to suppress this check.

> > If `AccessibleObject.setAccessible()` succeeds, then subsequent operations on this field value will not fail do to this problem. This may have unexpected side-effects; for example, sometimes the original value will continue to be used by some sections of the application even though the value has been modified. `AccessibleObject.setAccessible()` will only succeed if the operation is allowed by the security context.

Previous page: Getting and Setting Field Values
Next page: Methods