La definición de los campos in
y out
dentro de la System
clase son:
public final static PrintStream out;
public final static InputStream in;
Estas son constantes. También son objetos, pero son constantes. Es muy similar a la clase de matemáticas:
public static final double E = 2.7182818284590452354;
public static final double PI = 3.14159265358979323846;
O en la clase booleana:
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
O en la clase de 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);
Al acceder a una constante pública que no cambia, no hay una ventaja significativa para encapsularla, ya sea conceptualmente o en función del rendimiento. Está allá. No va a cambiar
No hay una diferencia real entre Color.white
y System.out
.
enum
para mantenerlos ... aunqueenum
era nuevo con Java 1.5 (no era una opción en los 1.0 días).final static
ystatic final
? Si es así, ¿qué es?La verdadera razón es que este es un problema heredado. Las
System.in,out,err
constantes eran parte de Java 1.0 ... y probablemente mucho más atrás. Cuando quedó claro que el diseño tenía problemas, ya era demasiado tarde para solucionarlo. Lo mejor que podían hacer era agregar losSystem.setIn,setOut,setErr
métodos en Java 1.1 y luego tratar los problemas de especificación del lenguaje 1 .Esto es similar a la cuestión de por qué hay un
System.arraycopy
método estático cuyo nombre viola las convenciones de nomenclatura de Java.En cuanto a si esto es "mal diseño" o no, creo que lo es. Hay situaciones en las que el manejo actual sin OO es un problema grave. (Piense ... cómo puede ejecutar un programa Java dentro de otro cuando sus requisitos de flujo de "IO estándar" entran en conflicto. Piense ... en el código de prueba de la unidad que implica cambiar los flujos).
Sin embargo, también puedo relacionarme con el argumento de que la forma actual de hacer las cosas es más conveniente en muchos casos.
1 - Es interesante notar que las
System.in,out,err
variables reciben una mención especial en el JLS por tener una "semántica especial". El JLS dice que si cambia el valor de unfinal
campo, el comportamiento no está definido ... excepto en el caso de estos campos.fuente
Creo que el objeto externo es inmutable, lo que lo hace de alguna manera seguro (esto es discutible) para mantenerse en un campo estático final público.
Muchas de las clases en el JDK no respetan los mejores principios de diseño orientado a objetos. Una razón para esto es el hecho de que fueron escritos hace casi 20 años, cuando la Orientación a Objetos solo estaba emergiendo como un paradigma convencional y muchos programadores simplemente no estaban familiarizados con ellos como lo están ahora. Un muy buen ejemplo de diseño de API incorrecto es la API de fecha y hora, que tardó 19 años en cambiar ...
fuente
Esta respuesta es genial y verdadera.
Quería agregar que en algunos casos se hicieron compromisos por el bien de la usabilidad.
Los objetos de tipo String se pueden instanciar sin un nuevo evento cuando String no es primitivo:
Al ser una cadena no primitiva, se debe instanciar así:
Pero el compilador permite la opción más corta y menos OO, porque String es, con mucho, la clase más utilizada en la API.
También las matrices se pueden inicializar de una manera no OO:
Por extraño que parezca, un objeto es una instancia de una clase o una matriz . Las matrices de significado son un tipo de clase completamente separado.
Las matrices tienen un
length
campo público que no es una constante. Además, no hay documentación sobre las matrices de clases de las que se trata. (no confundir con la clase Arrays o java.reflect.Array).fuente
new String("Hello")
siempre creará un nuevo objeto String. MientrasString s = "Hello";
usará el objeto interno. Comparar:"Hello" == "Hello"
puede ser cierto, mientrasnew String("Hello") == new String("Hello")
que siempre es falso. Hay una magia de optimización de tiempo de compilación sucediendo en el primero que no es posible connew String("Hello")
. Ver en.wikipedia.org/wiki/String_interningString s = new String("Hello");
" lo cual es incorrecto. La opción más corta (String s = "Hello";
) es más correcta debido al internamiento de cadenas.String
, no hay una opción "más correcta". Ambos son correctos. Sin embargo, como dice MichaelT, se prefiere el más corto debido al internamiento de String.