Как получить объект метода в Java без использования имен строк метода - PullRequest
13 голосов
/ 26 марта 2012

Я ищу удобный обходной путь для получения объекта Method из метода. Идея:

Method fooMethod = getMethod( new MyObject().foo() ) // returns method "foo" in MyObject

Очевидный способ - использовать имя метода в виде строки:

Method fooMethod = MyObject.class.getMethod("foo")

но я хочу избежать этого, потому что если я переименую foo (), этот код перестанет работать или я переименую строку во всех местах, где она используется.

Случай использования: я хочу использовать что-то похожее на ProperyChangeListeners , однако те полагаются на имя метода в виде строки. Я бы хотел использовать метод (безопасно) и не полагаться на строки.

Что я мог бы использовать, чтобы получить метод переименовывать безопасный способ?

UPDATE : Я хотел бы найти чистое решение Java, которое не использует функции IDE

Ответы [ 8 ]

11 голосов
/ 30 марта 2014

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

Обнаружил это после небольшого поиска:

http://benjiweber.co.uk/blog/2013/12/28/typesafe-database-interaction-with-java-8/

Удобный трюк - вызов метода для прокси-объекта, который записывает имя метода.Не пробовал, но выглядит многообещающе.

9 голосов
/ 26 марта 2012

В вашем вызове метода: Method me = (new MethodNameHelper () {}). GetMethod ();

/**
 * Proper use of this class is
 *     Method me = (new MethodNameHelper(){}).getMethod();
 * the anonymous class allows easy access to the method name of the enclosing scope.
 */
public class MethodNameHelper {
  public Method getMethod() {
    return this.getClass().getEnclosingMethod();
  }
}
8 голосов
/ 03 мая 2014

На самом деле есть библиотека, которая может сделать это:

Jodd MethRef - ссылки на имена методов со строгим типом

https://jodd.org/ref/methref.html

Methref<Str> m = Methref.on(Str.class);  // create Methref tool

// example #1
m.to().boo();
m.ref();                               // returns String: 'boo'
4 голосов
/ 15 ноября 2017

Мы опубликовали небольшую библиотеку de.cronn: refle-util , которую можно использовать для захвата метода.

Пример:

class MyClass {

    public void myMethod() {
    }

}

Method method = ClassUtils.getVoidMethod(MyClass.class, MyClass::myMethod);
System.out.println(method.getName()); // prints "myMethod"

Подробности реализации: подкласс Proxy MyClass создается с ByteBuddy , и вызывается вызов метода для получения его имени. ClassUtils кэширует информацию так, что нам не нужно создавать новый прокси при каждом вызове.

3 голосов
/ 26 марта 2012

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

Вы можете смело переименовывать метод, и ваш код будет работать.

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

1 голос
/ 26 марта 2012

Самое безопасное - это использовать IDE с возможностью рефакторинга, которая достаточно умна, чтобы распознавать и заменять это имя метода String.IntelliJ из JetBrains делает это - я только что доказал это себе.

0 голосов
/ 26 марта 2012

Используя отражение, вы отказываетесь от безопасности во время компиляции, просто по своей природе.

Вместо этого подумайте, действительно ли отражение здесь необходимо.Вы можете представить свой метод с помощью Runnable, например:

Runnable foo = new Runnable() {
    @Override
    public void run() {
        new MyObject().foo();
    }
}

...

foo.run();

Или, если вам нужно представить метод с типом возврата, посмотрите на Callable - или даже лучше, Guava's Function.

0 голосов
/ 26 марта 2012

Вы можете использовать IDE-рефакторинг, который также учитывает все строковые вхождения.

Вы не можете ссылаться на метод, используя отражение иначе, как по его имени.

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