В яве почему бы не расширить тогда коробку? - PullRequest
5 голосов
/ 12 января 2010

В Java мы можем боксировать, а затем расширить. Почему мы не можем расширить и коробку? Например:

 class WidenAndBox{
  static void go(Long x)  {   }
  public static void main(String [] args)
   {
    byte b=5;
    go(b);
   }
}

Ошибка компилятора

Ответы [ 5 ]

6 голосов
/ 12 января 2010

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

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

3 голосов
/ 28 апреля 2014

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

 class BoxAndWiden {
   static void go(Object o) {
   Byte b2 = (Byte) o; // ok - it's a Byte object
   System.out.println(b2);
   }
    public static void main(String [] args) {
    byte b = 5;
    go(b); // can this byte turn into an Object ? 
    }
    }

Это компилирует (!) И производит вывод: 5 Позвольте мне показать, как это работает за кулисами. Когда JVM, попал в строку, которая вызывает метод go ():

  1. Байт b был помещен в байт.
  2. Ссылка на байт была расширена на объект (поскольку байт расширяет объект).
  3. Метод go () получил ссылку на объект, которая фактически ссылается на байт объект.
  4. Метод go () возвращает ссылку на объект обратно в ссылку на байт. член, в этом сценарии никогда не было объекта типа Object, только объект типа Byte!).
  5. Метод go () печатает значение байта.

Но в вашем случае. Почему компилятор не пытался использовать логику box-then-widen, когда он пытался работать с классом WidenAndBox?

если бы он попытался сначала боксировать, байт был бы преобразован в байт. Теперь мы снова пытаемся расширить байт до длинного, и, конечно, тест IS-A не проходит.

2 голосов
/ 12 января 2010

Я считаю, что основной причиной является производительность. Если вы разрешите произвольную комбинацию расширения и (не) бокса, вам нужно будет проверить наличие более подходящих методов. Особенно в контексте с функциями, принимающими несколько примитивов малого диапазона, количество возможных комбинаций может стать довольно большим.

1 голос
/ 12 января 2010

Просто приведите его к длинному типу

 go( (long) b);
1 голос
/ 12 января 2010

Приведите его к длинному.

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