Java'da, neden bir günlükçü bildirmek en iyi uygulamadır static final
?
private static final Logger S_LOGGER
Java'da, neden bir günlükçü bildirmek en iyi uygulamadır static final
?
private static final Logger S_LOGGER
Yanıtlar:
private
- böylece başka hiçbir sınıf kaydedicinizi ele geçiremezstatic
- böylece sınıf başına yalnızca bir günlük kaydedici örneği vardır ve ayrıca günlükleri serileştirme girişimlerini de önlerfinal
- sınıfın ömrü boyunca kaydediciyi değiştirmeye gerek yokAyrıca, adın log
olabildiğince basit ama açıklayıcı olmasını tercih ederim .
DÜZENLEME: Ancak bu kuralların ilginç bir istisnası var:
protected final Logger log = LoggerFactory.getLogger(getClass());
aksine:
private static final Logger log = LoggerFactory.getLogger(Foo.class);
İlk yöntem, miras hiyerarşisi boyunca tüm sınıflarda aynı günlükçü adını (gerçek sınıfın adı) kullanmanıza izin verir. Yani eğer Bar
genişlerse Foo
, her ikisi de Bar
logger'a kaydedilir. Bazıları bunu daha sezgisel buluyor.
log
kodu dağıtmak yerine yazmayı daha kolay ve daha keyifli bir ad okumayı tercih ediyorum LOG
. Sadece bir geliştirme meselesi. takım anlaşması.
Şu blog gönderisine bakın: Java Static Logger'lardan Kurtulun . Jcabi-log ile slf4j'yi şu şekilde kullanıyorsunuz :
import com.jcabi.log.Logger;
class Foo {
void save(File f) {
Logger.info(this, "file %s saved successfully", f);
}
}
Ve bu statik gürültüyü bir daha asla kullanmayın.
static
Yalnızca değil, sınıf başına başına bir logger bir Logger oluşturmak demek olduğunu örneğinin sınıfının. Genel olarak, istediğiniz şey budur - çünkü kaydediciler yalnızca sınıfa göre değişme eğilimindedir.
final
logger
değişkenin değerini değiştirmeyeceğiniz anlamına gelir . Bu doğrudur, çünkü neredeyse her zaman tüm günlük mesajlarını (bir sınıftan) aynı kaydediciye atarsınız. Bir sınıfın farklı bir kaydediciye bazı mesajlar göndermek isteyebileceği ender durumlarda bile, widgetDetailLogger
statik bir değişkenin değerini anında değiştirmekten ziyade başka bir kaydedici değişkeni (örneğin ) oluşturmak çok daha açık olacaktır .
Alanın değerini ne zaman değiştirmek istersiniz?
Değeri asla değiştirmeyecekseniz, alanı final yapmak , değeri asla değiştirmeyeceğinizi açıkça ortaya koyar.
Normalde, sınıf adını kullanarak günlüğe kaydediciyi başlatırsınız - bu, statik olmasalar, sınıfın her bir örneğinin bir örneğine sahip olacağı anlamına gelir (yüksek bellek ayak izi), ancak tüm bu kaydediciler aynı yapılandırmayı paylaşır ve tamamen aynı şekilde davranır. static
Biraz arkasındaki sebep bu . Ayrıca Logger
, her biri sınıf adıyla başlatıldığından, alt sınıflarla çakışmaları önlemek private
için, miras alınamayacak şekilde beyan edersiniz . final
Normalde değişmez o noktadan itibaren gelir Logger
ile (ki bu durumda kimsenin değiştirebilirsiniz sağlamak için nihai hale getirmek için mantıklı - bu yüzden zaman onu "yeniden yapılandırılmış" asla başlatıldı - yürütülürken hata veya başka türlü). Tabii ki kullanacaksanızLogger
farklı bir şekilde ihtiyaç duyabileceğiniz DEĞİL kullanımına static final
- ancak yukarıda açıklandığı gibi uygulamaların% 80 günlüğü kullanmak istiyorsunuz tahmin girişim olacaktır.
Bu soruyu cevaplamak için, kendinize "durağan" ve "son" un ne anlama geldiğini sormanız gerekir.
Bir Logger için (Log4J Logger sınıfı hakkında konuştuğunuzu varsayıyorum) sınıf başına bir kategori istiyorsunuz. Bu, onu yalnızca bir kez atamanıza yol açmalıdır ve sınıf başına birden fazla örneğe gerek yoktur. Ve muhtemelen bir sınıfın Logger nesnesini diğerine ifşa etmek için bir neden yoktur, öyleyse neden onu özel yapıp bazı OO İlkelerini takip etmiyorsunuz?
Ayrıca, derleyicinin bundan faydalanabileceğini de unutmamalısınız. Yani kodunuz biraz daha iyi performans gösteriyor :)
Çünkü bu, genellikle nesnelerinizin tüm örnekleri arasında paylaşılabilen bir tür işlevselliktir. Aynı sınıfın iki örneği için farklı bir kaydediciye sahip olmak çok mantıklı değildir (zamanın% 90'ı).
Bununla birlikte, bazen günlükçü sınıflarının tekli olarak bildirildiğini veya hatta öğelerinizi kaydetmek için statik işlevler sunduğunu da görebilirsiniz.
Bu kod savunmasızdır , ancak Java7'den sonra Logger lgr = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
statik günlükleyici yerine kullanabiliriz .
This is code is vulnerable
Biraz cevap verir misin?
İdeal olarak Logger, Sonar vermemek ve Uyumlu Kod vermek için Java 7'ye kadar aşağıdaki şekilde olmalıdır: özel: asla ana sınıfının dışında erişilemez. Başka bir sınıfın bir şeyi günlüğe kaydetmesi gerekiyorsa, kendi günlükçüsünü başlatmalıdır. statik: bir sınıfın (bir nesnenin) bir örneğine bağlı olmayın. Bir şeyi günlüğe kaydederken, içeriğe dayalı bilgiler elbette mesajlarda sağlanabilir, ancak kaydedici, her bir nesneyle birlikte bir kaydedici oluşturmayı ve dolayısıyla Yüksek Bellek ayak izini önlemeyi önlemek için sınıf düzeyinde oluşturulmalıdır. final: sınıf başına bir kez ve yalnızca bir kez oluşturulur.
Diğer cevaplarda verilen nedenlere ek olarak, karşılaştığım bir şey, kaydedicimin ne statik ne de nihai olmamasıydı:
...
public Logger logger = LoggerFactory.getLogger(DataSummary.class);
public String toJson() {
GsonBuilder gsonBuilder = new GsonBuilder();
return gsonBuilder.create().toJsonTree(this).toString();
}
...
belirli durumlarda (Gson kitaplığını kullanırken) stackoverflow istisnası alırdım. Benim özel durumum, statik olmayan son günlük kaydediciyi içeren sınıfı somutlaştırmaktı. Sonra GsonBuilder'ı çağıran toJson yöntemini çağırın:
...
DataSummary ds = new DataSummary(data);
System.out.println(ds.toJson());
...
Aslında statik kaydediciler, statik bir bağlamda çalışması gerektiğinden "zararlı" olabilir. Dinamik bir ortama sahipken örn. OSGi, statik olmayan kaydedicilerin kullanılmasına yardımcı olabilir. Bazı günlük uygulamaları dahili olarak kaydedicilerin önbelleğe alınmasını sağladığından (AFAIK en azından log4j) performans etkisi ihmal edilebilir.
Statik kaydedicilerin bir dezavantajı, örn. çöp toplama (bir sınıf yalnızca bir kez kullanıldığında, örneğin başlatma sırasında kaydedici hala ortalıkta tutulacaktır).
Daha fazla ayrıntı için kontrol edin:
Ayrıca bakınız:
Logger'ı statik hale getirip getirmeme konusunda internetten okuduğum bilgilere göre, en iyi uygulama onu kullanım durumlarına göre kullanmaktır.
İki ana argüman var:
1) Statik hale getirdiğinizde, çöp toplanmaz (bellek kullanımı ve performans).
2) Statik yapmadığınızda, her sınıf örneği için oluşturulur (bellek kullanımı)
Bu nedenle, bir singleton için bir kaydedici oluştururken, onu statik hale getirmenize gerek yoktur. Çünkü sadece bir örnek ve dolayısıyla bir kaydedici olacaktır.
Öte yandan, bir model veya varlık sınıfı için bir kaydedici oluşturuyorsanız, yinelenen günlükler oluşturmamak için statik hale getirmelisiniz.