SCJP: не может расширяться и затем упаковываться, но вы можете боксировать и затем расширять - PullRequest
5 голосов
/ 15 сентября 2010

Я готовлюсь к экзамену SCJP, и столкнулся с проблемой, которую я не могу обернуть.

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

Их объяснение:

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

Но это звучит как коробка, а затем расширяется, а не расширяется, а затем коробка для меня.

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

Edit: Для пояснения: я говорю о страницах 252 и 253 сертифицированного программиста SCJP для книги Java 6. http://books.google.be/books?id=Eh5NcvegzMkC&pg=PA252#v=onepage&q&f=false

Ответы [ 5 ]

4 голосов
/ 10 ноября 2012

Причина, по которой «расширение, затем бокс» не допускается, может быть вызвана следующей причиной (стр. 249 книги SCJP):

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

4 голосов
/ 31 октября 2010

язык сбивает с толку.

По сути, вы не можете так поступить:
байт -> байт -> длинный
потому что Байт и Лонг не разделяют отношения.
Итак, он пытается сделать это:
байт -> длинный -> длинный
Но он также не может этого сделать (очевидно, из-за ограничений компилятора). Таким образом, он терпит неудачу и выдает ошибку.

Но, с другой стороны, вы МОЖЕТЕ сделать это:
byte -> Byte -> Object
потому что Байт - это Объект.

Рассмотрим 2 функции и байтовую переменную:

toLong (Long x)
toObject (Object x)
байт b = 5;

Тогда это утверждение будет незаконным:
toLong (б);
// потому что b -> новый байт (b) -> новый длинный (новый байт (b)) недопустим.
AND byte -> long -> Long не может быть сделано из-за ограничений компилятора.

но это утверждение законно:
toObject (b);
// потому что b -> новый байт (b) -> новый объект (новый байт (b)) допустим.

3 голосов
/ 15 сентября 2010

В основном это означает, что расширение работает только с примитивными типами, а не с обертками. Если вы сначала боксируете, вы получите упаковщик (byte -> Byte). Но оболочки - Byte, Double, Float, Integer, Long и Short не имеют никаких отношений наследования (IS-A). Например, параметр Long не может принять Byte.

Таким образом, вы должны сначала расширить (byte -> long), а затем поле (long -> Long).

1 голос
/ 28 января 2011

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

В то время как показанный пример пытается упаковывать, а затем расширяется, причина его неверности заключается в том, что байтне является длинным, т.е. они не находятся в одном и том же дереве наследования.Однако, если в примере используются Byte и Numeric, то вы можете использовать Box byte to Byte и затем расширить Byte до Numeric как Byte IS-A Numeric (они находятся в одном и том же дереве наследования)

1 голос
/ 15 сентября 2010

Это не расширение, потому что Байт не помещается в Long.Вот почему это не работает.

Вы можете поместить в байт, а затем расширить в Object или Number.

Как ваша книга говорит:

мы вернулись к , пытаясь расширить байт до длинного


В вашем случае, я полагаю, код выглядит следующим образом:

byte b = 1;
Long l = b;

b заменен на Byte (сначала бокс), но не может быть изменен на Long, поскольку байт не является подклассом Long.

. В следующих шагах:

byte b = 1;
Byte byteB = b; //works
Long l = byteB; //doesn't work
...