Почему autoboxing не отменяет varargs при использовании перегрузки методов в Java 7?

У нас есть class LogManager в нашем Java-проекте, который выглядит так:

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

При компиляции проекта с OpenJDK 6 при работе с Debian все работает отлично. При использовании OpenJDK 7 assembly (выполняется с помощью ant) ​​приводит к следующим ошибкам и сбою сборки:

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

Пока 1 не является автобоксированным, вызов метода должен быть однозначным, поскольку 1 является int и не может быть преобразован в Object. Итак, почему autoboxing не отменяет varargs здесь?

Eclipse (установленный с использованием tar.gz с eclipse.org) компилирует его независимо от того, установлен ли OpenJDK 6 или нет.

Большое спасибо за вашу помощь!

Редактировать:

В обоих случаях компилятор получает параметр source="1.6" и target="1.6" . Замечание компиляции Eclipse просто означает комментарий.

    Я думаю, это связано с ошибкой # 6886431 , которая, похоже, исправлена ​​и в OpenJDK 7.

    Проблема заключается в том, что JLS 15.12.2.5 Выбор наиболее конкретного метода говорит о том, что один метод более конкретный, чем другой, когда типы формальных параметров первого являются подтипами формальных параметров последнего.

    Поскольку int не является подтипом Object , ни один из ваших методов не является наиболее конкретным, поэтому ваш вызов является неоднозначным.

    Однако возможно следующее обходное решение, поскольку Integer является подтипом Object :

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

    Eclipse использует собственный компилятор, поэтому в конечном итоге Eclipse следует за тем, что делают компиляторы SUN / Oracle; однако иногда (как в этом случае) существуют различия.

    Это может «идти в одну сторону» и, вероятно, на Java 6, проблема не была подробно рассмотрена. Поскольку у Java есть сильное требование уменьшить количество «неоднозначных» значений в своей среде (чтобы обеспечить одинаковое поведение на многих платформах), я бы предположил, что они подтянули (или прямо указали) решительное поведение в версии 7.

    Вы просто попались на «неправильную» сторону нового уточнения спецификации. Извините, но я думаю, вы будете писать немного об этом

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

    в ваше новое решение.

    Это приближается ближе к краю, чем разумно. Если вы не найдете четкого языка в спецификации поведения, я бы избегал чего-то двусмысленного.

    Даже если он находится в спецификации, читатели вашего кода не будут знать юридическую консультацию по языку, поэтому вам нужно будет прокомментировать это, чтобы объяснить, и они могут или не могут читать комментарий. Возможно, они даже не рассматривают одну из альтернатив – просто посмотрите одну перегрузку, которая подходит, и бегите с этим. Авария в ожидании.

    Давайте будем гением компьютера.