'Неложью возврата', они означают возвращать любое значение, которое не удалось бы к булевой лжи. Таким образом, Вы могли возвратиться true
, 1
, 'non-false'
, или независимо от того, что можно продумать.
Вы можете добавить «Класс» в качестве первого параметра и перегрузить метод журнала:
public class SomeClass {
// Usage test:
public static void main( String [] args ) {
log( SomeClass.class, "Hola" );
log( new java.util.Date(), "Hola" );
}
// Object version would call Class method...
public static void log( Object o , String msg ) {
log( o.getClass(), msg );
}
public static void log( Class c , String message ) {
System.out.println( c.getSimpleName() + " " + message );
}
}
Вывод:
$ java SomeClass
SomeClass Hola
Date Hola
Но просто неприятно, когда вызывающий класс передается в качестве первого аргумента. Здесь в игру вступает объектно-ориентированная модель как противоположность «процедурному» стилю.
Вы можете получить вызывающий класс с помощью трассировки стека, но, как вы отметили, вызовите его тысячи раз возникнут накладные расходы.
Но , если вы создаете переменную is as class, тогда будет только один экземпляр для класса, если у вас будет 1000 классов, использующих эту утилиту, у вас будет не более 1000 вызовов.
Что-то вроде этого было бы лучше (тонкий вариант этого другого ответа):
public class LogUtility {
private final String loggingFrom;
public static LogUtility getLogger() {
StackTraceElement [] s = new RuntimeException().getStackTrace();
return new LogUtility( s[1].getClassName() );
}
private LogUtility( String loggingClassName ) {
this.loggingFrom = "("+loggingClassName+") ";
}
public void log( String message ) {
System.out.println( loggingFrom + message );
}
}
Тест использования:
class UsageClass {
private static final LogUtility logger = LogUtility.getLogger();
public static void main( String [] args ) {
UsageClass usageClass = new UsageClass();
usageClass.methodOne();
usageClass.methodTwo();
usageClass.methodThree();
}
private void methodOne() {
logger.log("One");
}
private void methodTwo() {
logger.log("Two");
}
private void methodThree() {
logger.log("Three");
}
}
OUtput
$ java UsageClass
(UsageClass) One
(UsageClass) Two
(UsageClass) Three
Обратите внимание на объявление:
....
class UsageClass {
// This is invoked only once. When the class is first loaded.
private static final LogUtility logger = LogUtility.getLogger();
....
Таким образом, это не ' Неважно, используете ли вы «регистратор» из objectA, objectB, objectC или из метода класса (например, main), все они будут иметь один экземпляр регистратора.
, запрос трассировки стека может быть бесполезным для вашей проблемы. У вас есть 3 возможных подхода.
Просто создайте экземпляр исключения и получите первый кадр:
static String className() {
return new RuntimeException().getStackTrace()[0].getClassName();
}
Использование Thread еще проще:
static String className2() {
return Thread.currentThread().getStackTrace()[1].getClassName();
}
эти два подхода имеют недостаток что вы не можете использовать их повторно. Итак, вы можете определить для этого вспомогательный класс:
class Helper {
public static String getClassName() {
return Thread.currentThread().getStackTrace()[2].getClassName();
}
}
теперь вы можете получить имя своего класса программно, без жесткого кодирования имени класса:
public static void log(Object o, String msg){
do_log(Helper.getCClassName() + " " + msg);
}
Вам следует жестко закодировать класс в вызове в ближайшее время. Если вы думаете, что вам это понадобится в различных местах вашего проекта, так как это static
, вы должны инкапсулировать его и использовать класс в качестве параметра.
public static void do_something_static(Class callingClass){
log(callingClass, "Some message from static");
}
Изменить метод журнал
кому:
public static void log(Class c, String msg){
do_log(c.getSimpleName()+" "+msg);
}
и если do_something_static
находится в классе MyClassWithStatics
, тогда do_something_static
станет:
public static void do_something_static(){
log(MyClassWithStatics.class, "Some message from static");
}
Что ж, если вы действительно не хотите жестко кодировать что-то вроде ClassName.class
, тогда вы можете попытаться определить класс, пройдя трассировку стека. К счастью, кто-то уже сделал это :). Также рассмотрите возможность использования регистратора, который позволяет вам регистрировать что-либо без указания вызывающего объекта.
Замените статические функции нестатическими. Вместо
Utils.do_something(...)
выполните
new Utils().do_something(...)