Java: Как получить объект класса текущего класса от статического контекста?

'Неложью возврата', они означают возвращать любое значение, которое не удалось бы к булевой лжи. Таким образом, Вы могли возвратиться true, 1, 'non-false', или независимо от того, что можно продумать.

11
задан DivideByHero 20 August 2009 в 16:45
поделиться

7 ответов

Вы можете добавить «Класс» в качестве первого параметра и перегрузить метод журнала:

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), все они будут иметь один экземпляр регистратора.

14
ответ дан 3 December 2019 в 04:53
поделиться

, запрос трассировки стека может быть бесполезным для вашей проблемы. У вас есть 3 возможных подхода.

Exception # getStackTrace ()

Просто создайте экземпляр исключения и получите первый кадр:

static String className() {
    return new RuntimeException().getStackTrace()[0].getClassName();
}

Thread

Использование 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);
}
7
ответ дан 3 December 2019 в 04:53
поделиться

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

public static void do_something_static(Class callingClass){
  log(callingClass, "Some message from static");
}
0
ответ дан 3 December 2019 в 04:53
поделиться

Изменить метод журнал кому:

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");
}
2
ответ дан 3 December 2019 в 04:53
поделиться

Вместо «этого» использования »

1
ответ дан 3 December 2019 в 04:53
поделиться

Что ж, если вы действительно не хотите жестко кодировать что-то вроде ClassName.class , тогда вы можете попытаться определить класс, пройдя трассировку стека. К счастью, кто-то уже сделал это :). Также рассмотрите возможность использования регистратора, который позволяет вам регистрировать что-либо без указания вызывающего объекта.

0
ответ дан 3 December 2019 в 04:53
поделиться

Замените статические функции нестатическими. Вместо

Utils.do_something(...)

выполните

new Utils().do_something(...)
-1
ответ дан 3 December 2019 в 04:53
поделиться
Другие вопросы по тегам:

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