Mengapa kita menyatakan final Loggers statis?


131

Di Jawa, mengapa praktik terbaik untuk mendeklarasikan logger static final?

private static final Logger S_LOGGER

Jawaban:


209
  • private- sehingga tidak ada kelas lain yang dapat membajak logger Anda
  • static - jadi hanya ada satu instance logger per kelas, juga menghindari upaya untuk membuat serial logger
  • final - tidak perlu mengubah logger selama masa pakai kelas

Juga, saya lebih suka nama logsesederhana mungkin, namun deskriptif.

EDIT: Namun ada pengecualian yang menarik untuk aturan ini:

protected final Logger log = LoggerFactory.getLogger(getClass());

sebagai lawan:

private static final Logger log = LoggerFactory.getLogger(Foo.class);

Cara sebelumnya memungkinkan Anda untuk menggunakan nama logger yang sama (nama kelas aktual) di semua kelas di seluruh hierarki warisan. Jadi jika Bardiperluas Foo, keduanya akan masuk ke Barlogger. Beberapa merasa lebih intuitif.


36
jika statis dan final maka agak LOG (huruf besar)
zacheusz

39
@zacheusz , saya tahu, itu intinya. Beberapa mengikuti konvensi penamaan Java secara religius (tidak ada yang salah dengan itu), tetapi saya lebih suka menulis lebih mudah dan lebih menyenangkan untuk membaca lognama daripada menyebarkan kode dengan LOG. Hanya masalah dev. perjanjian tim.
Tomasz Nurkiewicz

27
Harap dicatat bahwa tidak lagi selalu disarankan untuk menyatakan penebang sebagai statis dan final, lihat slf4j.org/faq.html#declared_static dan wiki.apache.org/commons/Logging/FrequentlyAskedQuestions section Haruskah saya mendeklarasikan referensi log statis atau tidak?
Matthew Farwell

6
@zacheusz Nama bidang huruf besar digunakan untuk konstanta. Logger tidak konstan. http://stackoverflow.com/questions/1417190/should-a-static-final-logger-be-declared-in-upper-case
michal.kreuzman

2
@ zacheusz tidak semua atribut final statis harus DITEMUKAN: stackoverflow.com/questions/1417190/…
bsmk

15

Periksa posting blog ini: Singkirkan Java Static Loggers . Ini adalah bagaimana Anda menggunakan slf4j dengan jcabi-log :

import com.jcabi.log.Logger;
class Foo {
  void save(File f) {
    Logger.info(this, "file %s saved successfully", f);
  }
}

Dan jangan pernah menggunakan kebisingan statis itu lagi.


Alternatif yang menarik dan tentunya lebih bersih. Saya bertanya-tanya bagaimana skala ini dibandingkan dengan penebang kelas individu.
Ross

12
Tulis Logger lagi .. (ini, ...) setiap kali. Tidak
Mikhail Boyarsky

Komentar pertama dalam posting blog terkait menunjukkan sisi jahat dari metode statis :) Jadi menggunakan Logger akhir pribadi adalah praktik terbaik yang saya kira.
Bahadir Tasdemir

5

staticberarti Anda hanya membuat satu Logger per kelas, bukan satu logger per instance kelas Anda. Secara umum, inilah yang Anda inginkan - karena para penebang cenderung bervariasi hanya berdasarkan kelas.

finalberarti Anda tidak akan mengubah nilai loggervariabel. Yang benar, karena Anda hampir selalu membuang semua pesan log (dari satu kelas) ke logger yang sama. Bahkan pada kesempatan langka di mana kelas mungkin ingin mengirim beberapa pesan ke logger yang berbeda, akan jauh lebih jelas untuk membuat variabel logger lain (misalnya widgetDetailLogger) daripada dengan memutasikan nilai variabel statis dengan cepat.


4

Kapan Anda ingin mengubah nilai bidang?

Jika Anda tidak akan pernah mengubah nilainya, membuat final bidang membuatnya jelas bahwa Anda tidak akan pernah mengubah nilainya.


1
Dalam banyak-banyak kasus itu jelas tanpa menambahkan kata final, yang mana hal ini menjadi semacam sampah.
Dima

2
@Dima: Yah saya masih bersyukur bahwa kompiler masih akan melakukan kesalahan jika saya secara tidak sengaja mencoba mengubah nilai dalam kasus-kasus ini ...
Jon Skeet

3

Biasanya Anda menginisialisasi logger untuk login menggunakan nama kelas - yang berarti bahwa jika mereka tidak statis, Anda akan berakhir dengan setiap instance dari kelas yang memiliki instance dari itu (jejak memori tinggi), tetapi semua penebang ini akan berbagi konfigurasi yang sama dan berperilaku sama persis. Itulah alasan di balik itu static. Juga karena masing Logger- masing diinisialisasi dengan nama kelas, untuk mencegah konflik dengan subclass, Anda mendeklarasikannya privatesehingga tidak dapat diwarisi. Itu finaldatang dari titik yang biasanya Anda tidak mengubah Loggerselama eksekusi - jadi setelah diinisialisasi Anda tidak pernah "mengkonfigurasi ulang" itu - dalam hal ini masuk akal untuk membuatnya final untuk memastikan tidak ada yang bisa mengubahnya (oleh kesalahan atau sebaliknya). Tentu saja jika Anda akan menggunakanLoggerdengan cara yang berbeda, Anda mungkin TIDAK perlu menggunakan static final- tapi saya berani menebak 80% aplikasi akan menggunakan logging seperti dijelaskan di atas.


3

Untuk menjawab pertanyaan itu, Anda seharusnya bertanya pada diri sendiri untuk apa "statis" dan "final".

Untuk seorang Logger, (saya berasumsi Anda berbicara tentang kelas Log4J Logger) Anda ingin kategori per kelas. Yang seharusnya mengarah pada fakta bahwa Anda menetapkannya hanya sekali, dan tidak perlu lebih dari satu instance per kelas. Dan mungkin tidak ada alasan untuk mengekspos objek Logger dari satu kelas ke kelas lain, jadi mengapa tidak menjadikannya pribadi dan mengikuti beberapa Prinsip-OO.

Anda juga harus mencatat, bahwa kompiler dapat mengambil manfaat dari itu. Jadi kode Anda berkinerja lebih baik :)


2

Karena itu biasanya jenis fungsi yang dapat dibagi di semua contoh objek Anda. Tidak masuk akal (90% dari waktu) memiliki logger berbeda untuk dua instance dari kelas yang sama.

Namun, Anda juga dapat melihat kadang-kadang kelas logger dinyatakan sebagai lajang atau bahkan hanya menawarkan fungsi statis untuk mencatat barang-barang Anda.


2

Kode ini rentan, tetapi, setelah Java7, kita dapat menggunakan Logger lgr = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); sebagai ganti dari pencatat statis.


This is code is vulnerableBisakah Anda menjelaskan sedikit jawaban?
Dmitry Zagorulkin

1

Dalam kebanyakan kasus, Anda tidak akan mengubah referensi dan mengubahnya final. Anda tidak perlu instance terpisah untuk setiap instance kelas - jadi static. Dan pertama-tama ini adalah untuk kinerja - dapat dioptimalkan dengan baik (final) dan menghemat memori (statis).


1

Idealnya Logger harus sebagai tindak lanjut hingga Java 7, karena tidak memberikan Sonar dan memberikan Kode yang Memenuhi Syarat: pribadi: tidak pernah dapat diakses di luar kelas induknya. Jika kelas lain perlu mencatat sesuatu, itu harus membuat instance logger sendiri. statis: tidak bergantung pada turunan suatu kelas (objek). Saat mencatat sesuatu, informasi kontekstual tentu saja dapat disediakan dalam pesan tetapi logger harus dibuat di tingkat kelas untuk mencegah membuat logger bersama dengan setiap objek dan karenanya mencegah jejak Memori Tinggi. final: dibuat sekali dan hanya sekali per kelas.


0

Selain alasan yang diberikan dalam jawaban lain satu hal yang saya temui adalah bahwa jika logger saya tidak statis atau final:

...
public Logger logger = LoggerFactory.getLogger(DataSummary.class);

public String toJson() {
  GsonBuilder gsonBuilder = new GsonBuilder();   
  return gsonBuilder.create().toJsonTree(this).toString();
}
...

dalam kasus-kasus tertentu (ketika saya menggunakan perpustakaan Gson) saya akan mendapatkan pengecualian stackoverflow. Situasi spesifik saya adalah untuk instantiate kelas yang berisi logger non final non statis. Kemudian panggil metode toJson yang memanggil GsonBuilder:

...
DataSummary ds = new DataSummary(data);    
System.out.println(ds.toJson());
...

0

Sebenarnya penebang statis bisa "berbahaya" karena mereka seharusnya bekerja dalam konteks statis. Ketika memiliki lingkungan yang dinamis misalnya. OSGi mungkin membantu menggunakan penebang non-statis. Karena beberapa implementasi logging melakukan caching terhadap penebang secara internal (AFAIK setidaknya log4j) dampak kinerja mungkin dapat diabaikan.

Salah satu kelemahan dari penebang statis adalah misalnya. pengumpulan sampah (ketika sebuah kelas hanya digunakan sekali mis. selama inisialisasi logger akan tetap disimpan).

Untuk lebih jelasnya periksa:

Lihat juga:


0

Menurut info yang saya baca dari internet tentang membuat logger statis atau tidak, praktik terbaik adalah menggunakannya sesuai dengan kasus penggunaan.

Ada dua argumen utama:

1) Ketika Anda membuatnya statis, itu bukan sampah yang dikumpulkan (penggunaan memori & kinerja).

2) Ketika Anda tidak membuatnya statis itu dibuat untuk setiap instance kelas (penggunaan memori)

Jadi, Saat Anda membuat logger untuk singleton, Anda tidak perlu membuatnya statis. Karena hanya akan ada satu instance sehingga satu logger.

Di sisi lain, jika Anda membuat logger untuk kelas model atau entitas, Anda harus membuatnya statis untuk tidak membuat duplikat logger.


-1

Anda masih memerlukan logger statis untuk kelas statis dalam

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.