Как я могу узнать через отражение то, что является строковым именем метода?
Например:
class Car{
public void getFoo(){
}
}
Я хочу получить строку "getFoo", что-то вроде следующего:
Car.getFoo.toString() == "getFoo" // TRUE
Как я могу узнать через отражение то, что является строковым именем метода?
Например:
class Car{
public void getFoo(){
}
}
Я хочу получить строку "getFoo", что-то вроде следующего:
Car.getFoo.toString() == "getFoo" // TRUE
Поскольку методы не являются самими объектами, у них нет прямых свойств (например, вы ожидали бы с первоклассными функциями в таких языках, как JavaScript).
Ближе всего вы можете позвонить: Car.class.getMethods()
Car.class
является объектом Class
, который вы можете использовать для вызова любого из методов отражения.
Однако, насколько мне известно, метод не может идентифицировать себя.
Вы можете получить строку следующим образом:
Car.class.getDeclaredMethods()[0].getName();
Это относится к случаю одного метода в вашем классе. Если вы хотите выполнить итерацию по всем объявленным методам, вам придется перебирать массив, возвращенный Car.class.getDeclaredMethods()
:
for (Method method : Car.class.getDeclaredMethods()) {
String name = method.getName();
}
Вы должны использовать getDeclaredMethods()
, если вы хотите просмотреть все из них, getMethods()
будет возвращать только общедоступные методы.
И, наконец, если вы хотите увидеть имя метода, который выполняется на данный момент, вы должны использовать этот код:
Thread.currentThread().getStackTrace()[1].getMethodName();
Это приведет к трассировке стека для текущего потока и вернет имя метода вверху.
Итак, вы хотите получить имя текущего исполняемого метода? Вот несколько уродливый способ сделать это:
Exception e = new Exception();
e.fillInStackTrace();
String methodName = e.getStackTrace()[0].getMethodName();
попробуйте это,
import java.lang.reflect.*;
public class DumpMethods {
public static void main(String args[]) {
try {
Class c = Class.forName(args[0]);
Method m[] = c.getDeclaredMethods();
for (int i = 0; i < m.length; i++)
System.out.println(m[i].toString());
} catch (Throwable e) {
System.err.println(e);
}
}
}
Посмотрите в этой теме:
Получение имени текущего выполняемого метода
Он предлагает еще несколько решений - например:
String name = new Object(){}.getClass().getEnclosingMethod().getName();
С Java 8 вы можете сделать это с помощью нескольких строк кода (почти) без каких-либо дополнительных библиотек. Ключ должен преобразовать ваш метод в сериализуемое лямбда-выражение. Следовательно, вы можете просто определить простой интерфейс следующим образом:
@FunctionalInterface
public interface SerializableFunction<I, O> extends Function<I, O>, Serializable {
// Combined interface for Function and Serializable
}
Теперь нам нужно преобразовать наше лямбда-выражение в объект SerializedLambda
. Судя по всему, Oracle на самом деле не хочет, чтобы мы это делали, так что возьмите это с крошкой соли... Поскольку требуемый метод является закрытым, мы должны вызвать его, используя отражения:
private static final <T> String nameOf(SerializableFunction<T, ?> lambda) {
Method findMethod = ReflectionUtils.findMethod(lambda.getClass(), "writeReplace");
findMethod.setAccessible(true);
SerializedLambda invokeMethod = (SerializedLambda) ReflectionUtils.invokeMethod(findMethod, lambda);
return invokeMethod.getImplMethodName();
}
Я использую класс Springs ReflectionUtils
здесь для простоты, но вы, конечно, можете заменить его, вручную зацикливая все суперклассы и используя getDeclaredMethod
чтобы найти метод writeReplace
.
И это уже, теперь вы можете использовать это так:
@Test
public void testNameOf() throws Throwable {
assertEquals("getName", nameOf(MyClassTest::getName));
}
Я не проверял это с модульной системой Java 9s, так что в качестве небольшой оговорки было бы сложнее сделать это с более свежими версиями Java...
Подождите, так как вы уже знаете имя метода, не можете ли вы просто ввести его как строку?
Вместо (pseudo) Class.methodName.toString()
просто используйте "methodName
".
В противном случае вы можете использовать Class#getDeclaredMethods()
для получения всех методов в классе
SomeClass ex = new SomeClass();
Method methods[] = ex.getClass().getMethods();
for(Method i : methods)
System.out.println("method"+i.getName());