Чому на Java чому найкраще застосовувати реєстрацію реєстратора static final
?
private static final Logger S_LOGGER
Чому на Java чому найкраще застосовувати реєстрацію реєстратора static final
?
private static final Logger S_LOGGER
Відповіді:
private
- так що жоден інший клас не може викрасти ваш лісорубstatic
- тож існує лише один екземпляр реєстратора в класі, що також уникає спроб серіалізації реєстраторівfinal
- не потрібно змінювати реєстратор протягом життя класуКрім того, я вважаю за краще, log
щоб ім’я було максимально простим, але описовим.
EDIT: Однак є цікавий виняток із цих правил:
protected final Logger log = LoggerFactory.getLogger(getClass());
на відміну від:
private static final Logger log = LoggerFactory.getLogger(Foo.class);
Колишній спосіб дозволяє використовувати однакове ім’я реєстратора (ім'я фактичного класу) у всіх класах у всій ієрархії спадкування. Тож якщо Bar
розширення Foo
, обидва ввійдуть до Bar
реєстратора. Деякі вважають це більш інтуїтивно зрозумілим.
log
ім'я, а не розкидати код за допомогою LOG
. Справа дев. командна угода.
Перевірте цю публікацію в блозі: Позбудьтесь статичних журналів Java . Ось як ви використовуєте slf4j з jcabi-log :
import com.jcabi.log.Logger;
class Foo {
void save(File f) {
Logger.info(this, "file %s saved successfully", f);
}
}
І ніколи більше не використовуйте цей статичний шум.
static
означає, що ви створюєте лише один реєстратор у класі, а не один реєстратор на примірник вашого класу. Взагалі, це саме те, що ти хочеш - оскільки лісоруби мають тенденцію змінюватися виключно залежно від класу.
final
означає, що ви не збираєтесь змінювати значення logger
змінної. Що вірно, оскільки ви майже завжди кидаєте всі повідомлення журналу (з одного класу) в один і той же реєстратор. Навіть у рідкісних випадках, коли клас може захотіти надсилати деякі повідомлення до іншого реєстратора, було б набагато зрозуміліше створити іншу змінну реєстратора (наприклад widgetDetailLogger
), а не мутувати значення статичної змінної на льоту.
Коли ви хочете змінити значення поля?
Якщо ви ніколи не збираєтесь змінювати значення, завдяки тому, що фінал поля дає зрозуміти, що ви ніколи не змінюєте значення.
Зазвичай ви ініціалізуєте журнал реєстрації, використовуючи ім'я класу - це означає, що якби вони не були статичними, ви б закінчували кожен екземпляр класу, який має його примірник (високий слід пам'яті), але всі ці реєстратори мали б мають однакову конфігурацію і поводяться абсолютно однаково. Це причина за static
шматочком. Крім того, оскільки кожен Logger
ініціалізується з назвою класу, щоб запобігти конфліктам з підкласами, ви заявляєте його, private
щоб він не міг успадковуватися. Це final
відбувається з того, що ви зазвичай не змінюєте Logger
під час виконання - так що після ініціалізації ви ніколи не "переконфігурували" його - у цьому випадку має сенс зробити остаточне, щоб ніхто не міг його змінити ( помилка чи інше). Звичайно, якщо ви збираєтесь використовувати aLogger
по-іншому вам може знадобитися НЕ використовувати static final
- але я б ризикну здогадатися, що 80% додатків використовуватимуть журнал, як пояснено вище.
Щоб відповісти на це запитання, ви мали б запитати себе, що таке "статичне" та "остаточне".
Для Logger, (я вважаю, що ви говорите про клас Log4J Logger), вам потрібна категорія на клас. Що повинно призвести до того, що ви призначаєте його лише один раз, і не потрібно більше одного екземпляра на клас. І, мабуть, немає причин піддавати об’єкт Logger одного класу іншому, то чому б не робити його приватним та слідувати деяким принципам ОО.
Також слід зазначити, що компілятор може скористатися цим. Так ваш код працює трохи краще :)
Тому що це, як правило, вид функціональності, яким можна ділитися у всіх примірниках ваших об'єктів. Немає особливого сенсу (90% часу) мати різний реєстратор для двох примірників одного класу.
Однак ви також можете побачити іноді класи реєстраторів, оголошені як одиночні кнопки, або навіть просто пропонувати статичні функції для реєстрації ваших речей.
В ідеалі Logger має бути наступним чином до Java 7, щоб не надавати Sonar і надавати Код відповідності: приватний: ніколи не бути доступним за межами свого батьківського класу. Якщо іншому класу потрібно щось зареєструвати, він повинен створити власний реєстратор. статичний: не залежати від екземпляра класу (об’єкта). Під час реєстрації чогось, звичайно, у повідомленнях може бути надана контекстна інформація, але реєстратор повинен бути створений на рівні класу, щоб запобігти створенню реєстратора разом з кожним об'єктом і, отже, запобігання сліду високої пам'яті. остаточний: створюється один раз і лише один раз у класі.
На додаток до причин, наведених в інших відповідях, я натрапив на те, що якщо мій лісоруб не був ні статичним, ні остаточним:
...
public Logger logger = LoggerFactory.getLogger(DataSummary.class);
public String toJson() {
GsonBuilder gsonBuilder = new GsonBuilder();
return gsonBuilder.create().toJsonTree(this).toString();
}
...
у певних випадках (коли я використовував бібліотеку Gson), я отримав би виняток stackoverflow. Моя конкретна ситуація полягала в тому, щоб створити екземпляр класу, що містить нестатичний не остаточний реєстратор. Потім зателефонуйте до методу toJson, який викликав GsonBuilder:
...
DataSummary ds = new DataSummary(data);
System.out.println(ds.toJson());
...
Насправді статичні реєстратори можуть бути "шкідливими", оскільки вони повинні працювати в статичному контексті. При наявності динамічного середовища, наприклад. OSGi може допомогти використовувати нестатичні реєстратори. Оскільки деякі реалізації журналів здійснюють кешування журналів внутрішньо (AFAIK принаймні log4j), вплив на продуктивність може бути незначним.
Одним недоліком статичних реєстраторів є, наприклад. збирання сміття (коли клас використовується лише один раз, наприклад, під час ініціалізації журнал зберігається навколо).
Для отримання більш детальної інформації перевірте:
Дивитися також:
Згідно з інформацією, яку я прочитав з Інтернету про те, як зробити лісоруб статичним чи ні, найкращим методом є використання його відповідно до випадків використання.
Є два основні аргументи:
1) Коли ви робите статичну, вона не збирає сміття (використання пам'яті та продуктивність).
2) Якщо ви не робить його статичним, він створюється для кожного екземпляра класу (використання пам'яті)
Таким чином, коли ви створюєте реєстратор для одиночного, вам не потрібно робити його статичним. Тому що буде лише один екземпляр, таким чином, один реєстратор.
З іншого боку, якщо ви створюєте реєстратор для моделі або класу сутності, вам слід статично не створювати дублюються реєстратори.