Как получить регистратор для подкласса?
У меня есть подкласс и суперкласс. В суперклассе у меня есть метод, который записывает что-то. Когда я создаю экземпляр подкласса, регистратор создает сообщение о регистрации для суперкласса. Почему это происходит?
Пример кода:
SuperClass.java
import java.util.logging.Level;
import java.util.logging.Logger;
public abstract class SuperClass {
public void logAndPrintClass(){
String name = this.getClass().getName();
System.out.println(name);
Logger logger = Logger.getLogger(name);
logger.log(Level.INFO, "Logmessage");
}
}
SubClass.java
public class SubClass extends SuperClass {
}
TestLogBubClass.java
public class TestLogBubClass {
public static void main(String[] args){
SuperClass obj = new SubClass();
obj.logAndPrintClass();
}
}
Вывод:
SubClass
Mar 15, 2013 6:30:04 PM SuperClass logAndPrintClass
INFO: Logmessage
Как вы можете видеть, имя класса правильно напечатано, но неправильно представлено в сообщении журнала.
Ответы
Ответ 1
Эта причина в JavaDoc для LogRecord:
Обратите внимание, что если клиентское приложение не указало явное имя исходного метода и имя исходного класса, тогда класс LogRecord будет вызывать их автоматически при первом доступе (из-за вызова getSourceMethodName или getSourceClassName) путем анализа стека вызовов.
В этом случае стек вызовов заканчивается методом, определенным SuperClass
, поэтому LogRecord
предполагает, что он вызывает класс. Если вы хотите увидеть это в действии, выполните этот код:
public class Example {
public static class Superclass {
public void foo() {
new Exception().printStackTrace();
}
}
public static class Subclass extends Superclass {
// nothing here
}
public static void main(String[] argv)
throws Exception
{
Superclass s = new Subclass();
s.foo();
}
}
Изменить: я не использую j.u.l, но надеялся, что будет простой способ настройки вывода (как и в любой другой реализации регистратора). Похоже, вам придется реализовать свой собственный класс Formatter и указать его с помощью свойства java.util.logging.ConsoleHandler.formatter
.
Я бы порекомендовал, если возможно, переключиться на SLF4J. Вы можете подключить весь существующий код j.u.l через SLF4J к фактическому регистратору, который дает вам больше контроля над его выходом (например, Log4J или Logback).
Ответ 2
Этот код java.util.logging
довольно странный.
Ведение журнала не использует name
, но пытается выяснить сам исходный класс (который затем регистрируется).
Изучите метод private void inferCaller()
в классе java.util.logging.LogRecord
.
Ответ 3
@Parsifal объяснил, почему это происходит, я попытаюсь объяснить обходной путь.
Если вы хотите увидеть точный класс, где вызывается метод, я бы рекомендовал использовать log4j или slf4j. Если вам нужно использовать java.util.Logger
, пожалуйста, посмотрите jul-to-slf4j.
Я пробовал и для меня с теми же вводами ввода в моем стандартном выпуске выглядит следующим образом:
SubClass
15 марта 2013 г. 20:39:44 SuperClass logAndPrintClass
INFO: Logmessage
20: 39: 44 478 INFO SubClass: 12 - Logmessage
И в лог файле есть только:
20: 39: 44 478 INFO SubClass: 12 - Logmessage
Это может выглядеть не так хорошо, но в некоторых случаях это может быть подходящим решением.
Ответ 4
Я думаю, что у меня есть обходное решение, даже если я не могу дать полное объяснение.
Переопределение logAndPrintClass
с помощью только вызова super
, как это, в SubClass
:
class SubClass extends SuperClass {
protected void logAndPrintClass(){ super.logAndPrintClass(); }
}
Я все равно получаю тот же результат.
SubClass
Mar 15, 2013 11:22:10 AM SuperClass logAndPrintClass
INFO: Logmessage
Затем я просто скопировал тело метода в подкласс:
class SubClass extends SuperClass {
protected void logAndPrintClass(){
String name = this.getClass().getName();
System.out.println(name);
Logger logger = Logger.getLogger(name);
logger.log(Level.INFO, "Logmessage");
}
}
Затем я получил другой вывод:
SubClass
Mar 15, 2013 11:23:31 AM SubClass logAndPrintClass
Я не знаю, почему это работает, но единственная разница, которую я, кажется, обнаруживаю, заключается в том, что объект Logger
теперь создается внутри подкласса, а не внутри суперкласса.