Однако во время компиляции будет создан новый анонимный внутренний класс (например, YourClass$1.class). Таким образом, будет создан .class файл для каждого метода, который использует этот трюк. Кроме того, при каждом вызове во время выполнения создается неиспользуемый экземпляр объекта. Так что это может быть приемлемым приемом отладки, но он сопряжен со значительными накладными расходами.
Преимущество этого трюка заключается в том, что getEnclosingMethod() возвращает данныеjava.lang.reflect.Method, которые могут быть использованы для извлечения всей другой информации о методе, включая аннотации и имена параметров. Это позволяет различать конкретные методы с одинаковым именем (перегрузка метода).
Обратите внимание, что согласно JavaDoc из getEnclosingMethod() этот трюк не должен вызывать a SecurityException поскольку внутренние классы должны загружаться с использованием того же загрузчика классов. Таким образом, нет необходимости проверять условия доступа, даже если присутствует менеджер безопасности.
Пожалуйста, имейте в виду: это требуется использовать getEnclosingConstructor() для конструкторов. Во время блоков вне (именованных) методов, getEnclosingMethod() возвращаетсяnull.
Некоторые виртуальные машины при определенных обстоятельствах могут пропускать один или несколько кадров стека из трассировки стека. В крайнем случае виртуальной машине, у которой нет информации о трассировке стека, касающейся этого потока, разрешается возвращать массив нулевой длины из этого метода.
/** * Get the method name for a depth in call stack. <br /> * Utility function * @param depth depth in the call stack (0 means current method, 1 means call method, ...) * @return method name */ publicstatic String getMethodName(finalint depth) { final StackTraceElement[] ste = Thread.currentThread().getStackTrace();
//System. out.println(ste[ste.length-depth].getClassName()+"#"+ste[ste.length-depth].getMethodName()); // return ste[ste.length - depth].getMethodName(); //Wrong, fails for depth = 0 return ste[ste.length - 1 - depth].getMethodName(); //Thank you Tom Tresansky }
static { // Finds out the index of "this code" in the returned stack trace - funny but it differs in JDK 1.5 and 1.6 inti=0; for (StackTraceElement ste : Thread.currentThread().getStackTrace()) { i++; if (ste.getClassName().equals(MethodNameTest.class.getName())) { break; } } CLIENT_CODE_STACK_INDEX = i; }
Кажется излишне разработанным, но у нас был некоторый фиксированный номер для JDK 1.5, и мы были немного удивлены, что он изменился, когда мы перешли на JDK 1.6. Теперь то же самое в Java 6/7, но вы просто никогда не знаете наверняка. Это не является доказательством изменений в этом индексе во время выполнения - но, надеюсь, HotSpot работает не так уж плохо. :-)