2016-01-12 2 views
5

Можете ли вы объяснить мне, почему результат «int»? Я ожидаю, что он будет «длинным», если переменная является байтом.Интервью с Java Primitive Widening

public class Test{ 
     public static void printValue(int i, int j, int k){ 
      System.out.println("int"); 
     } 

     public static void printValue(byte...b){ 
      System.out.println("long"); 
     } 

     public static void main(String... args){ 
      byte b = 9; 
      printValue(b,b,b); 
     } 
} 

ответ

12

Компилятор Java должен выбирать между двумя методами сопоставления. Он всегда будет выбирать метод, который не использует переменную arity (varargs) над тем, который ее использует. Это скорее способствовало бы всем 3 аргументам int, чтобы соответствовать первым printValue, чем использовать varargs.

Section 15.12.2 of the JLS состояние:

Остальная часть процесса разделяется на три этапа, чтобы обеспечить совместимость с версиями языка программирования Java до версии Java SE 5.0. Фазы:

  1. На первом этапе (§15.12.2.2) выполняет разрешение перегрузки, не допуская бокс или распаковки, преобразование или использование метода переменной валентности вызова. Если на этом этапе не обнаружен какой-либо применимый метод, обработка продолжается до второй фазы.
  2. Это гарантирует, что любые вызовы, которые были действительны на языке программирования Java до Java SE 5.0, не считаются неоднозначными в результате внедрения методов переменной arity, неявного бокса и/или распаковки. Однако объявление метода переменной arity (§8.4.1) может изменить метод, выбранный для выражения вызова метода данного метода, поскольку метод переменной arity рассматривается как метод фиксированной arity в первой фазе. Например, объявление m (Object ...) в классе, который уже объявляет m (Object), приводит к тому, что m (Object) больше не выбирается для некоторых выражений вызова (таких как m (null)), как m (Object [])) является более конкретным.

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

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

    <ол начать = «3»>
  3. Третий этап (§15.12.2.4) позволяет перегрузки, чтобы быть в сочетании с переменными методами арностью, бокс и распаковка.

(жирный шрифт курсив мой)

Способ согласования (первая перегрузка) находится в первой фазе, поэтому компилятор даже не рассматривает третий этап - разрешение переменных методов арности - - так печатается int.

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

printValue(new byte[]{b,b,b}); 
-1

Привет результат «ИНТ», так как при выполнении основной функции вы не printValue с одним аргументом, а с 3 аргумента. поэтому компилятор предположил, что вы ссылаетесь на первый printValue, у которого есть 3 параметра.Поскольку вы не использовали этот параметр внутри функции, все, что хорошо, без какой-либо ошибки времени выполнения. Я бы с другой стороны сказал, что это не очень хорошая практика, чтобы найти тип переменной таким образом. Лучшим способом будет использование оператора if if. И вы можете обратиться к этому сообщению за информацией о том, как найти тип в java: How do you know a variable type in java?

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