Die Definition für die Felder in
und out
in der System
Klasse lautet:
public final static PrintStream out;
public final static InputStream in;
Das sind Konstanten. Sie sind zufällig auch Objekte, aber sie sind Konstanten. Es ist sehr ähnlich wie in der Mathe-Klasse:
public static final double E = 2.7182818284590452354;
public static final double PI = 3.14159265358979323846;
Oder in der Booleschen Klasse:
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
Oder in der Farbklasse:
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);
Wenn auf eine öffentliche Konstante zugegriffen wird, die sich nicht ändert, hat die Verkapselung keinen wesentlichen Vorteil - konzeptionell oder leistungsbasiert. Es ist da. Es wird sich nicht ändern.
Es gibt keinen wirklichen Unterschied zwischen Color.white
und System.out
.
enum
zu verwenden, um sie zu halten ... obwohlenum
es neu in Java 1.5 war (keine Option in den 1.0 Tagen).final static
undstatic final
? Wenn ja was ist dasDer wahre Grund dafür ist, dass dies ein altes Problem ist. Die
System.in,out,err
Konstanten waren Teil von Java 1.0 ... und wahrscheinlich viel weiter zurück. Als klar war, dass das Design Probleme hatte, war es zu spät, um es zu beheben. Das Beste, was sie tun konnten, war, dieSystem.setIn,setOut,setErr
Methoden in Java 1.1 hinzuzufügen und sich dann mit den Sprachspezifikationsproblemen 1 zu befassen .Dies ähnelt der Frage, warum es eine statische
System.arraycopy
Methode gibt, deren Name die Java-Namenskonventionen verletzt.Ob dies "schlechtes Design" ist oder nicht, glaube ich. Es gibt Situationen, in denen die derzeitige Nicht-OO-Behandlung ein ernstes Problem darstellt. (Überlegen Sie, wie Sie ein Java-Programm in einem anderen ausführen können, wenn die "Standard-E / A" -Stream-Anforderungen kollidieren. Überlegen Sie, ob ... Unit-Test-Code die Streams ändert.)
Ich kann mich jedoch auch auf das Argument beziehen, dass die derzeitige Vorgehensweise in vielen Fällen praktischer ist.
1 - Es ist interessant zu bemerken, dass die
System.in,out,err
Variablen in der JLS als "spezielle Semantik" besonders erwähnt werden. Das JLS sagt, dass, wenn Sie den Wert einesfinal
Feldes ändern , das Verhalten undefiniert ist ... außer im Fall dieser Felder.quelle
Ich glaube, dass das Out-Objekt unveränderlich ist, was es irgendwie sicher macht (dies ist fraglich), in einem öffentlichen statischen Endfeld gehalten zu werden.
Viele der Klassen im JDK respektieren nicht die besten objektorientierten Gestaltungsprinzipien. Ein Grund dafür ist die Tatsache, dass sie vor fast 20 Jahren geschrieben wurden, als sich die Objektorientierung erst als Mainstream-Paradigma herauskristallisierte und viele Programmierer sie einfach nicht so kannten, wie sie jetzt sind. Ein sehr gutes Beispiel für ein schlechtes API-Design ist das Date & Time API, dessen Änderung 19 Jahre gedauert hat ...
quelle
Diese Antwort ist großartig und wahr.
Ich wollte hinzufügen, dass in einigen Fällen Kompromisse aus Gründen der Benutzerfreundlichkeit gemacht wurden.
Objekte vom Typ String können ohne neues Ereignis instanziiert werden, wenn String kein Grundelement ist:
Ein String, der kein Primitiv ist, sollte wie folgt instanziiert werden:
Der Compiler lässt jedoch die kürzere, weniger OO-Option zu, da String die bei weitem am häufigsten verwendete Klasse in der API ist.
Arrays können auch auf Nicht-OO-Weise initialisiert werden:
Seltsamerweise ist ein Objekt entweder eine Instanz einer Klasse oder ein Array . Das heißt, Arrays sind ein völlig separater Klassentyp.
Arrays haben ein
length
öffentliches Feld, das keine Konstante ist. Außerdem gibt es keine Dokumentation zu den Klassen-Arrays, von denen eine Instanz ist. (Nicht zu verwechseln mit Arrays class oder java.reflect.Array).quelle
new String("Hello")
immer ein neues String-Objekt. WhileString s = "Hello";
verwendet das internierte Objekt. Vergleichen Sie:"Hello" == "Hello"
kann wahr sein, währendnew String("Hello") == new String("Hello")
immer falsch ist. In der ersten Phase findet eine Magie zur Optimierung der Kompilierungszeit statt, die mit nicht möglich istnew String("Hello")
. Siehe en.wikipedia.org/wiki/String_interningString s = new String("Hello");
", die falsch ist. Die kürzere Option (String s = "Hello";
) ist mehr korrekt , weil die Zeichenfolge Internierung.String
gibt es keine "korrektere" Option. Beide sind richtig. Obwohl, wie MichaelT sagt, die kürzere wegen String-Internierung bevorzugt wird.