5

Изучаю ANDROID, вот пример листинга:

Button newMyBtn = (Button) findViewById(R.id.myBtn);

Синтаксически запись правильна, только я вот одного понять не могу, зачем здесь вот это самое приведения объектной ссылки? Что, нельзя в объект newMyBtn сразу положить вызов метода findViewById?

Я почитал Хорстаманна и нашел (но все равно остался непонятен принцип данного приведения):

Чтобы выполнить приведение объектной ссылки, используются такие же синтаксические конструкции, как и для числовых выражений. Имя требуемого класса надо поместить в скобки и поставить перед объектной ссылкой, которую нужно преобразовать. Пример соответствующего выражения приведен ниже.

Manager boss = (Manager) staff[0];

Для приведения типов существует только одна причина — необходимость использовать все возможности объекта после того, как его фактический тип был на время забыт. Например, в классе ManagerTest массив staff представляет собой массив объектов Employee. Этот тип выбран, поскольку некоторые элементы массива хранят информацию об обычных сотрудниках. Чтобы получить доступ ко всем новым полям класса Manager, нам может понадобиться привести тип некоторых элементов массива к типу Manager. (В примере, рассмотренном выше, мы предприняли специальные меры, чтобы избежать приведения типов. Мы инициализировали переменную boss объектом Manager, перед тем как поместить ее в массив. Для того чтобы задать размер премии, нужно знать правильный тип объекта.)

pavlofff
  • 36,765

1 Answers1

11

Проблема в различии двух вещей: декларируемого и фактического типа объекта.

Дело в том, что метод findViewById не может знать, что по данному id будет лежать именно Button. Поэтому он декларирует тип возвращаемого объекта как View — это максимальная гарантия, которую он может дать. Фактически возвращённый объект может быть любого производного от View типа.

Итак, у нас findViewById возвращает View, который, как мы уверены, фактически будет Button'ом. Для того, чтобы работать с ним как с Button'ом, мы должны иметь ссылку типа Button. Мы её декларируем: Button newMyBtn.

Теперь, у нас инициализация ссылки типа Button другой ссылкой, у которой декларируемый тип — всего лишь View. Система не уверена в том, что фактическим типом будет Button. Для того, чтобы убедить её в этом, мы используем приведение к нужному типу (Button)findViewById(...).

Эта конструкция фактически означает: «Я уверен, что фактический тип объекта будет Button или производный от него. Причём настолько уверен, что согласен крешнуть программу, если это не так.» (Точнее, выбросить исключение, да.) При этом компилятор соглашается с вашими доводами, и приводит декларируемый тип View к Button. (Если во время выполнения там реально будет не Button, вы таки получите исключение.)

Без приведения вы не убедите компилятор, что тип у ссылки правильный.

Почему для компилятора важно убедиться в правильности типа? Потому что если у вас ссылка newMyBtn имеет заявленный тип Button, то вы можете у неё вызывать методы, специфичные для Button'а, и обращаться к полям, которые есть в Button'е. Если этот объект окажется фактически другого типа, и таких полей в нём не будет, что тогда? Компилятор заботится о том, чтобы таких ситуаций не возникало. (Это называется словом «типобезопасность».)

VladD
  • 206,799
  • Ого, сильно конечно, спасибо за полноту ответа, с первого раза не все понял, еще раз прочту – Артёмыч Jan 26 '16 at 22:26
  • все понял ) спасибо, ключевое то здесь "findViewById не может знать, что по данному id будет лежать именно Button" – Артёмыч Jan 26 '16 at 22:28
  • Тогда вопрос: А где же определен метод findViewById? что его можно просто так, взять и вызвать... – Артёмыч Jan 26 '16 at 22:30
  • 1
    Вы молодец! Очень сильно разбираетесь в терминологии :) Не каждый так сможет ответить! – Артёмыч Jan 26 '16 at 22:59
  • @Артёмыч: Это метод класса Activity. Он определён, если вы наследуетесь от Activity (внутри класса-наследника). – VladD Jan 26 '16 at 22:59
  • @Артёмыч: Спасибо! :) – VladD Jan 26 '16 at 23:00
  • не подскажите литературу по ANDROID? :) – Артёмыч Jan 26 '16 at 23:03
  • @Артёмыч: Я не специалист, но у нас есть список литературы тут: http://ru.stackoverflow.com/a/416635/10105. Может быть, в нём найдётся что-нибудь интересное для вас. – VladD Jan 26 '16 at 23:04
  • @Артёмыч: Хм, хотя в том списке ничего про конкретно Android не видно :( – VladD Jan 26 '16 at 23:06
  • НЕ СПЕЦИАЛИСТ!? Да кроме вас, здесь никто больше и не ответил, видимо "Ок, гугл!" уже не тот ))) – Артёмыч Jan 26 '16 at 23:07
  • Вот ещё список: http://ru.stackoverflow.com/q/135019/10105 – VladD Jan 26 '16 at 23:07
  • 1
    @Артёмыч: Не, у нас есть спецы по Java куда круче. Просто их в этот момент не оказалось на сайте. Вот наши лучшие специалисты по Java/Android: http://ru.stackoverflow.com/help/badges/100/android, http://ru.stackoverflow.com/help/badges/93/java. – VladD Jan 26 '16 at 23:09
  • 2
    Да, KoVadim мне тоже как-то помогал с ответами! Я вам всем конечно же очень благодарен, я никого не хочу обидеть, просто бывают люди, которые кидают ссылки на гугл, с такой уверенностью, что неужели человек обращаясь за помощью уже не один день бьется над проблемой! – Артёмыч Jan 26 '16 at 23:13
  • @Артёмыч: У нас посылать в гугл больше не принято :) Вот обсуждение на Мете: http://meta.ru.stackoverflow.com/q/2013/10105 – VladD Jan 26 '16 at 23:15
  • А ну вот пожалуйста, только вспомнил очень толкового и смешного одессита Deonis, с языка сорвали, там как раз и от него комментарий ))) – Артёмыч Jan 26 '16 at 23:18