Download the JDK
Search the Tutorials
Hide the TOC
Trail: The Reflection API
Lesson: Classes
Section: Sealing Packages in Extensions
Classes
Retrieving Class Objects
Examining Class Modifiers and Types
Discovering Class Members
Troubleshooting
Home Page > The Reflection API > Classes
Troubleshooting

> The following examples show typical errors which may be encountered when reflecting on classes.

> ### Compiler Warning: "Note: ... uses unchecked or unsafe operations"

> When a method is invoked, the types of the argument values are checked and possibly converted. ``ClassWarning`` invokes `getMethod()` to cause a typical unchecked conversion warning:

> >     import java.lang.reflect.Method;

> >     public class ClassWarning {
> >         void m() {
> >     	try {
> >     	    Class c = ClassWarning.class;
> >     	    Method m = c.getMethod("m");  // warning

> >             // production code should handle this exception more gracefully
> >     	} catch (NoSuchMethodException x) {
> >         	    x.printStackTrace();
> >         	}
> >         }
> >     }

> >     $ javac ClassWarning.java
> >     Note: ClassWarning.java uses unchecked or unsafe operations.
> >     Note: Recompile with -Xlint:unchecked for details.
> >     $ javac -Xlint:unchecked ClassWarning.java
> >     ClassWarning.java:7: warning: [unchecked] unchecked call to getMethod(java.lang.String,java.lang.Class<?>...) as a member of the raw type java.lang.Class
> >                 Method m = c.getMethod("m");  // warning
> >                                       ^
> >     1 warning

> Many library methods have been retrofitted with generic declarations including several in `Class`. Since `c` is declared as a raw type (has no type parameters) and the corresponding parameter of `getMethod()` is a parameterized type, an unchecked conversion occurs. The compiler is required to generate a warning. (See The Java Language Specification, Third Edition, sections 5.1.9 and 5.3.)

> There are two possible solutions. The more preferable it to modify the declaration of `c` to include an appropriate generic type. In this case, the declaration should be:

> >     Class<?> c = warn.getClass();

> Alternatively, the warning could be explicitly suppressed using the predefined annotation `@SuppressWarnings` preceding the problematic statement.

> >     Class c = ClassWarning.class;
> >     @SuppressWarnings("unchecked")
> >     Method m = c.getMethod("m");  // warning gone

> > Tip: As a general principle, warnings should not be ignored as they may indicate the presence of a bug. Parameterized declarations should be used as appropriate. If that is not possible (perhaps because an application must interact with a library vendor's code), annotate the offending line using `@SuppressWarnings`.

> ### InstantiationException when the Constructor is Not Accessible

> `Class.newInstance()` will throw an `InstantiationException` if an attempt is made to create a new instance of the class and the zero-argument constructor is not visible. The ``ClassTrouble`` example illustrates the resulting stack trace.

> >     class Cls {
> >         private Cls() {}
> >     }

> >     public class ClassTrouble {
> >         public static void main(String... args) {
> >     	try {
> >     	    Class<?> c = Class.forName("Cls");
> >     	    c.newInstance();  // InstantiationException

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

> >     $ java ClassTrouble
> >     java.lang.IllegalAccessException: Class ClassTrouble can not access a member of
> >     class Cls with modifiers "private"
> >             at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)
> >             at java.lang.Class.newInstance0(Class.java:349)
> >             at java.lang.Class.newInstance(Class.java:308)
> >             at ClassTrouble.main(ClassTrouble.java:9)

> `Class.newInstance()` behaves very much like the `new` keyword and will fail for the same reasons `new` would fail. The typical solution in reflection is to take advantage of the `java.lang.reflect.AccessibleObject` class which provides the ability to suppress access control checks; however, this approach will not work because `java.lang.Class` does not extend `AccessibleObject`. The only solution is to modify the code to use `Constructor.newInstance()` which does extend `AccessibleObject`.

> > Tip: In general, it is preferable to use `Constructor.newInstance()` for the reasons described in the Creating New Class Instances section in the Members lesson.

> Additional examples of potential problems using `Constructor.newInstance()` may be found in the Constructor Troubleshooting section of the Members lesson.

Previous page: Discovering Class Members
Next page: Members