/ / Вкласти суперклас в підклас [дублікат] - java, клас, об'єкт, успадкування, лиття

Передати суперклас до підкласу [дублікат] - java, клас, об'єкт, спадщина, відливання

Уявіть собі клас Котедж розширюється Будівництво і код

Building building = new Building();
Cottage cottage = (Cottage)building;

Тепер це має сенс Будівництво не можна передати Котедж враховуючи природу спадкоємства Java, але те, що не має сенсу (для мене), це те, що це компілюється. Чому він компілюється, а потім кидає час виконання ClassCastException?

Хіба це не очевидно будівля є посиланням на a Будівництво об'єкт, перш ніж фактично запустити програму?

Будучи таким загальним питанням, я знаю, що я отримую можливий дублікат для цього :), але я не міг знайти відповідь на запитання ЧОМУ ВІДБУВАЄТЬСЯ питання:)

EDIT2 Я прийняв тут чудову відповідь (не кажучи вже про обговорення нижче): але я все ще знаходжу прийняту відповідь Заливання Java призводить до помилки під час виконання замість помилки компіляції найцікавіший...

РЕДАГУВАТИ Я редагував IllegalCastException і покласти правильно ClassCastException

Відповіді:

10 за відповідь № 1

Це тому, що компілятор не знає, який об'єкт робить вашу посилання Building має на увазі.

Отже, у наведеному нижче випадку, де у вас є a базовий клас посилання, вказує на підклас об'єкт: -

Building building = new Cottage();
Cottage cottage = (Cottage)building;

Це спрацювало б чудово. Отже, це повністю a runtime рішення, чи є воно чинним чи ні. Отже, компілятор не викине помилку.

Хіба це не очевидно, що будівля є посиланням на об'єкт будівлі перед тим, як фактично запустити програму?

Немає. Абсолютно не. Тип об'єкта, на який посилаються, не відомий до часу виконання. Завжди пам'ятайте, що Компілятор завжди перевіряє еталонний тип. Фактичний тип об'єкта перевіряється під час виконання.

Ця концепція відома як Поліморфізм, де можна мати один і той же тип посилання, щоб вказати на об'єкти різних підтипів. Ви можете Google це, і отримаєте багато ресурсів для читання.


3 для відповіді № 2

Частина функції лиття полягає в тому, що вона робитькомпілятор заткнувся, ви говорите, що ви знаєте краще, ніж компілятор, що це за об'єкт, який ви "" кастингу.

Можливо, ви очікуєте, що компілятор відстежує те, до чого спрямовуються речі, і працюючи, якщо посилання є достовірним. Компілятор не такий розумний, його легко обдурити, перегляньте цей фрагмент:

    int i = 1;
System.out.println((Number)i);
Object o = i;
System.out.println((String)i); // won"t compile (primitive-to-ref-type cast)
System.out.println((String)o); // compiles (thanks to autoboxing)

Компілятор піклується лише про запобігання перетворенню між примітивами та типовими посиланнями.


2 для відповіді № 3

Розглянемо створення об'єкта котеджу (підкласу) з посиланням на будинок (суперклас)

Building b= new Cottage();
Cottage c = (Cottage) b;

Наведений вище код є легальним, тому компілятор не знає, який об'єкт виконує еталонна змінна c посилаються на час виконання, таким чином компілятор не кине помилку.

Чому він компілюється, а потім викидається під час виконання IllegalCastException?

До речі, він кидає ClassCastException коли ви намагаєтеся передати об'єкт надкласу в підклас, не IllegalCastException.