Moje pytanie dotyczy klas System.in
i System.out
klas (mogą istnieć inne, takie jak te w bibliotece Standard). Dlaczego? Czy to nie jest zła praktyka w OOP? Nie należy go używać jako: System.getIn()
i System.getOut()
? Zawsze miałem to pytanie i mam nadzieję, że znajdę tutaj dobrą odpowiedź.
java
object-oriented
encapsulation
Clawdidr
źródło
źródło
enum
do trzymania ich ... chociażenum
było nowe w Javie 1.5 (nie jest to opcja w ciągu 1.0 dni).final static
istatic final
? Jeśli tak to co to jest?Prawdziwym powodem jest to, że jest to problem spuścizny. Na
System.in,out,err
stałe były częścią Java 1.0 ... i pewnie dużo dalej wstecz. Gdy stało się jasne, że projekt ma problemy, było już za późno, aby go naprawić. Najlepsze, co mogli zrobić, to dodaćSystem.setIn,setOut,setErr
metody w Javie 1.1, a następnie rozwiązać problemy ze specyfikacją języka 1 .Jest to podobne do pytania, dlaczego istnieje
System.arraycopy
metoda statyczna , której nazwa narusza konwencje nazewnictwa Java.Jeśli chodzi o to, czy jest to „zły projekt”, czy nie, myślę, że tak. Są sytuacje, w których obecna obsługa bez OO stanowi poważny problem. (Pomyśl ... jak możesz uruchomić jeden program Java w innym, gdy konflikt wymagań jego standardowego strumienia we / wy. Pomyśl ... kod testu jednostkowego, który pociąga za sobą zmianę strumieni.)
Mogę jednak również odnieść się do argumentu, że obecny sposób robienia rzeczy jest wygodniejszy w wielu przypadkach.
1 - Warto zauważyć, że
System.in,out,err
zmienne są szczególnie wymieniane w JLS jako mające „specjalną semantykę”. JLS mówi, że jeśli zmienisz wartośćfinal
pola, zachowanie jest niezdefiniowane ... z wyjątkiem tych pól.źródło
Uważam, że nasz obiekt jest niezmienny, co czyni go w jakiś sposób bezpiecznym (jest to kwestia dyskusyjna) z powodu trzymania go w publicznym polu statycznym.
Wiele klas w JDK nie przestrzega najlepszych zorientowanych obiektowo zasad projektowania. Jednym z powodów tego jest fakt, że zostały napisane prawie 20 lat temu, kiedy Object-Orientation pojawił się jako główny paradygmat i wielu programistów po prostu ich nie znało. Bardzo dobrym przykładem złego projektu API jest Date & Time API, którego zmiana zajęła im 19 lat ...
źródło
Ta odpowiedź jest świetna i prawdziwa.
Chciałem dodać, że w niektórych przypadkach dokonano kompromisów ze względu na użyteczność.
Obiekty typu String mogą być tworzone bez nowych, zdarzenie, gdy String nie jest prymitywem:
Ciąg znaków, który nie jest prymitywny, powinien być utworzony w następujący sposób:
Ale kompilator pozwala na krótszą, mniejszą liczbę opcji OO, ponieważ String jest zdecydowanie najczęściej używaną klasą w API.
Również tablice mogą być inicjowane w sposób inny niż OO:
Co dziwne, obiekt jest instancją klasy lub tablicy . Tablice znaczeń są całkowicie odrębnym typem klas.
Tablice mają
length
publiczne pole, które nie jest stałe. Również nie ma dokumentacji dotyczącej tablic klas, które są instancją. (nie mylić z klasą Arrays lub java.reflect.Array).źródło
new String("Hello")
zawsze utworzy nowy obiekt String. ChociażString s = "Hello";
użyje internowanego obiektu. Porównaj:"Hello" == "Hello"
może być prawdziwe, podczas gdynew String("Hello") == new String("Hello")
zawsze jest fałszywe. Po pierwsze dzieje się magia optymalizacji czasu kompilacji, która nie jest możliwanew String("Hello")
. Zobacz en.wikipedia.org/wiki/String_interningString s = new String("Hello");
”, co jest niepoprawne. Krótsza opcja (String s = "Hello";
) jest bardziej poprawna z powodu internowania łańcucha.String
nie ma opcji „więcej poprawnych”. Obydwie są prawidłowe. Chociaż, jak mówi MichaelT, krótszy jest preferowany ze względu na internowanie String.