2013-03-19 2 views
1

Я работаю над Java Se 7 OCA и не могу понять, почему ниже код не компилируется. вызов aMethod в основном методе дает ошибку компиляции с указанием неоднозначного метода. Приоритетные правила между расширением и боксом, похоже, противоречат этому образцу метода перегрузки.Java-метод перегрузки с бокса/расширения

public class Overloading { 
public static void main(String[] args) { 
    Byte i = 5; 
    byte k = 5; 
    aMethod(i, k); 
} 

static void aMethod(byte i, Byte k) { 
    System.out.println("Inside 1"); 
} 

static void aMethod(byte i, int k) { 
    System.out.println("Inside 2"); 
} 

static void aMethod(Byte i, Byte k) { 
    System.out.println("Inside 3 "); 
} 
} 

Ошибка "Метод aMethod (байты, байты) является неоднозначным для типа Перегрузки". Когда я прокомментирую первый метод, он дает такую ​​же ошибку для второго метода.

Мое мышления: Первый метод нуждается в распаковке и бокс Второй метод требует распаковки и расширение Третьего метод требует только бокса. Так что это должен быть третий метод, так как он нуждается в наименьшем преобразовании, и все они имеют преобразование в бокс.

+1

И сообщение об ошибке было? – bmargulies

+0

Почему вы думаете, что этот * должен компилироваться? –

+0

Вы можете найти правильное объяснение проблемы здесь: http://stackoverflow.com/a/4921807/1065197. Поскольку компилятор перейдет к этапу 3, он найдет более подходящий метод для использования, что будет двусмысленным. –

ответ

0

Проблема заключается со всеми этими методами:

static void aMethod(byte i, Byte k) { 
    System.out.println("Inside 1"); 
} 

static void aMethod(byte i, int k) { 
    System.out.println("Inside 2"); 
} 

static void aMethod(Byte i, Byte k) { 
    System.out.println("Inside 3 "); 
} 

Java не знает , который он должен вызывать в строке:

aMethod(i, k); 

Вашего PARAMS i и k могут быть преобразованы различными способами, в соответствии с JLS характеристик:

i может быть unboxed к byte (5.1.8) или уезжал в Byte (5.1.1) -> 2-й вариант

k может быть boxed до Byte (5.1.7) или расширена до int тип (5.1.2) -> 2 варианта.

+0

Вы правы; но преобразование имеет правила приоритета. он будет выбирать расширение по боксу. И он должен оставить «i» в качестве байта, когда это необходимо, чем распаковать его. – isaolmez

+0

@isaolmez Единственным приоритетом, который будет работать здесь, является правило 5.1.1 (тип преобразования для того же типа). В случае, если у вас нет метода с соответствующей сигнатурой (т. Е. 'AMethod (Byte i, byte k)'), это преимущество не имеет смысла. – Andremoniy

0

этого класса у вас есть два метода равна

static void aMethod(Byte i, Byte k) { 
    System.out.println("Inside 3 "); 
} 

static void aMethod(byte i, Byte k) { 
    System.out.println("Inside 1"); 
} 

Byte автоматического преобразования байт, поэтому компилировать ошибка

+0

На самом деле мой вызов неоднозначен, методы в порядке. – isaolmez

0

На самом деле это не определение, но вызов неоднозначен. Так как все целые числа в java по умолчанию, int. даже если вы говорите, что байт b = 5, 5 будет внутренне преобразован в int для любой операции. Но поскольку эта ссылка является байтом, в вашем случае она имеет возможность вызывать метод 2 & 3. Поэтому компилятор не может понять, что назвать.

поэтому aMethod(i, (Byte)k) должно работать.

+0

Я предполагаю, что вы предложили aMethod (i, (int) k). Но в этом случае других вариантов этого вызова нет. только метод принятия целого числа является вторым. – isaolmez

+0

не принимаем. как я уже сказал, все целочисленные литералы по умолчанию преобразуются в int, будь то короткие, байтовые, длинные. поэтому через ссылочный компилятор видит байт, но из значения он видит int. То есть создается двусмысленность. Итак, здесь будет работать aMethod (i, (byte) k), иначе вам может понадобиться передать значение типа int. Это можно проверить, вызвав aMethod (i, 5) и aMethod (i, (byte) 5); – Ankit

+0

aMethod (i, (байт) 5); не скомпилировал и не дал ту же ошибку. Но если я использую aMethod (i, 5), он компилируется. – isaolmez

0

Эти пункты должны иметь в виду, в то время как method overloading in Java:

  1. Widening примитивных типов использует непосредственный следующий более широкий тип метод аргумент, если точное совпадение не найдено.

  2. Бокс и вар-args совместимы с перегрузкой метода, если они используются индивидуально.

  3. Один тип обертки не может быть расширен до другого. Например, Integer не может быть расширен до Long.

  4. Расширение, за которым следует бокс, не работает. Например, int не может передать в Long.

  5. Бокс с последующим расширением работает только в одной ситуации, если в коробке аргумент передается в ссылку типа объекта. Int может быть передан объекту через Integer.

  6. Var-args можно комбинировать с расширением или боксом, но тщательно.

В выше части коде аргументы, передаваемые в aMethod должны быть соответствующим образом типа-литой, поскольку промежуточные результаты в Java преобразуются в междунар в выражении Int.

Смежные вопросы