2010-01-12 4 views
4

В java мы можем вставлять, а затем расширять. Почему мы не можем расширять и закрывать коробку? Для экс:В java почему бы не расширить окно?

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

Compiler ошибки

+1

Я знаю, что это, вероятно, теоретическое, но почему бы не заставить функцию взять «номер x»? – Powerlord

+2

Ошибка IS-A здесь.байтовый примитивный класс-оболочка - это Byte, но в качестве правила Java вы не можете применять расширение для объектов-оболочек, я имею в виду, что Byte не может расширяться до Long. (хорошо я знаю довольно поздно, но уверен, что люди проведут этот ответ :)) – HRgiger

+0

Что делать, если переменная b была int? – Ascendant

ответ

6

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

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

1

Просто брось к длинному типа

go((long) b); 
1

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

3

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

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 Позвольте мне показать, как она работает за scene.when виртуальная машина, попал в линию, которая вызывает идти() метод:

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

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

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