2016-08-23 3 views
2

Следующий код не компилируется из-за необработанного исключения, хотя мне кажется, что там не должно быть никаких проблем:Почему это считается необработанным исключением?

class Car { 
    public void drive() throws Exception { 
     System.out.println("Driving..."); 
    } 
} 

public class Sedan extends Car { 
    public void drive() { 
     System.out.println("Driving Sedan..."); 
    } 
    public static void main(String[] args) { 
     Car c = new Sedan(); 
     c.drive(); //unhandled exception! 
    } 
} 

Если это не очевидно для компилятора, что, когда наиважнейшая метод c.drive() является вызванное, исключенное исключение не будет выбрано? Почему именно потому, что ссылка имеет тип Car вместо типа Sedan, мы должны рассматривать диск так, как если бы он все еще выдавал проверенное исключение? Отличительный метод этого не делает!

+0

'drive' может бросить' 'Exception' но главный 'не справляется с этим. – tkausl

+3

, потому что 'c' также может быть не' Sedan', который мог бы «бросить» «Исключение». Поскольку 'throw' определен в' Car', вам нужно обработать его. – SomeJavaGuy

+0

Do 'Sedan c = new Sedan();' –

ответ

5

К сожалению, нет, это не очевидно для компилятора.

Компилятор по существу смотрит на Car c и на звонок drive. Компилятор не знает тип времени выполнения объекта, на который указывает c. Из-за этого он оценивает подпись метода Car.drive(), которая включает в себя throws Exception.

Чтобы уточнить, что, если каким-либо другим способом c был переназначен объекту SUV, который все еще выбрасывает это исключение? Компилятор не может узнать состояние объекта к моменту вызова метода drive.

+0

На самом деле, если бы у нас был 'final Car c', то было бы возможным вывод типа. Но этого не происходит, потому что язык построен вокруг статической типизации. – dhke

+0

@dhke Так как у нас также есть понятие «эффективно окончательный», такая явная маркировка не понадобится. Но это было бы очень запутанно. – biziclop

+0

@dhke С типом вывода у вас будет 'val c = new Sedan()', и тогда это будет работать по очевидной причине. Если вы явно объявляете тип как «Автомобиль», то это то, что вы получаете. –

0

Вы можете это исправить с

1.

Sedan c = new Sedan(); 
c.drive(); 

2.

или

Car c = new Sedan(); 
((Sedan) c).drive(); 
Смежные вопросы