Определение для in
и out
полей внутри System
класса:
public final static PrintStream out;
public final static InputStream in;
Это константы. Они тоже бывают объектами, но они постоянные. Это очень похоже на класс Math:
public static final double E = 2.7182818284590452354;
public static final double PI = 3.14159265358979323846;
Или в логическом классе:
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
Или в классе Color:
public final static Color white = new Color(255, 255, 255);
public final static Color black = new Color(0, 0, 0);
public final static Color red = new Color(255, 0, 0);
При доступе к общедоступной константе, которая не изменяется, нет существенного преимущества для ее инкапсуляции - концептуально или на основе производительности. Это здесь. Это не изменится.
Там нет никакой реальной разницы между Color.white
и System.out
.
enum
для хранения ... хотя этоenum
было новшество с Java 1.5 (не вариант в 1.0 дней).final static
иstatic final
? Если так, то, что это?Настоящая причина в том, что это проблема наследия. Эти
System.in,out,err
константы были частью Java 1.0 ... и , вероятно, намного дальше. К тому времени, когда стало ясно, что у дизайна были проблемы, было слишком поздно, чтобы исправить это. Лучшее, что они могли сделать, - это добавитьSystem.setIn,setOut,setErr
методы в Java 1.1, а затем заняться проблемами спецификации языка 1 .Это похоже на проблему того, почему существует статический
System.arraycopy
метод, имя которого нарушает соглашения об именах Java.Что касается того, является ли это «плохим дизайном» или нет, я думаю, что это так. Существуют ситуации, когда текущая обработка без OO является серьезной проблемой. (Подумайте ... как вы можете запустить одну Java-программу внутри другой, когда их требования к стандартному потоку ввода-вывода вступают в противоречие. Подумайте ... код модульного тестирования, который влечет за собой изменение потоков.)
Тем не менее, я также могу сослаться на аргумент, что нынешний способ ведения дел во многих случаях более удобен .
1 - Интересно отметить, что
System.in,out,err
переменные в JLS особо упоминаются как имеющие «особую семантику». JLS говорит, что если вы измените значениеfinal
поля, поведение будет неопределенным ... за исключением случая с этими полями.источник
Я считаю, что объект out является неизменным, что делает его каким-то образом безопасным (спорным) для хранения в открытом конечном статическом поле.
Многие из классов в JDK не соответствуют лучшим принципам объектно-ориентированного проектирования. Одной из причин этого является тот факт, что они были написаны почти 20 лет назад, когда объектно-ориентация только становилась основной парадигмой, и многие программисты просто не были знакомы с ними, как сейчас. Очень хороший пример плохого дизайна API - API Date & Time, на изменение которого ушло 19 лет ...
источник
Этот ответ велик и правдив.
Я хотел бы добавить, что в некоторых случаях компромиссы были сделаны ради удобства использования.
Объекты типа String могут создаваться без нового события, когда String не является примитивом:
Строка, являющаяся не примитивной, должна создаваться следующим образом:
Но компилятор допускает более короткую, меньшую OO-опцию, потому что String - безусловно, наиболее широко используемый класс в API.
Также массивы могут быть инициализированы не OO-способом:
Как ни странно, объект является экземпляром класса или массива . Значимые массивы - это совершенно отдельный тип класса.
Массивы имеют
length
открытое поле, которое не является константой. Также нет документации по массивам классов. (не путать с классом Arrays или java.reflect.Array).источник
new String("Hello")
всегда будет создавать новый объект String. ПокаString s = "Hello";
буду использовать интернированный объект. Сравните:"Hello" == "Hello"
может быть истиной, аnew String("Hello") == new String("Hello")
всегда ложной. В первом случае происходит волшебство оптимизации времени компиляции, которое невозможно сnew String("Hello")
. См en.wikipedia.org/wiki/String_interningString s = new String("Hello");
», что неверно. Более короткий параметр (String s = "Hello";
) более корректен из-за интернирования строк.String
этом нет более «правильной» опции. Оба верны. Хотя, как говорит MichaelT, более короткий предпочтителен из-за интернирования String.