We have a class LogManager in our Java project which looks like this:
public class LogManager {
public void log(Level logLevel, Object... args) {
// do something
}
public void log(Level logLevel, int value, Object... args) {
// do something else
}
}
When compiling the project with OpenJDK 6 under Debian everyting works fine. When using OpenJDK 7 the build (done with ant) produces the following errors and the build fails:
[javac] /…/LogManager.java:123: error: reference to log is ambiguous,
both method log(Level,Object...) in LogManager
and method log(Level,int,Object...) in LogManager match
[javac] log(logLevel, 1, logMessage);
[javac] ^
[javac] /…/SomeOtherClass.java:123: error: reference to log is ambiguous,
both method log(Level,Object...) in LogManager
and method log(Level,int,Object...) in LogManager match
[javac] logger.log(logLevel, 1, logMessage);
[javac] ^
As long as the 1 is not autoboxed, the method call should be unambiguous as 1 is an int and cannot be upcast to Object. So why doesn't autoboxing overrule varargs here?
Eclipse (installed using the tar.gz from eclipse.org) compiles it no matter if OpenJDK 6 is installed or not.
Thank's a lot for your help!
Edit:
The compiler gets the option source="1.6"
and target="1.6"
in both cases. The Eclipse compiling note is just meant as a comment.
This is skating way closer to the edge than is prudent. Unless you can find clear language in the spec as to behavior, I'd avoid anything ambiguous like this.
Even if it is in the spec, readers of your code won't have done the language lawyering to know, so you'll need to comment it to explain, and they may or may not read the comment. They may not even consider one of the alternatives - just see one overload that fits, and run with that. An accident waiting to happen.
Eclipse uses it's own compiler, so what Eclipse does eventually follows what the SUN / Oracle provided compilers does; however, sometimes (like in this case) there are differences.
This could "go either way" and probably in Java 6, the issue wasn't addressed in detail. Since Java has a strong requirement to reduce the number of "ambiguous" meanings in its environment (to enforce same behavior across many platforms), I'd imagine that they tightened up (or directly specified) the decided behavior in the 7 release.
You just got caught on the "wrong" side of new specification clarification. Sorry, but I think you'll be writing a bit of this
into your new solution.
I guess it's related to bug #6886431, which seems to be fixed in OpenJDK 7 as well.
The problem is that JLS 15.12.2.5 Choosing the Most Specific Method says that one method is more specific than another one when types of formal parameters of the former are subtypes of formal parameters of the latter.
Since
int
is not a subtype ofObject
, neither of your methods is the most specific, thus your invocation is ambiguous.However, the following workaround is possible, because
Integer
is a subtype ofObject
: