Регистратор Java, который автоматически определяет имя класса вызывающей стороны

Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  1. Вызов метода экземпляра объекта null.
  2. Доступ или изменение поля объекта null.
  3. Принимая длину null, как если бы это был массив.
  4. Доступ или изменение слотов null, как если бы это был массив.
  5. Бросок null как будто это было значение Throwable.

Приложения должны бросать экземпляры этого класса, чтобы указать на другие незаконные использования объекта null.

Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html

35
задан yanchenko 26 July 2013 в 00:51
поделиться

12 ответов

Я предполагаю, что это добавляет много издержек для каждого класса. Каждый класс должен 'искаться'. Вы создаете новые объекты Throwable сделать это... Эти throwables не прибывают бесплатно.

16
ответ дан Daan 27 November 2019 в 06:32
поделиться

Если Вам действительно не нужен Ваш Регистратор для помех, Вы могли использовать

final Logger logger = LoggerFactory.getLogger(getClass());
0
ответ дан Asgeir S. Nilsen 27 November 2019 в 06:32
поделиться

Этот механизм вставляет большое дополнительное усилие во времени выполнения.

, Если Вы используете Eclipse в качестве своего IDE, рассмотрите использование Log4e. Этот удобный плагин генерирует объявления регистратора для Вас использующий Вашу любимую платформу журналирования. Часть больше усилия при кодировании времени, но очень меньше работы над временем выполнения.

0
ответ дан Bill Michell 27 November 2019 в 06:32
поделиться

Почему нет?

public static Logger getLogger(Object o) {
  final Logger logger = Logger.getLogger(o.getClass());
  logger.setLevel(ResourceManager.LOGLEVEL);
  return logger;
}

И затем когда Вам нужен регистратор для класса:

getLogger(this).debug("Some log message")
0
ответ дан Mario Ortegón 27 November 2019 в 06:32
поделиться

Я предпочитаю создавать (статический) Регистратор для каждого класса (с, он - явное имя класса). Я, чем использую регистратор как есть.

2
ответ дан Philip Helger 27 November 2019 в 06:32
поделиться

Вы могли, конечно, просто использовать Log4J с соответствующим расположением шаблона:

, Например, для имени класса "org.apache.xyz. SomeClass", шаблон %C {1} произведет "SomeClass".

http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html

2
ответ дан Ian 27 November 2019 в 06:32
поделиться

Для каждого класса, с которым Вы используете это, Вы оказываетесь перед необходимостью искать Регистратор так или иначе, таким образом, Вы могли бы также просто использовать статический Регистратор в тех классах.

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

Тогда Вы просто ссылка, что регистратор, когда необходимо сделать сообщения журнала. Ваш метод делает то же самое, которое статический Регистратор Log4J уже делает итак, почему перестраивают колесо?

4
ответ дан 18Rabbit 27 November 2019 в 06:32
поделиться

Создание отслеживания стека является относительно медленной операцией. Ваша вызывающая сторона уже знает, в каком классе и методе это находится, таким образом, усилие потрачено впустую. Этот аспект Вашего решения неэффективен.

Даже при использовании статической информации о классе Вы не должны выбирать Регистратор снова для каждого сообщения. От автора из Log4j, Ceki GГјlcГј:

наиболее распространенная ошибка в классах обертки является вызовом метода Logger.getLogger по каждому запросу журнала. Это, как гарантируют, нанесет ущерб производительности Вашего приложения. Действительно!!!

Это - стандартная, эффективная идиома для получения Регистратора, во время инициализации класса:

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

Примечание, что это дает Вам отдельный Регистратор для каждого типа в иерархии. Если Вы придумаете метод, который вызывает getClass() на экземпляр, Вы будете видеть сообщения, зарегистрированные базовым типом, обнаруживающимся под регистратором подтипа. Возможно, это желательно в некоторых случаях, но я нахожу его сбивающим с толку (и я склонен одобрять состав по наследованию так или иначе).

, Очевидно, с помощью динамического типа через getClass() потребует, чтобы Вы получили регистратор, по крайней мере, однажды на экземпляр, а не однажды в классе как рекомендуемая идиома с помощью статической информации о типе.

23
ответ дан erickson 27 November 2019 в 06:32
поделиться

Вы не должны создавать новый объект Throwable. Можно просто звонить Thread.currentThread().getStackTrace()[1]

2
ответ дан ykaganovich 27 November 2019 в 06:32
поделиться

Предполагая, что вы храните статические ссылки на логгеры, вот автономный статический синглтон:

public class LoggerUtils extends SecurityManager
{
    public static Logger getLogger()
    {
        String className = new LoggerUtils().getClassName();
        Logger logger = Logger.getLogger(className);
        return logger;
    }

    private String getClassName()
    {
        return getClassContext()[2].getName();
    }
}

Использование хорошее и чистое:

Logger logger = LoggerUtils.getLogger();
8
ответ дан 27 November 2019 в 06:32
поделиться

На самом деле у нас есть нечто очень похожее в классе LogUtils. Да, это довольно неприятно, но, насколько мне известно, преимущества того стоят. Мы хотели убедиться, что у нас нет никаких накладных расходов из-за его многократного вызова, поэтому наш (несколько хакерский) гарантирует, что он может быть вызван ТОЛЬКО из статического контекста инициализатора, а-ля:

private static final Logger LOG = LogUtils.loggerForThisClass();

Он не будет работать, если он будет вызван из обычного метода или из инициализатора экземпляра (т. е. если «статика» не указана выше), чтобы снизить риск потери производительности. Метод следующий:

public static Logger loggerForThisClass() {
    // We use the third stack element; second is this method, first is .getStackTrace()
    StackTraceElement myCaller = Thread.currentThread().getStackTrace()[2];
    Assert.equal("<clinit>", myCaller.getMethodName());
    return Logger.getLogger(myCaller.getClassName());
}

Любой, кто спрашивает, какое преимущество у этого есть перед

= Logger.getLogger(MyClass.class);

, вероятно, никогда не имел дела с кем-то, кто копирует и вставляет эту строку из другого места и забывает изменить имя класса, оставляя вам иметь дело с классом который отправляет все свои данные другому регистратору.

18
ответ дан 27 November 2019 в 06:32
поделиться

Тогда лучше всего смешать два .

public class LoggerUtil {

    public static Level level=Level.ALL;

    public static java.util.logging.Logger getLogger() {
        final Throwable t = new Throwable();
        final StackTraceElement methodCaller = t.getStackTrace()[1];
        final java.util.logging.Logger logger = java.util.logging.Logger.getLogger(methodCaller.getClassName());
        logger.setLevel(level);

        return logger;
    }
}

И тогда в каждом классе:

private static final Logger LOG = LoggerUtil.getLogger();

в коде :

LOG.fine("debug that !...");

Вы получаете статический регистратор, который вы можете просто копировать и вставлять в каждый класс и без накладных расходов ...

Алаа

3
ответ дан 27 November 2019 в 06:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: