/ / Java кастинг в резултат на грешка по време на изпълнение вместо грешка при компилирането - java

Извличането в Java води до грешка в хода на изпълнение вместо грешка при компилиране - java

Следният кодов фрагмент ще доведе до изпълнение:

class Vehicle {
public void printSound() {
System.out.print("vehicle");
}
}

class Car extends Vehicle {
public void printSound() {
System.out.print("car");
}
}

class Bike extends Vehicle {
public void printSound() {
System.out.print("bike");
}
}

public class Test {
public static void main(String[] args) {
Vehicle v = new Car();
Bike b = (Bike) v;

v.printSound();
b.printSound();
}
}

Моят въпрос е: защо това води до грешка по време на изпълнение, но не и компилационна грешка? Не трябва ли компилаторът да знае, че "v" вече е "Car" и не може да бъде хвърлен в "Bike"?

Отговори:

9 за отговор № 1

На теория е възможно компилаторът да каже на себе си: "v е локална променлива, която е присвоена на a Car, В нито един момент преди опита да се направи Bike променя ли стойността си и няма начин Car за да бъдете успешно хвърлени Bike, Следователно това е грешка. "

Въпреки това, знам, че няма да има никакъв Java компилатортози анализ за вас. Това е наистина полезно само в най-простия случай. Vehicle до a Bike, и така го позволява.

Най-общо казано, това означава: той казва на компилатора, че въпреки че това присвояване може да се провали, ти си доста сигурен, че е спечелил. В замяна, за да позволи на кода да се компилира, вие поемате риска от изключение по време на изпълнение.


4 за отговор № 2

Кастинг от супер клас може да работи, така че е позволено (по време на компилация). Кастингът от напълно различен клас не е разрешен, например:

Integer a = 1;
String b = (String)a; // compile error
String b = (String)(Object)a; // runtime error

3 за отговор № 3

За

R r = /* some code to initialize "r" */
T t = (T) r;

Най- Спецификация за език на Java казва:

Ако R е обикновен клас (не клас масив):

  • Ако T е тип клас, тогава R трябва да бъде или същия клас като T или подклас от T, или да се хвърли изключение по време на изпълнение.
  • Ако T е тип интерфейс, тогава R трябва да въведе интерфейс T или да бъде хвърлено изключение по време на изпълнение.
  • Ако T е тип масив, тогава се хвърля изключение по време на изпълнение.

1 за отговор № 4

Въвеждането на обекта се извършва по време на изпълнение, така че компилаторът не го разпознава


0 за отговор № 5

Не. v е Vehicle и може да е възможно да го хвърлим Bike, Това не е работата на компилатора, за да разбере действителните видове изпълнения на всеки обект (особено защото понякога това е невъзможно).


0 за отговор № 6

Семантиката на Java казва, че това трябва да доведе до товапри грешка по време на изпълнение. В този случай е възможно да погледнете кода и да видите, че той определено ще хвърли грешка по време на изпълнение, но как компилаторът знае, че ClassCastException не е това, което искаш?

Редакторите като IntelliJ и Eclipse могат (и правят) да забележат такива грешки и да ви предупредят за тях, но правилата на Java казват, че това е законен код, който трябва да се компилира.


0 за отговор № 7

Това е грешка по време на изпълнение, защото вече сте дефинирали променливата v като Car, Не можете да конвертирате Car да се Bike.

Компилаторът няма да провери този тип присвояване на стойност, защото компилаторите като цяло не проверяват семантиката.