Haruskah "pemblokir akhir statis" dideklarasikan dalam UPPER-CASE?

243

Di Jawa, variabel final statis adalah konstanta dan konvensi adalah bahwa mereka harus dalam huruf besar. Namun, saya telah melihat bahwa kebanyakan orang menyatakan penebang dalam huruf kecil yang muncul sebagai pelanggaran dalam PMD .

misalnya:

private static final Logger logger = Logger.getLogger(MyClass.class);

Cukup cari google atau SO untuk "pencatat akhir statis" dan Anda akan melihatnya sendiri.

Haruskah kita menggunakan LOGGER saja?

dogbane
sumber
PMD atau Checkstyle adalah upaya naif pra-matang untuk meningkatkan keterbacaan tetapi mereka menyebabkan lebih banyak kerugian daripada manfaat. Gaya yang paling mudah dibaca dapat mengubah kasus per kasus berdasarkan konteksnya. Lihat Guava, atau JDK src, itu tidak mengikuti template gaya yang ketat, tetapi dibuat oleh para profesional itu tidak perlu dipertanyakan lagi. contoh: DelegatedExecutorService @ docjar.com/html/api/java/util/concurrent/Executors.java.html
Daniel Hári
Sonar Rules ( rules.sonarsource.com/java/tag/convention/RSPEC-1312 ) juga memilikinyaprivate static final Logger LOGGER = LoggerFactory.getLogger(Foo.class);
Kenston Choi

Jawaban:

306

Referensi logger bukan konstanta, tetapi referensi final, dan TIDAK boleh dalam huruf besar. VALUE konstan harus dalam huruf besar.

private static final Logger logger = Logger.getLogger(MyClass.class);

private static final double MY_CONSTANT = 0.0;
crunchdog
sumber
42
referensi final statis adalah konstanta jika tidak dapat diubah. oleh logika ini, Anda tidak akan pernah memiliki string konstan karena string final statis adalah referensi.
Jeffrey Blattman
30
Tapi java.lang.String tetap dan jenis khusus kelas tetap (lihat String.intern (), dokumentasi tentang kolam Sring dll.)
Aleksander Adamowski
3
abadi berarti keadaan objek tidak dapat berubah setelah konstruksi. lihat posting saya di bawah ini. penebang belum tentu bisa berubah.
Jeffrey Blattman
4
jika seseorang masih peduli dengan masalah ini, silakan berbagi ide di github.com/checkstyle/checkstyle/issues/23 , untuk membedakan mana yang membutuhkan huruf besar dan mana yang tidak.
Roman Ivanov
2
@Jeach saya tidak berpikir ketidakberdayaan berkaitan dengan bagaimana keadaan berubah, hanya itu yang terjadi. apalagi, apa itu pengguna? pengguna eksternal yang menjalankan program? akankah Anda membuat perbedaan antara keadaan yang sedang dimodifikasi oleh pengguna yang menekan tombol, dan itu sedang dimodifikasi oleh penghitung waktu yang menembak pada suatu interval acak? (kurasa tidak).
Jeffrey Blattman
236

Untuk menambah nilai pada jawaban crunchdog, Java Coding Style Guide menyatakan ini dalam paragraf 3.3 Penamaan Bidang

Nama bidang yang digunakan sebagai konstanta harus huruf besar semua, dengan menggarisbawahi kata-kata yang memisahkan. Berikut ini dianggap konstanta:

  1. Semua static finaltipe primitif (Ingat bahwa semua bidang antarmuka secara inheren static final).
  2. Semua static finaltipe referensi objek yang tidak pernah diikuti oleh " ." (titik).
  3. Semua static finalarray yang tidak pernah diikuti oleh " [" (pembukaan braket persegi).

Contoh:

MIN_VALUE, MAX_BUFFER_SIZE, OPTIONS_FILE_NAME

Berikut konvensi ini, loggermerupakan static finalreferensi obyek sebagaimana dimaksud dalam butir 2, tetapi karena ini diikuti oleh " ." setiap kali Anda menggunakannya, itu tidak dapat dianggap sebagai konstan dan dengan demikian harus huruf kecil.

cbliard
sumber
11
Definisi terbaik yang pernah saya lihat untuk ini. Doc yang ditautkan tampaknya telah pindah ke sini, adalah pembaruan cs.bilgi.edu.tr/pages/standards_project/…
robert
15
Saya tidak mendapatkan poin 2. Apa contoh dari tipe objek yang tidak pernah diikuti oleh titik. Semua tipe objek mewarisi dari Objectdan Anda dapat memanggil metode seperti .equalsitu.
dogbane
6
Kamu benar. Dan ketika melihat beberapa konstanta Java seperti Boolean.TRUE, Boolean.FALSE, TimeUnit.MINUTES, String.CASE_INSENSITIVE_ORDER atau Collections.EMPTY_LIST, mereka dapat diikuti .juga.
cbliard
5
@RomanIvanov Saya menemukannya lagi di sini: scribd.com/doc/15884743/Java-Coding-Style-by-Achut-Reddy ditulis oleh Achut Reddy, pembaruan terakhir 30 Mei 2000
cbliard
1
Saya percaya tujuan 2 adalah untuk menetapkan bahwa hanya kelas yang dimaksudkan untuk dibandingkan yang dianggap konstanta. Kelas tidak dimaksudkan untuk 'digunakan'. Saya tahu selalu merasa ngeri ketika saya melihat SOME_CLASS.doStuff (). Itu hanya coding yang jelek. Satu-satunya masalah dengan ini adalah dalam kasus umum dari sebuah objek konstan (String menjadi contoh umum) yang hanya dimaksudkan untuk perbandingan, tetapi untuk menghindari cek kosong, pengkodean gaya yoda digunakan dan dengan demikian equal () dipanggil pada konstanta. Saya pikir saya akan membuat ini satu peringatan untuk 2.
Robin
44

Dari java efektif, edisi ke-2,

Satu-satunya pengecualian pada aturan sebelumnya adalah “bidang konstan,” yang namanya harus terdiri dari satu atau beberapa kata huruf besar yang dipisahkan oleh karakter garis bawah, misalnya, VALUES atau NEGATIVE_INFINITY. Bidang konstan adalah bidang final statis yang nilainya tidak berubah . Jika bidang final statis memiliki tipe primitif atau tipe referensi yang tidak dapat diubah (Butir 15), maka itu adalah bidang konstan. Sebagai contoh, konstanta enum adalah bidang konstan. Jika bidang akhir statis memiliki jenis referensi yang bisa berubah, itu masih bisa menjadi bidang konstan jika objek yang direferensikan tidak dapat diubah.

Singkatnya, konstan == final statis, ditambah jika itu referensi (vs tipe sederhana), kekekalan.

Melihat logger slf4j, http://www.slf4j.org/api/org/slf4j/Logger.html

Itu tidak berubah. Di sisi lain, JUL logger bisa berubah. Log4j logger juga bisa berubah. Jadi benar, jika Anda menggunakan log4j atau JUL, itu harus "logger", dan jika Anda menggunakan slf4j, itu harus LOGGER.

Perhatikan bahwa halaman jfcj slf4j yang ditautkan di atas memiliki contoh di mana mereka menggunakan "logger", bukan "LOGGER".

Ini tentu saja hanya konvensi dan bukan aturan. Jika Anda kebetulan menggunakan slf4j dan Anda ingin menggunakan "logger" karena Anda terbiasa dengan itu dari kerangka kerja lain, atau jika lebih mudah untuk mengetik, atau untuk keterbacaan, silakan.

Jeffrey Blattman
sumber
2
Berdasarkan alasan ini maka definisi sederhana checkstyle tidak tepat bukan?
robert
3
saya tidak tahu aturan cek gaya. jika itu hanya bersikeras bahwa final statis harus huruf besar, maka ya, itu salah.
Jeffrey Blattman
5
Bagaimana tepatnya Logger antarmuka tidak bisa diubah ? Hanya final class(suka Stringatau Integer) yang bisa menjamin keabadian. Sekalipun Anda tidak dapat menemukan implementasi SLF4J yang Loggerdapat diubah , tidak ada yang dapat menghentikan Anda untuk menulis sendiri.
Costi Ciudatu
Karena metode dalam antarmuka tidak memungkinkan mutasi secara inheren. Anda benar meskipun Anda bisa mengimplementasikan antarmuka untuk memiliki efek samping yang bisa berubah.
Jeffrey Blattman
Periksa aturan gaya TIDAK DEWASA cukup untuk menyiratkan keterbacaan. Keterbacaan tidak dapat dicapai dengan menggunakan gaya, keterbacaan dapat membedakan kasus per kasus berdasarkan konteksnya. Lihat kode JDK, tidak mengikuti template gaya apa pun, dan dibuat oleh para profesional, yang menunjukkan sesuatu.
Daniel Hári
37

Saya suka Google mengambilnya ( Google Java Style )

Setiap konstanta adalah bidang final statis, tetapi tidak semua bidang final statis adalah konstanta. Sebelum memilih kasus konstan, pertimbangkan apakah bidang tersebut benar-benar terasa seperti konstan. Sebagai contoh, jika salah satu dari keadaan yang dapat diamati contoh itu dapat berubah, hampir pasti tidak konstan. Hanya berniat untuk tidak pernah bermutasi objek umumnya tidak cukup.

Contoh:

// Constants
static final int NUMBER = 5;
static final ImmutableList<String> NAMES = ImmutableList.of("Ed", "Ann");
static final Joiner COMMA_JOINER = Joiner.on(',');  // because Joiner is immutable
static final SomeMutableType[] EMPTY_ARRAY = {};
enum SomeEnum { ENUM_CONSTANT }

// Not constants
static String nonFinal = "non-final";
final String nonStatic = "non-static";
static final Set<String> mutableCollection = new HashSet<String>();
static final ImmutableSet<SomeMutableType> mutableElements = ImmutableSet.of(mutable);
static final Logger logger = Logger.getLogger(MyClass.getName());
static final String[] nonEmptyArray = {"these", "can", "change"};
mateuscb
sumber
6
Saya pikir kalimat pertama merangkum dengan singkat: "Setiap konstanta adalah bidang final statis, tetapi tidak semua bidang final statis adalah konstanta." Sangat mudah untuk menggunakan pemikiran mekanis dan hanya memiliki setiap bidang akhir statis dalam huruf besar (dan saya telah melakukan ini sampai sekarang) tetapi ini akan kehilangan kehalusan bahasa.
ayahuasca
Menurut kutipan itu, itu bermuara pada jika bidang "benar-benar terasa" seperti sebuah konstanta. Kami insinyur, bukan psikiater.
Jeffrey Blattman
"Pertimbangkan ... jika itu benar-benar terasa seperti konstan". Perasaan seseorang benar-benar tidak boleh masuk ke bidang teknik.
Jeffrey Blattman
Kemudian dalam kode Guava mereka memilikinyaprivate static final Logger logger = Logger.getLogger(Finalizer.class.getName());
Kenston Choi
10

Jika Anda menggunakan alat otomatis untuk memeriksa standar pengkodean Anda dan itu melanggar standar kata maka itu atau standar harus diperbaiki. Jika Anda menggunakan standar eksternal, perbaiki kodenya.

Konvensi di Sun Java adalah huruf besar untuk konstanta statis publik. Jelas logger tidak konstan, tetapi merupakan hal yang bisa berubah (jika tidak, tidak ada gunanya memanggil metode dengan harapan bahwa sesuatu akan terjadi); tidak ada standar khusus untuk bidang final yang tidak konstan.

Pete Kirkham
sumber
10
Mengapa Anda mengatakan logger tidak konstan? Tampaknya memang konstan. Penebangan menghasilkan adalah efek samping dari memanggil metode-metodenya, tetapi tidak mengubah keadaan yang bisa diamati. Apakah saya melewatkan sesuatu?
KLE
Periksa API. Itu memang memiliki metode add / get pair. Tapi alasanmu tetap saja cacat. Penebangan dapat diamati (jika tidak, apa gunanya).
Tom Hawtin - tackline
3
Jika itu adalah StringBuilder daripada logger, maka itu mungkin akan lebih jelas tidak konstan. Bahkan untuk penebang, metode seperti Logger.setLevel () melakukan mutasi pada penerima yang diamati. Umumnya huruf besar adalah untuk konstanta-konstanta yang bahasa-bahasa memperlakukan sebagai konstanta dan akan sebaris.
Pete Kirkham
5
Logger bukan konstanta karena merupakan referensi ke objek. Konstanta adalah nilai yang tidak dapat diubah. Referensi objek bersifat final (jadi referensi tidak dapat diubah, mis. Ditukar dengan sesuatu yang lain atau setel ke nol) tetapi objek itu sendiri dapat.
Spoike
1
@ JeffreyBlattman Saya tidak setuju bahwa semua referensi final harus huruf besar, tetapi Anda bebas untuk mengadopsi standar pengkodean apa pun yang Anda suka. Saya menyesal Anda menemukan perbedaan antara 'objek yang dapat berubah-ubah' dan 'objek yang mewakili hal yang dapat diubah' membingungkan; satu contoh mungkin nomor akun belakang Anda, yang dengan sendirinya tidak berubah, tetapi digunakan untuk mengakses saldo variabel. Carilah perbedaan antara penanda dan signifikansi untuk detail lebih lanjut, atau pengantar untuk Leibnitz's monads tentang bagaimana suatu hal yang tidak dapat berubah dapat mewakili kemampuan berubah-ubah.
Pete Kirkham
7

Jika Anda Google ini, Anda mungkin menemukan bahwa dalam beberapa kasus, para penebang tidak didefinisikan sebagai final statis. Tambahkan beberapa copy-n-paste cepat ke ini, dan ini mungkin menjelaskannya.

Kami menggunakan LOGGER di semua kode kami, dan ini sesuai dengan konvensi penamaan kami (dan CheckStyle kami senang dengan itu).


Kami bahkan melangkah lebih jauh, mengambil keuntungan dari konvensi penamaan yang ketat di Eclipse. Kami membuat kelas baru dengan templat kode:

    // private static final Logger LOGGER = Logger.getLogger(${enclosing_type}.class);

Logger dikomentari, karena pada awalnya kita tidak membutuhkannya. Tetapi jika kita membutuhkannya nanti, kita cukup batalkan komentar itu.

Kemudian dalam kode, kami menggunakan templat kode yang mengharapkan pencatat ini hadir. Contoh dengan templat coba tangkap:

    try {
      ${cursor} or some other template
    } catch (Exception t) {
      LOGGER.error("${methodName} ${method parameters}", t);
    }

Kami memiliki beberapa templat lagi yang menggunakannya.

The konvensi yang ketat memungkinkan kita untuk menjadi lebih produktif dan koheren dengan kode template .

KLE
sumber
5
Menangkap Throwable adalah praktik yang buruk, kecuali Anda login dan rethrow. Remember Errors: OutOfMemeoryError, dll. Pengecualian Peristiwa tidak begitu aman untuk ditangkap dan ditangani sendiri di aplikasi multi-utas.
m_vitaly
2
Sintaks Eclipse adalah: Logger.getLogger ($ {enclosing_type} .class);
dogbane
@ fahdshariff Terima kasih atas sintaks yang tepat. Saya memperbarui jawaban saya.
KLE
Jika "konvensi ketat" dari CheckStyle atau PMD membantu, lalu mengapa sumber Guava, dan JDK tidak memiliki gaya umum APA SAJA yang berlaku? Misalnya sumber mereka memiliki banyak blok inline penuh di mana diperlukan. Keterbacaan tergantung pada konteks, jadi menggunakan konvensi penataan yang ketat untuk semuanya menghancurkan keputusan berdasarkan konteks, sehingga mengurangi keterbacaan.
Daniel Hári
6

Saya pribadi berpikir itu terlihat sangat besar dalam huruf besar. Selain itu, karena itu adalah kelas yang itu tidak berkaitan langsung dengan perilaku kelas, saya tidak melihat masalah besar dalam menggunakan loggerbukan LOGGER. Tetapi jika Anda akan benar-benar bertele-tele, maka gunakan LOGGER.

João Silva
sumber
4

Jangan lupa bahwa PMD akan menghormati komentar

// NOPMD

di dalamnya. Ini akan menyebabkan PMD melewatkan garis dari pemeriksaannya, ini akan memungkinkan Anda untuk memilih gaya mana yang Anda inginkan.

Fortyrunner
sumber
6
Atau jangan gunakan PMD, mereka selalu salah dan kode Anda sempurna
IAdapter
1
Jika Anda selalu perlu mengecualikan cek setiap saat, maka cek itu tidak masuk akal.
keiki
Tidak bisa setuju lebih - namun ... ini berguna untuk mengetahui komentar pengecualian
Fortyrunner
3

Biasanya konstanta dalam huruf besar.

Logger, bagaimanapun, tidak boleh statis tetapi mencari setiap "baru" dari kelas yang mengandung jika menggunakan fasad slf4j. Ini menghindari beberapa masalah classloader yang tidak menyenangkan dalam wadah web khusus, ditambah lagi memungkinkan kerangka logger untuk melakukan hal-hal khusus tergantung pada konteks doa.

Thorbjørn Ravn Andersen
sumber
2

Saya lebih suka 'logger', yaitu huruf kecil. Alasannya bukan karena itu adalah konstanta atau bukan konstanta (bisa berubah atau tidak berubah). Jika kita menggunakan alasan itu, kita harus mengubah nama variabel jika kita mengubah kerangka kerja logging (atau jika kerangka kerja mengubah mutabilitas penebang).

Bagi saya, alasan lain lebih penting.

  1. Logger adalah objek bayangan di kelas dan seharusnya tidak terlalu menonjol karena tidak mengimplementasikan logika utama. Jika kita menggunakan 'LOGGER', itu adalah eye catcher dalam kode yang menarik terlalu banyak perhatian.

  2. Kadang-kadang penebang dideklarasikan pada level instance (yaitu tidak statis), dan bahkan disuntikkan sebagai dependensi. Saya tidak ingin mengubah kode saya jika saya memutuskan untuk mengubah cara saya mendapatkan logger. Stabilitas kode wrt. perubahan (hipotetis dalam banyak kasus) ini adalah alasan lain mengapa saya lebih suka huruf kecil.

fml2
sumber
1

Jika standar pengkodean Anda - jika Anda punya - katakan itu huruf besar maka ya.

Saya tidak melihat alasan ketat untuk satu atau lain cara. Saya pikir itu benar-benar tergantung pada resp suka pribadi Anda. standar pengkodean perusahaan Anda.

BTW: Saya lebih suka "LOGGER" ;-)

Kutzi
sumber