La définition des champs in
et out
dans la System
classe est:
public final static PrintStream out;
public final static InputStream in;
Ce sont des constantes. Ce sont aussi des objets, mais ce sont des constantes. C'est très similaire à la classe Math:
public static final double E = 2.7182818284590452354;
public static final double PI = 3.14159265358979323846;
Ou dans la classe booléenne:
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
Ou dans la classe Couleur:
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);
Lorsque vous accédez à une constante publique qui ne change pas, il n'y a pas d'avantage significatif à l'encapsuler - conceptuellement ou en fonction des performances. C'est là. Ça ne va pas changer.
Il n'y a pas de réelle différence entre Color.white
et System.out
.
enum
pour les conserver ... bien qu'ilenum
soit nouveau avec Java 1.5 (pas une option dans les 1.0 jours).final static
etstatic final
? Si oui, c'est quoi?La vraie raison est qu'il s'agit d'un problème hérité. Les
System.in,out,err
constantes faisaient partie de Java 1.0 ... et probablement beaucoup plus loin. Au moment où il était clair que la conception avait des problèmes, il était trop tard pour y remédier. Le mieux qu'ils pouvaient faire était d'ajouter lesSystem.setIn,setOut,setErr
méthodes dans Java 1.1, puis de traiter les problèmes de spécification du langage 1 .Ceci est similaire à la question de savoir pourquoi il existe une
System.arraycopy
méthode statique dont le nom viole les conventions de dénomination Java.Quant à savoir si c'est une "mauvaise conception" ou non, je pense que oui. Il y a des situations où la gestion non OO actuelle est un problème sérieux. (Pensez ... comment pouvez-vous exécuter un programme Java à l' intérieur d' un autre lorsque leurs exigences de flux "IO standard" entrent en conflit. Pensez ... au code de test unitaire qui implique de changer les flux.)
Cependant, je peux également comprendre l'argument selon lequel la manière actuelle de faire les choses est plus pratique dans de nombreux cas.
1 - Il est intéressant de noter que les
System.in,out,err
variables reçoivent une mention spéciale dans le JLS comme ayant une "sémantique spéciale". Le JLS indique que si vous modifiez la valeur d'unfinal
champ, le comportement n'est pas défini ... sauf dans le cas de ces champs.la source
Je crois que l'objet out est immuable, ce qui le rend en quelque sorte sûr (c'est discutable) pour être gardé dans un champ statique final public.
De nombreuses classes du JDK ne respectent pas les meilleurs principes de conception orientée objet. L'une des raisons à cela est le fait qu'ils ont été écrits il y a près de 20 ans, lorsque l'Orientation-Orientation émergeait seulement comme un paradigme dominant et que de nombreux programmeurs ne les connaissaient tout simplement pas comme ils le sont maintenant. Un très bon exemple de mauvaise conception d'API est l'API Date & Time, qui leur a pris 19 ans pour changer ...
la source
Cette réponse est grande et vraie.
Je voulais ajouter que dans certains cas, des compromis ont été faits pour des raisons de convivialité.
Les objets de type String peuvent être instanciés sans nouvel événement, lorsque String n'est pas une primitive:
La chaîne étant non primitive, elle doit être instanciée comme ceci:
Mais le compilateur permet l'option plus courte et moins OO, car String est de loin la classe la plus utilisée dans l'API.
Les tableaux peuvent également être initialisés de manière non OO:
Assez étrange, un objet est soit une instance d'une classe ou un tableau . Les tableaux de signification sont un type de classe complètement séparé.
Les tableaux ont un
length
champ public qui n'est pas une constante. Il n'y a pas non plus de documentation sur les tableaux de classes dont est une instance. (à ne pas confondre avec la classe Arrays ou java.reflect.Array).la source
new String("Hello")
créera toujours un nouvel objet String. WhileString s = "Hello";
utilisera l'objet interné. Comparer:"Hello" == "Hello"
peut être vrai, alors qu'ilnew String("Hello") == new String("Hello")
est toujours faux. Il y a une magie d'optimisation du temps de compilation qui se produit dans le premier qui n'est pas possible avecnew String("Hello")
. Voir en.wikipedia.org/wiki/String_interningString s = new String("Hello");
" ce qui est incorrect. L'option plus courte (String s = "Hello";
) est plus correcte en raison de l'internement de chaînes.String
, il n'y a pas d'option "plus correcte". Les deux sont corrects. Cependant, comme le dit MichaelT, le plus court est préféré en raison de l'internement de chaînes.