2010-06-14 16 views
7

Szukałem w czyimś kodzie i zobaczył, że wielokrotnie deklarowałaNa System.out, wyjaśnienie potrzebne

PrintStream out = System.out; 

a później nazywany

out.println("blah"); 

I rzeczywiście, że to był rodzaj schludne. Czy to powszechna praktyka? Czy był po prostu fancy?

+6

Mógł równie łatwo dodać deklarację "import static java.lang.System.out;" na górze pliku. – ILMTitan

+0

@ILMTitan to jeszcze bardziej porządne rozwiązanie, ale oczywiście będzie działać tylko z wersją Java 5 i nowszą. – Alb

+2

@Alb Java 5 zakończyła już okres końca okresu użytkowania. –

Odpowiedz

7

Jest to rozsądne podejście. W zasadzie tworzy alias dla System.out. Istnieje wiele korzyści:

  • Mniej pisania.
  • Łatwiejsze późniejsze zmienienie kodu na wyjście do innego strumienia wydruku.
  • Prawdopodobnie poprawa wydajności, mimo że będzie znikoma.
+0

punkt 1, nie mniej niż sysout , który wstawi "System.out.println()". Punkt 2 tak, ale oznacza to również, że możesz popełnić błąd zakładając, że "out" oznacza System.out.println, ponieważ tak zostało wykonane w innym miejscu kodu. Jest również bardziej jednoznaczny, jak nie używanie krótkich nazw zmiennych. Punkt 3 - nie. Kompilacja jest mądrzejsza od ciebie. NIGDY nie podejmuj decyzji w oparciu o to, co myślisz, kompilator zamierza zrobić, nie opierając się na testowaniu - twoje przypuszczenie jest prawie zawsze błędne, kompilator optymalizuje w oparciu o to, że nie jesteś podstępny - na pisanie najczystszego możliwego kodu. –

+0

@Bill K: Kompilator jest inteligentny, ale semantyka dostępu do pola i dostępu do zmiennych lokalnych jest różna, więc nie może zoptymalizować tego w ogóle. Kto powiedział, że println() nie zmienił wartości System.out? (Pola końcowe nie są tak ostateczne, jak mogłoby się wydawać - spójrz na System.setout().) –

+0

@ Adam Crume Przypuszczam, że powinienem był powiedzieć, że kompilator + środowisko wykonawcze jest mądrzejsze niż myślisz. Może patrzeć na to, że System.out się nie zmienia i wpisywać kod do niego. W rzeczywistości może on wbudować cały blok kodu, aby wykonać rzeczywisty wynik, jeśli chce - prawdopodobnie nie, ale nie byłbym zbyt zaskoczony, gdyby to zrobił. Jeśli masz alias "out", może to uniemożliwić taką optymalizację środowiska wykonawczego. Zasadniczo mówiłem tylko, że jeśli KIEDYKOLWIEK wykonujesz decyzję programistyczną w oparciu o teoretyczne zalety wydajności zamiast sprawdzonych zalet, naprawdę musisz to przemyśleć. –

0

To skrót jeśli robisz dużo println. Widziałem to zrobić w miejscach wcześniej, choć nie wydają się zrobić, bo myślę System.out.println jest jaśniejszy, ponieważ nie trzeba dowiedzieć się, gdzie out został przydzielony. Konfiguruję szablon zaćmienia, dzięki czemu mogę autouzupełnić println do System.out.println i jest dość szybki.

+0

Eclipse ma wbudowany szablon "sysout", więc nie musiałeś nawet tworzyć własne :) – benjismith

+0

To prawda, ale piszę dużo groovy kodu i w ten sposób mogę użyć println w dowolnym języku. –

0

Nie. Nigdy wcześniej tego nie widziałem.

Zgadzam się. Nie jest zbyt obskurny ...

3

Aby uniknąć wpisywania System.out.println specjalnie podczas wykonywania mały test (bez IDE) Używam import static java.lang.System.out zamiast

Ale to może mieć sens, jeśli chcesz zastąpić wartość System.out później, być może do owinięcia przekierować do pliku

PrintStream out = new FilePrintStream("MyLogs.log"); // // System.out 

Jednocześnie wycisz standardowe wyjście. Powtarzam to: may ma sens w niektórych scenariuszach, ponieważ do tego chciałbym użyć ramy Logging.

BTW, byłoby lepiej, aby uznać je za ostateczne i statyczne również:

class YourClass { 
    private final static PrintStream out = System.out; 
} 
0

Jeśli spojrzeć na Throwable.printStackTrace w dokumentacji można nazwać bez argumentów, a to po prostu przechodzi System.out do wersji, która pobiera PrintStream.

Często zdarza się, że można znaleźć wiele różnych obiektów PrintStream, co znacznie upraszcza drukowanie.

0

To urocza sztuczka, ale jak większość uroczych sztuczek może lepiej zrobić to dobrze.

Gdy dojdziesz do punktu, w którym na pewno chcesz się zalogować (na tyle, aby dodać coś takiego), dlaczego nie po prostu uzyskać Log4J lub inny system rejestrowania, który ma jeszcze większą elastyczność i moc?

Aliasy są urocze i zabawne, jeśli jesteś sam, ale nawet jeśli jesteś naprawdę powolnym maszynistą i oszczędzasz całe 5 sekund za każdym razem, gdy je wpisujesz (przez System.out lub "sysout +<ctrl-space>" w eclipse/netbeans), stracisz ten czas dziesięciokrotnie za pierwszym razem, gdy ktoś - prawdopodobnie ty - zobaczy "na zewnątrz". i nie wie od razu, co to znaczy.

Chodzi mi o to, że w jednym programie powiedzmy, że zrobiłeś to, co sugerował inny plakat i przekierowano "na zewnątrz", aby przejść do pliku zamiast STDOUT, ale w niektórych klasach może "wylogować" się do System.out. a może po prostu zapomnisz, że przekierowałeś go do pliku. Później przyjść i powiedzieć „dobrze, to mówi:

out.println("WE MADE IT"); 

ale nie widzę tej linii w standardowe wyjście, co do cholery?”

Następnie tracisz 4 godziny na śledzenie złego wskazania zamiast naprawiania błędu.

+0

Jeśli korzystałeś z Eclipse i widziałeś "out", czy nie wcisnąłbyś na nie F3 i nie zobaczyłbyś, dokąd zmierza, bez marnowania czasu? Jestem za usuwaniem duplikacji i usuwanie wywołania System.out wszędzie tam, gdzie jest używany, jest usuwanie duplikatów. Powody są dobrze określone przez odpowiedź http://stackoverflow.com/questions/3041482/plain-old-system-out-question/3041495#3041495 – Alb

+0

Nie, jeśli nie myślisz, o co chodzi. Wyraźnie bije krótko, gdy pracujesz z innymi. Kiedy jesteś sam, twój kod może być tak zabawny, jak chcesz, ale mam dość pracy nad innymi sztuczkami. Ta postawa zyskuje trochę miłości/nienawiści dzięki konwencjom nazywania zmiennych Java. Chodzi mi o to, że zaoszczędziłbyś tyle miejsca używając yalvn zamiast wpisywać nazwęAnotherLongVariableName, ale niektórzy ludzie zaczynają nabierać znaczenia jawnego przez krótki (przynajmniej w świecie Java - wciąż widzę dużo "yalvn" c zmiennej nazwy, tak jakby zajęły pamięć lub coś takiego) –

+0

Oczywiście doceniam przyzwoitą nazwę metody, ale w tym przypadku oryginalna nazwa metody jest po prostu "wylogowana". Po pierwsze, nie sądzę, aby ktokolwiek zakładał, że to System.out bez sprawdzania go, po drugie nie sądzę, że dodanie do niego pakietu przy każdym wywołaniu jest najlepszym sposobem radzenia sobie z nim. Wyodrębnianie wszystkich wywołań System.out do, na przykład, metody "printToConsole" lub "printToLogStream" jest lepsze niż pozostawienie ich w linii w mojej opinii, ponieważ usuwa duplikację, ale zachowuje jasność intencji. – Alb

0

To, czy jest to dobry pomysł, jest dyskusyjne i prawdopodobnie zależy od okoliczności.

Na plus:

  • To sprawia, że ​​wygląd neater kodu aplikacji.
  • Może to ułatwić zmianę miejsca docelowego dla danych wyjściowych.

Negatywną stroną:

  • To potencjalnie zwiększa sprzęgania krzyżowego; na przykład jeśli zmienna out jest zmienną instancji lub musi zostać przekazana jako parametr.
  • Potencjalnie powoduje problemy, jeśli aplikacja musi zadzwonić pod numer System.setOut().
  • Jeśli kod System.out właśnie debuguje, utrudni to zauważenie i usunięcie. Rzeczywiście, prawdopodobnie unieważnia on kontrolę jakości kodu PMD (etc), który zgłasza tego typu rzeczy.

Należy zauważyć, że istnieją potencjalne inne sposoby, aby to zrobić; na przykład Zastąpienie System.out.println(String) przy użyciu metody użytkowej uzyskuje podobny efekt bez sprzężenia poprzecznego.

0

od System.out jest zmienną final, to co zrobił byłoby identyfikatorem do odniesienia System.out bezpośrednio.

, chyba że ktoś o nazwie System.setOut() ponownie przypisał System.out.

czekaj, co?

1

Może to być spowodowane tym, że ogólnie nie jest zalecane zagnieżdżanie i używanie obiektów należących do innych obiektów. Wygląda to tak, jakby ktoś sięgał po twoją kieszeń, by wyciągnąć pieniądze z portfela zamiast prosić cię o pożyczenie pieniędzy.

Może to być niewielka korzyść, która mogłaby być w stanie zmienić strumień wyjściowy w razie potrzeby na plik, gniazdo lub cokolwiek innego.Więc będzie mógł wymienić:

PrintStream out = System.out; 

z

PrintStream out = new PrintStream(new FileOutputStream(filename)); 

Jeśli jednak jest on wielokrotnie deklarując ją w kółko, jest on naprawdę utraty powyższą zaletę, ponieważ cały punkt byłoby mieć to gdzieś scentralizowane i decyduje, gdzie wydrukować logi w jednym miejscu.

Należy zauważyć, że jest to bardzo surowy sposób, a prawdziwą standardową praktyką jest korzystanie z rejestrowania. Java ma swój własny pakiet java.util.logging po wyjęciu z pudełka, log4j to kolejna bardzo potężna alternatywa (i bardzo popularna) i są inne.