Dlaczego w Javie najlepiej jest zadeklarować program rejestrujący static final
?
private static final Logger S_LOGGER
Dlaczego w Javie najlepiej jest zadeklarować program rejestrujący static final
?
private static final Logger S_LOGGER
Odpowiedzi:
private
- aby żadna inna klasa nie mogła przejąć twojego loggerastatic
- więc istnieje tylko jedna instancja programu rejestrującego na klasę, co pozwala również uniknąć prób serializacji rejestratorówfinal
- nie ma potrzeby zmiany loggera w czasie trwania klasyPonadto wolę, log
aby nazwa była jak najprostsza, a jednocześnie opisowa.
EDYCJA: Istnieje jednak ciekawy wyjątek od tych zasad:
protected final Logger log = LoggerFactory.getLogger(getClass());
w przeciwieństwie do:
private static final Logger log = LoggerFactory.getLogger(Foo.class);
Pierwszy sposób umożliwia użycie tej samej nazwy programu rejestrującego (nazwy rzeczywistej klasy) we wszystkich klasach w hierarchii dziedziczenia. Więc jeśli Bar
rozszerzy Foo
, oba będą logować się do Bar
rejestratora. Niektórzy uważają to za bardziej intuicyjne.
log
nazwy niż rozpraszanie kodu LOG
. Tylko kwestia dev. umowa zespołowa.
Sprawdź ten wpis na blogu: Pozbądź się Java Static Loggers . Oto jak używasz slf4j z jcabi-log :
import com.jcabi.log.Logger;
class Foo {
void save(File f) {
Logger.info(this, "file %s saved successfully", f);
}
}
I nigdy więcej nie używaj tego statycznego szumu.
static
oznacza, że tworzysz tylko jeden program rejestrujący na klasę, a nie jeden program rejestrujący na instancję swojej klasy. Generalnie tego właśnie chcesz - ponieważ rejestratory zwykle różnią się wyłącznie w zależności od klasy.
final
oznacza, że nie zamierzasz zmieniać wartości logger
zmiennej. Co jest prawdą, ponieważ prawie zawsze wysyłasz wszystkie komunikaty dziennika (z jednej klasy) do tego samego programu rejestrującego. Nawet w rzadkich przypadkach, gdy klasa może chcieć wysłać jakieś komunikaty do innego programu rejestrującego, znacznie bardziej przejrzyste byłoby utworzenie innej zmiennej rejestrującej (np. widgetDetailLogger
) Zamiast modyfikowania wartości zmiennej statycznej w locie.
Kiedy chciałbyś zmienić wartość pola?
Jeśli nigdy nie zamierzasz zmieniać wartości, ostateczna wersja pola sprawia, że oczywiste jest , że nigdy nie zmienisz wartości.
Zwykle inicjujesz rejestrator do rejestrowania przy użyciu nazwy klasy - co oznacza, że gdyby nie były statyczne, skończyłoby się na tym, że każda instancja klasy miałaby swoją instancję (duży ślad pamięci), ale wszystkie te rejestratory mają tę samą konfigurację i zachowują się dokładnie tak samo. To jest powód tego static
bitu. Ponieważ każda Logger
z nich jest inicjalizowana nazwą klasy, aby zapobiec konfliktom z podklasami, deklarujesz ją, private
aby nie mogła być dziedziczona. final
Pochodzi od miejsca, które normalnie nie zmienić Logger
w trakcie realizacji - tak raz zainicjowany nigdy „rekonfiguracji” to - w tym przypadku ma to sens, aby końcowy, aby zapewnić nikt nie może go zmienić (przez błąd lub w inny sposób). Oczywiście, jeśli masz zamiar użyćLogger
w inny sposób, może być konieczne NIE do użytku static final
- ale Zaryzykowałbym domyślić 80% aplikacji użyłby rejestrowanie jak wyjaśniono powyżej.
Aby odpowiedzieć na to pytanie, powinieneś zadać sobie pytanie, do czego służą „statyczne” i „ostateczne”.
Dla Loggera (zakładam, że mówisz o klasie Log4J Logger) chcesz mieć kategorię na klasę. Co powinno prowadzić do tego, że przypisujesz ją tylko raz i nie ma potrzeby posiadania więcej niż jednej instancji na klasę. I przypuszczalnie nie ma powodu, aby ujawniać obiekt Logger jednej klasy drugiej, więc dlaczego nie uczynić go prywatnym i przestrzegać pewnych zasad OO.
Należy również pamiętać, że kompilator może to wykorzystać. Twój kod działa więc trochę lepiej :)
Ponieważ zazwyczaj jest to rodzaj funkcji, która może być współdzielona we wszystkich instancjach twoich obiektów. Nie ma większego sensu (w 90% przypadków) posiadanie innego rejestratora dla dwóch instancji tej samej klasy.
Jednak czasami możesz zobaczyć klasy rejestratorów zadeklarowane jako pojedyncze lub nawet oferujące funkcje statyczne do rejestrowania twoich rzeczy.
Ten kod jest podatny na ataki ,, ale po Javie7 możemy użyć Logger lgr = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
zamiast statycznego rejestratora.
This is code is vulnerable
Czy mógłbyś trochę wyjaśnić swoją odpowiedź?
W większości przypadków nie będziesz zmieniać odniesienia, a final
modyfikator je oznaczy. Nie potrzebujesz osobnych instancji dla każdej instancji klasy - więc static
. A przede wszystkim ze względu na wydajność - można go ładnie zoptymalizować (finalnie) i oszczędzać pamięć (statycznie).
Idealnie byłoby, gdyby Logger był następujący aż do Java 7, aby nie dawać sonaru i dawać Zgodny kod: prywatny: nigdy nie będzie dostępny poza swoją klasą nadrzędną. Jeśli inna klasa musi coś zarejestrować, powinna utworzyć własną instancję rejestrującą. statyczny: nie zależy od instancji klasy (obiektu). Podczas rejestrowania czegoś, informacje kontekstowe mogą być oczywiście dostarczane w komunikatach, ale rejestrator powinien być utworzony na poziomie klasy, aby zapobiec tworzeniu programu rejestrującego wraz z każdym obiektem, a tym samym zapobiec zużyciu dużej ilości pamięci. finał: być utworzony raz i tylko raz na zajęcia.
Zgodnie z informacjami, które przeczytałem z Internetu, na temat ustawiania loggera w stanie statycznym lub nie, najlepszą praktyką jest używanie go zgodnie z przypadkami użycia.
Istnieją dwa główne argumenty:
1) Po ustawieniu go jako statycznego nie jest on zbierany jako śmieci (użycie pamięci i wydajność).
2) Jeśli nie ustawisz go statycznie, jest tworzony dla każdej instancji klasy (użycie pamięci)
Tak więc, kiedy tworzysz rejestrator dla singletona, nie musisz ustawiać go statycznie. Ponieważ będzie tylko jedna instancja, a więc jeden rejestrator.
Z drugiej strony, jeśli tworzysz program rejestrujący dla modelu lub klasy encji, powinieneś ustawić statyczne, aby nie tworzyć zduplikowanych rejestratorów.
Oprócz powodów podanych w innych odpowiedziach jedną rzecz, na którą natknąłem się, było to, że jeśli mój rejestrator nie był ani statyczny, ani ostateczny:
...
public Logger logger = LoggerFactory.getLogger(DataSummary.class);
public String toJson() {
GsonBuilder gsonBuilder = new GsonBuilder();
return gsonBuilder.create().toJsonTree(this).toString();
}
...
w niektórych przypadkach (gdy korzystałem z biblioteki Gson) otrzymywałem wyjątek stackoverflow. Moja konkretna sytuacja polegała na utworzeniu instancji klasy zawierającej niestatyczny, niekońcowy rejestrator. Następnie wywołaj metodę toJson, która wywołała GsonBuilder:
...
DataSummary ds = new DataSummary(data);
System.out.println(ds.toJson());
...
W rzeczywistości statyczne rejestratory mogą być „szkodliwe”, ponieważ powinny działać w kontekście statycznym. Mając dynamiczne środowisko np. OSGi może pomóc użycie niestatycznych rejestratorów. Ponieważ niektóre implementacje rejestrowania wykonują wewnętrzne buforowanie rejestratorów (AFAIK co najmniej log4j), wpływ na wydajność może być pomijalny.
Wadą rejestratorów statycznych jest np. wyrzucanie elementów bezużytecznych (gdy klasa jest używana tylko raz, np. podczas inicjalizacji, rejestrator będzie nadal dostępny).
Aby uzyskać więcej informacji, sprawdź:
Zobacz też: