Reflection in 1.5


M

Mike Schilling

Before 1.5, a class could only have one method with a given list of argument
types. [1] Therefore, the behavior of Class.getDeclaredMethod() (and
lilkewise getMethod()) was simple: it would return that method, if it
existed, and throw an exception otherwise.

In 1.5, the implementation of covariant return types can result in there
being more than one such method. The Javadoc for getDeclaredMethod() (and
getMethod()) says

If more than one method with the same parameter
types is declared in a class, and one of these methods
has a return type that is more specific than any of the others,
that method is returned; otherwise one of the methods is chosen
arbitrarily.

Two questions:

First, can anyone construct, in Java, a situation where the "otherwise"
applies?

I tried the following:

public interface Int1
{
Int1 meth();
}

public interface Int2
{
Int2 meth();
}

public abstract class Class1 implements Int1, Int2
{
}

I thought this might give Class1 two versions of meth(), neither of which
dominates the other, but it results in the error "types Int2 and Int1 are
incompatible; both define meth(), but with unrelated return types". This
seems like an odd restriction for interfaces: it says to me merely that a
subclass of Class1 which defines meth() must have it return a type which
implements both Int1 and Int2. In fact, if I change Class 1 to

public abstract class Class1 implements Int1, Int2
{
public Class1 meth()
{
return null;
}
}

it compiles OK, although

public abstract class Class1 implements Int1, Int2
{
public abstract Class1 meth();
}

gives the same error.

Anyway, it seems to me that in the "otherwise" case, a call using those
argument types would be ambiguous; surely the compiler wouldn't choose an
arbitrary overload to call. [2] Therefore, either

A. It can only occur for classes in which the methods is abstract, or
B. The compiler allows situations where calls would be ambiguous so long as
these calls are not made.

Second, can anything be assumed about the arbitrarily chosen method, e.g.
will it always be the same method within a JVM execution, or across
executions of the same JVM implementation?

1. I think that was a Java restriction, not a JVM restriction, but either
way, it was something you could rely on.

2. Or would it, since the Java compiler does ensure that all the overloads
have the same effect? I hope not.
 
Ad

Advertisements

C

Chris Uppal

Mike said:
In 1.5, the implementation of covariant return types can result in there
being more than one such method.

So can generics, as in the following example:

======
interface Creepy<X>
{
X method();
}
class Test
implements Creepy<String>
{
public String method() { return "ugh!"; }
}
======

where the compiler must synthesise a
public Object method()
in order to satisfy the contract defined by the interface (after erasure).

The Javadoc for getDeclaredMethod() (and
getMethod()) says

If more than one method with the same parameter
types is declared in a class, and one of these methods
has a return type that is more specific than any of the others,
that method is returned; otherwise one of the methods is chosen
arbitrarily.

Two questions:

First, can anyone construct, in Java, a situation where the "otherwise"
applies?

I haven't been able to do so, and I don't see how either the convariant return
hack, or the creepy generics hack, can ever require it. So I read your quoted
paragraph as saying, in essence:

If the class was generated by Sun(tm)'s javac then getMethod() will
choose the method you might naively have thought was "the"
method. (And if not, then all bets are off.)

I can understand why the authors choose to use a different wording, though ;-)

BTW:
public interface Int1
{
Int1 meth();
}

public interface Int2
{
Int2 meth();
} [...]
public abstract class Class1 implements Int1, Int2
{
public Class1 meth()
{
return null;
}
}

it compiles OK, although

public abstract class Class1 implements Int1, Int2
{
public abstract Class1 meth();
}

gives the same error.

Odd. Not what I would have expected either. Possibly a bug, or it might be
justified by a close reading of the JLS -- but I have given up on the JLS (at
least for the time being).

-- chris
 

Top