Почему автоупаковка выполняет некоторые вызовы, неоднозначные в Java?

is - тестирование идентичности, == - тестирование равенства (см. Документация Python ).

В большинстве случаев, если a is b, то a == b. Но есть исключения, например:

>>> nan = float('nan')
>>> nan is nan
True
>>> nan == nan
False

Таким образом, вы можете использовать is для тестирования идентичности, никогда не проводить тесты равенства.

34
задан Hosam Aly 1 February 2009 в 19:20
поделиться

5 ответов

При кастинге первого аргумента для Возражения себе, компилятор будет соответствовать методу, не используя автоупаковку (JLS3 15.12.2):

первая фаза (В§15.12.2.2) выполняет разрешение перегрузки, не разрешая упаковывающее или распаковывающее преобразование или использование переменного вызова метода арности. Если никакой применимый метод не найден во время этой фазы, затем обрабатывающей, продолжается к второй фазе.

, Если Вы не бросаете его явно, это перейдет к второй фазе попытки найти метод сопоставления, позволяя автоупаковку, и затем это действительно неоднозначно, потому что Ваш второй аргумент может быть подобран булевской переменной или Объектом.

вторая фаза (В§15.12.2.3) выполняет разрешение перегрузки при разрешении упаковки и распаковывания, но все еще устраняет использование переменного вызова метода арности.

Да ведь во второй фазе, разве компилятор не выбирает второй метод, потому что никакая автоупаковка булева аргумента не необходима? Поскольку после того, как это нашло эти два метода сопоставления, только выделите подтипы в преобразовании, используется для определения самого определенного метода этих двух, независимо от любой упаковки или распаковывания, которое произошло для соответствия им во-первых (В§15.12.2.5).

Также: компилятор не может всегда выбирать самый определенный метод на основе количества автоматических (ООН) необходимая упаковка. Это может все еще привести к неоднозначным случаям. Например, это все еще неоднозначно:

public class Test {
    static void f(Object a, boolean b) {}
    static void f(int a, Object b) {}

    static void m(int a, boolean b) { f(a, b); } // ambiguous
}

Помнят, что алгоритм для выбора метода сопоставления (шаг 2 времени компиляции) исправлен и описан в JLS. Однажды в фазе 2 нет никакой выборочной автоупаковки или распаковывания. Компилятор расположится весь методы, которые доступны (оба метода в этих случаях) и применимы (снова эти два метода), и только затем выбирает самый определенный, не смотря на упаковку/распаковывание, которая неоднозначна здесь.

32
ответ дан 27 November 2019 в 17:04
поделиться

Компилятор сделал , автоупаковывают первый аргумент. После того как это было сделано, это - второй аргумент, это неоднозначно, поскольку это могло рассматриваться или как булевская переменная или как Объект.

Эта страница объясняет правила для автоупаковки и выбора который метод вызвать. Компилятор сначала пытается выбрать метод , не используя автоупаковки во всем , потому что упаковка и распаковывание несут потери производительности. Если никакой метод не может быть выбран, не обращаясь к упаковке, как в этом случае, то упаковка находится на таблице для весь аргументы тому методу.

4
ответ дан 27 November 2019 в 17:04
поделиться

Когда Вы говорите f (a, b), компилятор перепутан, относительно которой функции он должен сослаться к.

Это вызвано тем, что интервал , но аргументом, ожидаемым в [1 113] f, является Объект. Таким образом, compliler решает преобразовать к Объекту. Теперь проблема состоит в том, что, если может быть преобразован в объект, так может быть b.

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

, Когда Вы преобразовываете к Объекту вручную, компилятор просто ищет самое близкое соответствие и затем относится к нему.

, Почему компилятор не выбрал функцию, которая может быть достигнута путем "выполнения наименее возможного количества упаковки/распаковывания преобразований"?

Посмотрите следующий случай:

f(boolean a, Object b)
f(Object a , boolean b)

, Если мы звоним как [1 118] f (булевская переменная a, булевская переменная b) , какую функцию это должно выбрать? Это неоднозначное право? Точно так же это станет более сложным, когда много аргументов будет присутствовать. Таким образом, компилятор принял решение дать Вам предупреждение вместо этого.

С тех пор нет никакого способа знать, какую из функций программист действительно намеревался вызвать, компилятор дает ошибку.

3
ответ дан 27 November 2019 в 17:04
поделиться

Итак, почему разрешение перегрузки перестало работать? Почему компилятор не автоупаковывал первый аргумент и обычно принимал второй аргумент? Почему я должен был запросить автоупаковку явно?

Это обычно не принимало второй аргумент. Помните, что "булевская переменная" может быть упакована к Объекту также. Вы, возможно, явно бросили булев аргумент для Возражения также, и он будет работать.

2
ответ дан 27 November 2019 в 17:04
поделиться

См. http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#20448

, бросок помогает, потому что затем никакая упаковка не необходима, чтобы найти, что метод звонит. Без броска вторая попытка состоит в том, чтобы позволить упаковывать, и затем также булевская переменная может быть упакована.

лучше иметь ясные и понятные спецификации для высказывания, что произойдет, чем высказать людей предположение.

2
ответ дан 27 November 2019 в 17:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: