Поле in
, определенное классом System
, не обязательно должно ссылаться на конкретную реализацию InputStream
- как вы уже работали, оно не может - просто нужно ссылаться на что-то, что расширяет InputStream
.
По крайней мере, в Linux in
ссылается на BufferedInputStream, который сам оборачивает FileInputStream. Другие реализации могут различаться, и в этом суть: использование абстрактного класса, такого как InputStream, позволяет варьировать реализующий класс и потенциально меняться от одной версии Java к другой, сохраняя при этом вызывающий код довольным.