java compiler-construction overloading variadic-functions autoboxing

¿Por qué el autoboxing no anula las varargs cuando se utiliza la sobrecarga de métodos en Java 7?



compiler-construction overloading (3)

Eclipse usa su propio compilador, por lo que Eclipse finalmente sigue lo que hacen los compiladores provistos por SUN / Oracle; Sin embargo, a veces (como en este caso) hay diferencias.

Esto podría "ir en cualquier dirección" y, probablemente, en Java 6, el problema no se abordó en detalle. Como Java tiene un fuerte requisito para reducir el número de significados "ambiguos" en su entorno (para imponer el mismo comportamiento en muchas plataformas), me imagino que ajustaron (o especificaron directamente) el comportamiento decidido en la versión 7.

Acaba de quedar atrapado en el lado "incorrecto" de la aclaración de la nueva especificación. Lo siento, pero creo que vas a escribir un poco de esto

public void log(Level logLevel, Object... args) { if (args != null && args[0] instanceof Integer) { // do something else } else { // do something } }

en su nueva solución.

Tenemos un LogManager de clase en nuestro proyecto Java que se ve así:

public class LogManager { public void log(Level logLevel, Object... args) { // do something } public void log(Level logLevel, int value, Object... args) { // do something else } }

Al compilar el proyecto con OpenJDK 6 en Debian, todo funciona bien. Cuando se usa OpenJDK 7, la compilación (hecha con ant) ​​produce los siguientes errores y la compilación falla:

[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] ^

Siempre que el 1 no esté en modo automático, la llamada al método no debe ser ambigua, ya que 1 es un int y no se puede convertir a Objeto. Entonces, ¿por qué autoboxing no anula los varargs aquí?

Eclipse (instalado usando el tar.gz de eclipse.org) lo compila sin importar si OpenJDK 6 está instalado o no.

¡Muchas gracias por tu ayuda!

Editar:

El compilador obtiene la opción source="1.6" y target="1.6" en ambos casos. La nota de compilación de Eclipse es solo un comentario.


Esto es patinar mucho más cerca del borde de lo que es prudente. A menos que pueda encontrar un lenguaje claro en la especificación del comportamiento, evitaría cualquier cosa ambigua como esta.

Incluso si se encuentra en la especificación, los lectores de su código no habrán hecho el lenguaje que el legado legal debe conocer, por lo que deberá comentarlo para explicarlo, y pueden o no leer el comentario. Es posible que ni siquiera consideren una de las alternativas: solo vean una sobrecarga que se ajuste y corran con eso. Un accidente a punto de suceder.


Supongo que está relacionado con el error #6886431 , que también parece estar solucionado en OpenJDK 7.

El problema es que JLS 15.12.2.5 La elección del método más específico dice que un método es más específico que otro cuando los tipos de parámetros formales de los primeros son subtipos de parámetros formales de los últimos.

Como int no es un subtipo de Object , ninguno de sus métodos es el más específico, por lo que su invocación es ambigua.

Sin embargo, la siguiente solución es posible, porque Integer es un subtipo de Object :

public void log(Level logLevel, Object... args) { ... } public void log(Level logLevel, Integer value, Object... args) { ... }