Справжня причина полягає в тому, що це спадщина. Ці System.in,out,errконстанти були частиною Java 1.0 ... і , ймовірно, набагато далі. На той час, коли було зрозуміло, що в дизайні виникли проблеми, виправити це було вже пізно. Найкраще, що вони могли зробити, було додати System.setIn,setOut,setErrметоди в Java 1.1, а потім розібратися з питаннями мовної специфікації 1 .
Це схоже на питання, чому існує статичний System.arraycopyметод, ім'я якого порушує умови імен Java.
Що стосується того, це "поганий дизайн" чи ні, я думаю, що це так. Бувають ситуації, коли поточне поводження, що не пов’язане з ООС, є серйозною проблемою. (Подумайте ... як можна запустити одну програму Java всередині іншої, коли їх "стандартний IO" потік вимог суперечить. Подумайте ... код тестування блоку, який тягне за собою зміну потоків.)
Однак я можу також звернутися до аргументу про те, що сучасний спосіб виконання справ є більш зручним у багатьох випадках.
1 - Цікаво зазначити, що System.in,out,errзмінні в JLS мають особливу згадку як такі, що мають "особливу семантику". JLS говорить, що якщо ви зміните значення finalполя, поведінка не буде визначеною ... за винятком цих полів.