Java Reference
In-Depth Information
hashCode method is invoked with a qualifying type that is inaccessible to the client. The qualifying
type of the method invocation is library.Api.PackagePrivate , which is a nonpublic class in a
different package.
This does not imply that Client can't invoke hashCode on Api.member . To do this, it has merely to
use an accessible qualifying type, which it can do by casting Api.member to Object . With this
change, Client compiles and runs successfully:
System.out.println(( (Object) Api.member).hashCode());
As a practical matter, this problem doesn't arise in ordinary nonreflective access, because API
writers use only public types in their public APIs. Even if the problem were to occur, it would
manifest itself as a compile-time error, so it would be fixed quickly and easily. Reflective access is
another matter. Although common, the idiom object.getClass().getMethod("methodName") is
broken and should not be used. It can easily result in an IllegalAccessException at run time, as
we saw in the original program.
When accessing a type reflectively, use a Class object that represents an accessible type. Going
back to our original program, the hasNext method is declared in the public type
java.util.Iterator , so its class object should be used for reflective access. With this change, the
Reflector program prints TRue as expected:
Method m = Iterator .class.getMethod("hasNext");
You can avoid this whole category of problem if you use reflection only for instantiation and use
interfaces to invoke methods [EJ Item 35]. This use of reflection isolates the class that invokes
methods from the class that implements them and provides a high degree of type-safety. It is
commonly used in Service Provider Frameworks. This pattern does not solve every problem that
demands reflective access, but if it solves your problem, by all means use it.
In summary, it is illegal to access a member of a nonpublic type in a different package, even if the
member is also declared public in a public type. This is true whether the member is accessed
normally or reflectively. The problem is likely to manifest itself only in reflective access. For
platform designers, the lesson, as in Puzzle 67 , is to make diagnostics as clear as possible. Both the
runtime exception and the compiler diagnostic leave something to be desired.
 
 
Search WWH ::




Custom Search