Wednesday, June 15, 2005

Java is wierd

It all began when I wrote a simple class with overloaded methods:


public abstract Object apply (Object obj);

public Object apply (Collection collection)
{
for (Iterator i = collection.iterator (); i.hasNext(); )
{
apply (i.next());
}
return this;
}

Note that the first version is abstract (as was the class, of course). The second method, which takes a Collection and applies the first method on each item. The intent is that you extend the class and provide a implemetation of the abstract method. Invoking the apply (Collection) method will invoke your apply (Object) over the collection. Seemed simple enough to me. My unit tests green barred, so I was ready to plug the code into the project.

I get a compilation error. Huh? I run my unit tests again. Green bar. Now I'm confused. I isolate the offending code into a sandbox environment. and repeated the above. Unit tests green bar; code fails to compile. Now wait a minute. To run a unit test, the code has to compile, correct? Stop and think.

So, here's the situation. When I wrote the code in Eclipse, it gave no errors. Ecplise compiles in the background; so my code does compile. When I build the project I run an Ant build script (started from Eclipse, usually). That build script reports the following:

[javac] C:\John\Closures\src\functor\ClosureTest.java:138: reference to apply is ambiguous, both method apply java.util.Collection) in functor.Closure and method apply(java.lang.Object) in match
[javac] new BufferedClosure ()

So Eclipse thinks my code is good; javac disagrees. That's just dandy, right?

As the practical person I am, I did the quick fix; rename apply (Collection) to applyAll (Collection). Project build works and we are back on track. I have no peace, however, until I understand what is going on.

The answer turns up after some googling. It's a bug; Bug Id 4761586. Furthermore, it's fixed in java 1.5, and interstingly enough, the fix was quietly back ported to 1.4.2. There is a discussion of the issues in the JDJ article, Overloaded Method Matching. (Published Oct 2003 -- how did I miss it?).

The current project is locked down to 1.4.1 — where it is definitely not fixed. Another thing is that Bug Id 4761586 (and it's resolution) refers to "the class in which an overloaded method is declared (the 'declaring class')". Now my two methods were declared in the same class; even if one was first defined in the extending class. As far as I can figure it out, that's a compiler bug, even according to wording of the old spec. which, as the above mentioned article declares, "was simply a mistake in the original specification" with "no logical explanation".

Java is wierd.

Category: Software, Programming, Java

0 Comments:

Post a Comment

<< Home