2010-04-15 2 views
1

Рассмотрим следующий Java класс:Можно ли получить доступ к объекту Class в статическом методе?

public class Foo 
{ 
    public static void doStuff() 
    { 
     // boring stuff here 
    } 
} 

Есть ли возможность доступа к одному классу буквальным Foo.class, или только имя класса "Foo" внутри статического метода, такого как doStuff()? В нестационарном методе я бы просто вызвал this.getClass(), но нет this для использования в статическом методе.


Edit: жаль, что это не было ясно - я хочу сделать это с явным использованием класса буквального Foo.class.

+0

Чтобы ответить на ваш вопрос, да, вы можете использовать 'Foo.class' в статическом методе, но не' this.getClass() '. Это единственная причина, по которой это будет проблемой, - это причудливое наследование статического метода Java (серьезно, статические методы не должны попадать в дочерние классы ... C# явно запрещает это). – Powerlord

+0

Статические методы не являются виртуальными в Java. Это одна из причин использования шаблона фабрики. –

+0

@ Ха - Я не следую. –

ответ

1

К сожалению, Java не дает вам хороший способ сделать это. Вам просто нужно обратиться к Foo.class. Это то, что вызывает у меня постоянное раздражение.

Для регистрации я решил это (идея решения пришла из Log5j), прочитав стек, потому что было очень раздражать, чтобы каждый раз повторять класс для каждого регистратора. К счастью, современные IDE делают его относительно безболезненным, так что рефакторинг на самом деле не оказывает негативного влияния, если вам нужно изменить имя класса.

EDIT: Некоторый код:

private static StackTraceElement getCallerStackTraceElement(StackTraceElement[] elements) { 
    for (int i = 0; i < elements.length; i++) { 
     if (elements[i].getClassName().equals(MyLogger.class.getName())) { 
      return elements[i + 1]; 
     } 
    } 
    return null; 
} 

MyLogger в этом случае является классом, где этот метод существует. Он находится в стеке и идет один раньше, а затем извлекает класс из StackTraceElement.

Массив StackTraceElement [] может быть получен либо с помощью нового Exception(). GetStackTrace(), либо Thread.currentThread(). GetStackTrace(); Способ, которым этот метод написан, предполагает, что stacktrace создается при первом вызове метода в MyLogger.

+0

Можете ли вы уточнить, что именно вы сделали? Возможно, добавьте немного кода? – einpoklum

2

Использование Class<Foo> clazz = Foo.class


Если вам нужно что-то вроде:

class Foo { 
    static Class foo(){return the current class} 
} 

class Bar extends Foo { 

} 

и ожидать Bar.foo() вернуться Bar при вызове на Bar и Foo при вызове на Foo - у вас есть что-то неправильно в вашем дизайн и, возможно, вам нужно сделать методы нестатическими.

0

Просто используйте Foo.class. Вам не нужно беспокоиться о наследовании или что-то в этом роде, поскольку объект не связан со статическим методом.

+0

Весь смысл моего вопроса состоял в том, чтобы сделать это ** без ** ссылки на «Foo.class». –

0

При работе со статическими методами вы можете рассматривать их как библиотеки, где имя класса становится именем библиотеки. Вы сообщаете компилятору, какой метод bar() запускаться, указав имя библиотеки (класса). Foo.bar() - Bar.bar().

Сам метод не имеет родителя и никакого экземпляра, поэтому он не может использовать отражение, чтобы знать, к какому классу он принадлежит. Однако вы можете добавить метод отражения.

Вы можете добавить статический метод класса, который отвечает сам, какой класс он находится в:

public class Foo { 

    private static class self() { 
     return Foo.class; 
    } 

    public static void doStuff() 
    { 
     // Use self() to reference the Foo class 
    } 
} 

Обратите внимание, что я сделал метод самостоятельно() частный, потому что за пределами класса, это не имеет никакого смысла.

Это работает, потому что метод self() отображается внутри класса и внутри статического метода.

Напротив, PHP имеет конструкцию self для ссылки на текущий класс.