Получение информации о вызове класса - PullRequest
1 голос
/ 19 февраля 2010

Можно ли получить информацию о классе, который вызывает другой?


class Bar{
    public Bar{}

    public String getInvokingClassInfo(){
        return "...";
    }
}

class Foo{
    public Foo(){
       Bar bar = new Bar();
       System.out.println("Invoking class is: "+bar.getInvokingClassInfo());
    }
}

Как добраться по месту:


System.out.println(bar.getInvokingClassInfo());

информация о классе, который вызывает (Foo) этот (Bar):

Invoking class: Foo

Ответы [ 4 ]

8 голосов
/ 19 февраля 2010
 StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
 String callerClassName = stackTrace[index].getClassName();

Получает трассировку стека для текущего потока. Как отмечено в комментариях, есть различия в реализации, поэтому, если вы боитесь такого, вы можете реализовать что-то вроде этого:

  • цикл по массиву StackTraceElement (с использованием переменной счетчика, объявленной вне цикла)
  • всякий раз, когда вы сталкиваетесь с текущим именем класса и текущим методом, break
  • получить следующий элемент массива - это будет вызывающий объект. (это то, что index означает в приведенном выше коде)
  • если вышеупомянутое не дает соответствующей информации, вы всегда можете вернуться к new Exception().getStackTrace()
3 голосов
/ 19 февраля 2010

Лучшее (хотя и искаженное и уродливое) решение, о котором я мог подумать, - это выбросить исключение внутри Bar и сразу его перехватить, а затем извлечь информацию о вызывающем абоненте из трассировки стека.

Обновление на основе комментариев других пользователей: вам даже не нужно бросать и ловить исключение, new Exception().getStackTrace() сделает свое дело.

2 голосов
/ 20 февраля 2010

Самый надежный способ, который я могу себе представить, это передать "this" в качестве аргумента B изнутри A. Затем B может взглянуть на объект и распечатать его класс.

Все, что возится со следами стека, полагается на вещи, которые не гарантированно работают. Подход "пас-это" будет.

0 голосов
/ 22 февраля 2013

Простейшим способом, который я нашел, было создание следующего класса:

private static class ClassLocator extends SecurityManager {
    public static Class<?> getCallerClass() {       
        return new ClassLocator().getClassContext()[2];
    }
}

Как сказано в Справочнике API:

"protected Class [] getClassContext () Возвращает текущий стек выполнения какмассив классов. Длина массива - это число методов в стеке выполнения. Элемент с индексом 0 является классом выполняемого в данный момент метода, элемент с индексом 1 является классом вызывающего этого метода и т. д.. "

http://docs.oracle.com/javase/7/docs/api/java/lang/SecurityManager.html#getClassContext()

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