Почему мы объявляем статичные фишки Loggers?
В Java, почему лучше всего объявить logger static final
?
private static final Logger S_LOGGER
Ответы
Ответ 1
-
private
- чтобы ни один другой класс не мог захватить ваш логгер
-
static
- поэтому для каждого экземпляра есть только один экземпляр журнала, а также избегать попыток сериализации журналов
-
final
- не нужно менять регистратор на время жизни класса
Кроме того, я предпочитаю, чтобы имя log
было как можно более простым, но описательным.
EDIT: Однако есть интересные исключения из этих правил:
protected final Logger log = LoggerFactory.getLogger(getClass());
в отличие от:
private static final Logger log = LoggerFactory.getLogger(Foo.class);
Первый способ позволяет использовать одно и то же имя регистратора (имя фактического класса) во всех классах во всей иерархии наследования. Поэтому, если Bar
extends Foo
, оба будут записываться в Bar
logger. Некоторые считают это более интуитивным.
Ответ 2
Отметьте это сообщение в блоге: Избавиться от Java Static Loggers. Так вы используете slf4j с jcabi-log:
import com.jcabi.log.Logger;
class Foo {
void save(File f) {
Logger.info(this, "file %s saved successfully", f);
}
}
И никогда больше не используйте этот статический шум.
Ответ 3
static
означает, что вы создаете только один Logger для каждого класса, а не один регистратор на один экземпляр вашего класса. Как правило, это то, что вы хотите - поскольку регистраторы имеют тенденцию меняться исключительно на основе класса.
final
означает, что вы не собираетесь изменять значение переменной logger
. Это верно, поскольку вы почти всегда бросаете все сообщения журнала (из одного класса) в один и тот же журнал. Даже в редких случаях, когда класс может отправлять некоторые сообщения другому регистратору, было бы намного проще создать другую переменную регистратора (например, widgetDetailLogger
), а не мутировать значение статической переменной "на лету".
Ответ 4
Чтобы ответить на этот вопрос, вы должны были спросить себя, для чего нужны "статические" и "окончательные".
Для регистратора (я предполагаю, что вы говорите о Log4J Logger class) вы хотите иметь категорию для каждого класса. Это должно привести к тому, что вы назначаете его только один раз, и нет необходимости в более чем одном экземпляре для каждого класса. И, по-видимому, нет причин подвергать объект Logger одного класса другому, поэтому почему бы не сделать его закрытым и следовать некоторым принципам OO.
Также следует отметить, что компилятор может воспользоваться преимуществами этого. Таким образом, ваш код работает немного лучше:)
Ответ 5
Когда вы хотите изменить значение поля?
Если вы никогда не измените значение, сделав поле окончательным, станет очевидным, что вы никогда не измените значение.
Ответ 6
Потому что это обычно тип функционала, который можно разделить на все экземпляры ваших объектов. Не имеет смысла (90% времени) иметь другой регистратор для двух экземпляров одного и того же класса.
Однако вы также можете видеть, что иногда классы логгеров объявляются как одиночные или даже предлагают статические функции для регистрации ваших вещей.
Ответ 7
Обычно вы инициализируете регистратор для ведения журнала с использованием имени класса, что означает, что если они не были статичными, вы попадаете в каждый экземпляр класса, имеющего экземпляр (высокий объем памяти), но все эти регистраторы будут иметь одну и ту же конфигурацию и вести себя точно так же. Это причина бит static
. Кроме того, поскольку каждый Logger
инициализируется именем класса, чтобы предотвратить конфликты с подклассами, вы объявляете его private
, чтобы он не мог быть унаследован.
final
исходит из того, что вы обычно не меняете Logger
во время выполнения, поэтому после инициализации вы никогда не "повторно настроили" его, и в этом случае имеет смысл сделать его окончательным, чтобы гарантировать отсутствие его можно изменить (по ошибке или иначе).
Конечно, если вы собираетесь использовать Logger
по-другому, вам может понадобиться NOT для использования static final
- но я бы рискнул предположить, что 80% приложений будут использовать протоколирование, как описано выше.
Ответ 8
Этот код уязвим, но после Java7 мы можем использовать Logger lgr = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
вместо статического регистратора.
Ответ 9
В большинстве случаев вы собираетесь изменить значение, а модификатор final
отметит его. Для каждого экземпляра класса вам не нужны отдельные экземпляры, поэтому static
. И в первую очередь это для производительности - он может быть хорошо оптимизирован (окончательный) и сохраняет memmory (статический).
Ответ 10
В дополнение к причинам, приведенным в других ответах, я столкнулся с тем, что если мой регистратор не был ни статичным, ни окончательным:
...
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());
...