2016-02-25 3 views
3

Когда я вызываю java.util.logging.Logger.log(Level, String) из лямбда, метод java.util.logging.LogRecord.getSourceMethodName() возвращает lambda $ 0 на моем Formatter.

Например:

public void doStuff() { 
    List<String> names = new ArrayList<>(); 
    names.add("John"); 
    names.add("Paul"); 
    names.add("George"); 
    names.add("Ringo"); 

    names.forEach((beatle) -> Logger.getLogger("myLog").log(Level.SEVERE, beatle)); 
} 

Как я могу получить имя метода (DoStuff) вместо 'лямбда $ 0'?

PS: Я бы не хотел его получать из StackTrace.

ответ

2

От documentation of the Logger class:

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

Таким образом, способ, чтобы решить вашу проблему, чтобы указать имя класса и имя метода:

Logger logger = Logger.getLogger("myLog"); 
names.forEach(beatle -> logger.log(Level.SEVERE, 
    getClass().getName(), "doStuff", beatle)); 
+2

Вместо 'GetClass() GetName()', что лучше использовать 'SuroundingClass.class.. getName() ', поскольку фактический тип' this', возвращаемый 'getClass()', не обязательно является классом, содержащим фактическую реализацию 'doStuff()'. Кроме того, выражение лямбда не должно захватывать «это». – Holger

+1

@ Хольгер Я согласен, и лично я всегда так делаю. Но OP не включал имя класса, и я хотел, чтобы ответ был прост. – VGR

+0

@ VGR Я также подумал об этом обходном пути, но это может быть проблемой в случае переименования метода. Не забудьте также обновить строку. – hbelmiro