PROPOSAL: Using Ordinary Syntax for Reflective Method Invocations
Lawrence Kesteloot
lk at teamten.com
Fri Mar 27 12:36:26 PDT 2009
Could you get rid of the Unknown marker type and use a different
syntax for method invocation?
> String s = o->getName("Foo", 3);
It would be allowed on any object. There would be no need to cast the
return value, it would be cast implicitly by the generated code and
throw an exception if it didn't match.
Lawrence
On Fri, Mar 27, 2009 at 12:25 PM, Alan Snyder <javalists at cbfiddle.com> wrote:
> Using Ordinary Syntax for Reflective Method Invocations
>
>
> AUTHOR: Alan Snyder
>
> OVERVIEW
>
> FEATURE SUMMARY:
>
> This proposal allows ordinary method invocation syntax to be used to issue
> a reflective method invocation, when enabled by the use of a new marker
> type for the target object.
>
> MAJOR ADVANTAGE:
>
> Invoking a method using the reflection API is tedious and verbose, and it
> does not look anything like the corresponding ordinary method invocation
> that would be used when the target class or interface is statically known.
> The proposal allows the ordinary method invocation syntax to be used
> instead to invoke a method using reflection.
>
> MAJOR BENEFIT:
>
> This proposal makes invoking methods using reflection much easier to write
> and also much more readable.
>
> When a programmer wants to avoid creating a static dependency on an
> optional module, one way to do so is to invoke the module using
> reflection. (Note that the target interface may be packaged with the rest
> of the module, so even a static reference to the target interface would
> create a dependency.) This proposal would make such loose couplings much
> simpler and more natural, and would also make it easier to change from
> tight coupling to loose coupling, or vice versa.
>
> MAJOR DISADVANTAGE:
>
> A small language change is required, involving the introduction of a new
> marker type and an extension of method invocation semantics to cover the
> new marker type.
>
> ALTERNATIVES:
>
> The major alternatives are to use an IDE or a (nonstandard) preprocessor
> to generate the appropriate calls on the reflection API. IDE generated
> code is easy to write but remains difficult to read. Preprocessors do not
> interact well with tools, especially debuggers.
>
> EXAMPLE:
>
> Here is a simple invocation of a method on an object whose type is not
> statically known. The type Unknown is the new marker type that signals the
> use of reflection to invoke methods on the object so declared.
>
> Unknown o = ...; // obtain object without referencing its class
> try {
> String s = (String) o.getName("Foo", 3);
> } catch (InvocationTargetException ex) {
> ... method threw an exception
> } catch (Exception ex) {
> ... could not find method, invoke method, or wrong result type
> }
>
> A more complex example might need to use a type cast to provide a type for
> a null argument:
>
> String s = (String) o.getName((String) null, 3);
>
> Another complex example would handle the various individual exceptions
> that can be raised:
>
> try {
> String s = (String) o.getName("Foo", 3);
> } catch (NoSuchMethodException ex) {
> ...
> } catch (SecurityException ex) {
> ...
> } catch (IllegalAccessException ex) {
> ...
> } catch (ExceptionInInitializerError ex) {
> ...
> } catch (InvocationTargetException ex) {
> ...
> } catch (ClassCastException ex) {
> ...
> }
>
> DETAILS
>
> The proposal requires the introduction of a new marker type, which I am
> calling Unknown. It could be new interface, perhaps in java.reflect. My
> thought is that extending this interface probably should not be allowed,
> as it would seem pointless.
>
> The Unknown type is used by the programmer to indicate a desire to perform
> reflective invocations on an object whose type is not statically known. It
> is thus different than Object (despite having the same set of declared
> methods), where no such intent is implied. Thus, there is no relaxation of
> static type checking in programs that do not explicitly use this new
> feature.
>
> When the compiler encounters a method invocation where the static type of
> the target object expression is Unknown, it replaces the static invocation
> with the equivalent reflection code, something like this:
>
> {
> Class c = o.getClass();
> Class c1 = String.class;
> Class c2 = Integer.class;
> Method m = c.getMethod("getName", c1, c2);
> Object arg1 = "Foo";
> Object arg2 = 3;
> String s = (String) m.invoke(o, arg1, arg2);
> }
>
> The Class objects used in the method lookup are determined based on the
> expression types of the invocation argument expressions, not the runtime
> types of the argument objects. (The latter would fail to handle null
> arguments, for example.) As in the above example, the null literal could
> not be used without a type cast. I do not claim to have full command of
> the type system vocabulary, but it seems to me that the process is roughly
> equivalent to creating a class literal based on the result of type
> erasure.
>
> SPECIFICATION:
>
> JLS 15.12.1 would need to be changed to recognize this new case.
> Specifically, this clause:
>
> If the form is Primary.NonWildTypeArgumentsopt Identifier, then the
> name of the method is the Identifier. Let T be the type of the Primary
> expression; then the class or interface to be searched is T if T is a
> class or interface type, or the upper bound of T if T is a type
> variable.
>
> would be extended as follows:
>
> If the form is Primary.NonWildTypeArgumentsopt Identifier, then the
> name of the method is the Identifier. Let T be the type of the Primary
> expression; then the class or interface to be searched is T if T is a
> class or interface type, or the upper bound of T if T is a type
> variable. However, if T is the interface Unknown, no search of that
> interface is performed. Instead, the method is determined at runtime
> by examining the class of the target object.
>
> Since the JLS does not define reflection, it is not clear to me whether
> the exact details would be specified in the JLS.
>
> COMPILATION:
>
> The compiler would have to implement this new case. I don't believe there
> are any new concepts involved. Debuggers should be changed to make the
> invocation look like an ordinary invocation.
>
> COMPATIBILITY
>
> The major compatibility issue arises from the introduction of a new name
> in the class name space. That could potentially cause a program to fail to
> compile if it imported a class with the name Unknown using a wild card
> import statement.
>
>
>
>
More information about the coin-dev
mailing list