Я не знаю, почему он компилируется ...
Потому что это явное приведение между не final
ссылочным типом и интерфейсом.Явное приведение между ссылочными типами говорит компилятору: «Послушайте, я (программист) знаю, что это приведение будет действительным во время выполнения. Поверьте мне».Так оно и есть.Конечно, позже во время выполнения, поскольку программист ошибался неправильно , он терпит неудачу.
Компилятор не вслепую доверяет программисту.Подробности в §JLS5.5 , но если компилятор может доказать , что приведение не может быть действительным, оно все равно отклонит приведение.Однако в вашем случае это невозможно, поскольку InputStreamSource
- это интерфейс , а FileInputStream
- это класс не final
.Таким образом, FileInputStream
вполне может ссылаться на некоторый объект подкласса, который реализует InputStreamSource
.(Конечно, мы можем сказать, глядя на это, что это не так, поскольку просто установлено на результат new FileInputStream
. Но компилятор выглядит не так уж и сложно, его волнует толькоо типах, участвующих в кастинге.)