getClass () и статические методы: какова лучшая практика? - PullRequest
1 голос
/ 02 марта 2009

Я хочу предоставить некоторое удобство для размышлений программистам, которые будут использовать мой код. Чтобы достичь желаемого результата, я хотел бы получить объект класса для классов, расширяющих мой код. Несмотря на то, что они не могут переопределить статический метод, из которого я хочу получить доступ к информации, в настоящее время это будет полезно. Я мог бы в конечном итоге просто немного реорганизовать дизайн, чтобы избежать этой ситуации, но хотел передать этот вопрос сообществу.

Единственный способ добиться этого, о котором я знаю, - это взять текущий поток, провести трассировку стека и извлечь имя класса, а затем преобразовать его в фактический экземпляр класса.

Любые другие предложения?

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

Ответы [ 4 ]

2 голосов
/ 02 марта 2009

К сожалению, ходить по стеку не всегда безопасно:

Из Javadoc JDK 6 для getStackTrace:

Некоторые виртуальные машины могут, под некоторыми обстоятельства, пропустите один или несколько стеков кадры из стека трассировки. в крайний случай, виртуальная машина, которая не имеет информации о трассировке стека относительно этого броска разрешено вернуть массив нулевой длины из Этот метод. Вообще говоря, массив, возвращаемый этим методом, содержит один элемент для каждого кадра это будет напечатано printStackTrace.

Вы можете, возможно, использовать API отладчика, чтобы сделать это. Я полагаю, что отладочная программа способна использовать HotSpot на полной скорости (я могу ошибаться), поэтому вы не увидите значительный удар по скорости для этого. Вы можете начать с просмотра: http://java.sun.com/javase/6/docs/technotes/guides/jpda/trace.html

Кроме того, опираясь на неотвеченный ответ ...

class Base
{
    // instance method helper
    public final int foo()
    {
        return (foo(this.getClass()));
    }

    // the real helper, with access to the class
    private static int foo(final Class clazz)
    {
        return (0);
    }
}

class Child
    extends Base
{
    public void bar()
    {
        final int x;

        x = foo();
    }
}
1 голос
/ 03 марта 2009

Создание Throwable очень дорого, поэтому не используйте его, если ваш метод вызывается часто (например, чаще, чем раз в секунду) Немного лучший подход - Thread.currentThread (). GetStackTrace ().

Другим подходом, если вы используете JVM от Sun, является Reflection.getCallerClass (n). Это намного быстрее, но не переносимо на другие JVM. Если вы обеспокоены этим, у вас может быть другой метод, который вызывает его, если он доступен, и использует трассировку стека, если нет.

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

1 голос
/ 02 марта 2009

В статическом методе, какова гарантия того, что некоторый (любой) класс, который был расширен от вашего, находится в стеке?

Если вы немного подумаете об этом, я подозреваю, вы поймете, что то, что вы ищете, не существует.

/ РЕДАКТ. 1 / Я думаю, что вам нужно это

abstract class B {
    <T extends B> B create(Class<T> clazz) {
    ....
}

Хм. Что если create - это protected метод? Тогда вы можете быть почти уверены, что вызывающий абонент B, вы можете даже потребовать этого, бросив UnsupportedOperation или IllegalState, если вызывающему не назначается B.

Вы можете использовать Thread.currentThread().getStackTrace()

0 голосов
/ 02 марта 2009

Я предлагаю избегать трясины отражения. Вы, кажется, делаете какое-то простое программирование. Используйте простую реализацию (недостаточно информации, чтобы сделать разумное предположение, что это может быть).

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