如何在Java中不使用方法字符串名称就获得方法对象

时间:2023-02-09 23:40:08

I'm looking for a convenient workaround for getting the Method object from a method. The idea:

我正在寻找一种方便的方法来从一个方法获取方法对象。的想法:

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

The obvious way is to use the name of the method as a string:

显而易见的方法是将方法的名称用作字符串:

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

but I want to avoid this because if I rename foo() that code will stop working or I have rename the string in all the places where it is used.

但是我想避免这种情况,因为如果我重命名foo(),代码就会停止工作,或者我已经在使用字符串的所有地方重命名了字符串。

The use case is that I want to use something similar to ProperyChangeListeners however those rely on the method name as string. I'd like to use the actual method (safely) and not rely on strings.

用例是我想使用类似于properychangelistener的东西,但是它们依赖于方法名作为字符串。我希望使用实际的方法(安全地),而不依赖字符串。

What could I use to get the method in a rename safe way?

我可以使用什么来以安全的方式获得重命名方法?

UPDATE: I'd like to find a pure java solution that does not rely on IDE features

更新:我希望找到一个不依赖IDE特性的纯java解决方案

8 个解决方案

#1


9  

Java 8 method references would be ideal for this - the tricky part is getting to the underlying method, because the method reference syntax itself results in an opaque lambda object.

Java 8方法的引用是非常理想的——棘手的部分是找到底层方法,因为方法引用语法本身会导致不透明的lambda对象。

Found this after a bit of searching:

在搜索之后发现了这个:

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

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

Neat trick - call the method on a proxy object that records the method name. Haven't tried it but looks promising.

巧妙的技巧——在记录方法名的代理对象上调用方法。我还没试过,但看起来很有希望。

#2


7  

In your method call: Method me = (new MethodNameHelper(){}).getMethod();

在方法调用中: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();
  }
}

#3


6  

There is actually a library that can do this:

实际上有一个图书馆可以这样做:

Jodd MethRef - Strongly-typed method name references

强类型方法名称引用

http://jodd.org/doc/methref.html

http://jodd.org/doc/methref.html

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

// example #1
m.to().boo();
m.ref();                               // returns String: 'boo'

#4


4  

We have published the small library de.cronn:reflection-util that can be used to capture a method.

我们已经发布了小库de.cronn:reflection-util,可以用来捕获方法。

Example:

例子:

class MyClass {

    public void myMethod() {
    }

}

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

Implementation details: A Proxy subclass of MyClass is created with ByteBuddy and a call to the method is captured to retrieve its name. ClassUtils caches the information such that we do not need to create a new proxy on every invocation.

实现细节:使用ByteBuddy创建MyClass的代理子类,并捕获对方法的调用以检索其名称。ClassUtils缓存信息,这样我们就不需要在每次调用中创建新的代理。

#5


2  

The safest thing is to use an IDE with refactoring capability that's smart enough to recognize and replace that String method name. IntelliJ from JetBrains does it - I just proved it to myself.

最安全的方法是使用具有重构功能的IDE,它足够智能,能够识别并替换该字符串方法名称。来自JetBrains的IntelliJ做了它——我刚刚证明了它。

#6


2  

You might want to use annotations. You can create a custom annotation for each method that you want to retrieve and the using reflection pull that method from the object.

您可能需要使用注释。您可以为您想要检索的每个方法创建一个自定义注释,并使用反射从对象中提取该方法。

You can safely rename the method and your code will work.

您可以安全地重命名该方法,您的代码将会工作。

If you want to be able to retrieve many methods then use only one annotation with a string value which will change per method and then your reflection code will look for those annotations with that string value. You can still rename your method as long as you leave the string value of the annotation the same.

如果您想要检索许多方法,那么只需使用一个带有字符串值的注释,该值将对每个方法进行更改,然后您的反射代码将查找那些带有字符串值的注释。您仍然可以重命名您的方法,只要您将注释的字符串值保持不变。

#7


0  

You can use IDE refactoring which take care about all string occurences as well.

您可以使用IDE重构,它也会考虑所有出现的字符串。

You cannot reference a method using reflection otherwise than by its name.

不能使用反射引用方法,除非使用它的名称。

#8


0  

By using reflection you're giving up compile-time safety, just by its nature.

通过使用反射,你放弃了编译时的安全,就像它的本质一样。

Instead consider whether reflection is really necessary here. You could represent your method with a Runnable, for example:

相反,我们应该考虑反射在这里是否真的必要。你可以用可运行的来表示你的方法,例如:

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

...

foo.run();

Or if you need to represent a method with a return type, look at Callable - or even better, Guava's Function.

或者,如果您需要表示带有返回类型的方法,请查看Callable——或者更好的是,Guava的函数。

#1


9  

Java 8 method references would be ideal for this - the tricky part is getting to the underlying method, because the method reference syntax itself results in an opaque lambda object.

Java 8方法的引用是非常理想的——棘手的部分是找到底层方法,因为方法引用语法本身会导致不透明的lambda对象。

Found this after a bit of searching:

在搜索之后发现了这个:

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

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

Neat trick - call the method on a proxy object that records the method name. Haven't tried it but looks promising.

巧妙的技巧——在记录方法名的代理对象上调用方法。我还没试过,但看起来很有希望。

#2


7  

In your method call: Method me = (new MethodNameHelper(){}).getMethod();

在方法调用中: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();
  }
}

#3


6  

There is actually a library that can do this:

实际上有一个图书馆可以这样做:

Jodd MethRef - Strongly-typed method name references

强类型方法名称引用

http://jodd.org/doc/methref.html

http://jodd.org/doc/methref.html

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

// example #1
m.to().boo();
m.ref();                               // returns String: 'boo'

#4


4  

We have published the small library de.cronn:reflection-util that can be used to capture a method.

我们已经发布了小库de.cronn:reflection-util,可以用来捕获方法。

Example:

例子:

class MyClass {

    public void myMethod() {
    }

}

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

Implementation details: A Proxy subclass of MyClass is created with ByteBuddy and a call to the method is captured to retrieve its name. ClassUtils caches the information such that we do not need to create a new proxy on every invocation.

实现细节:使用ByteBuddy创建MyClass的代理子类,并捕获对方法的调用以检索其名称。ClassUtils缓存信息,这样我们就不需要在每次调用中创建新的代理。

#5


2  

The safest thing is to use an IDE with refactoring capability that's smart enough to recognize and replace that String method name. IntelliJ from JetBrains does it - I just proved it to myself.

最安全的方法是使用具有重构功能的IDE,它足够智能,能够识别并替换该字符串方法名称。来自JetBrains的IntelliJ做了它——我刚刚证明了它。

#6


2  

You might want to use annotations. You can create a custom annotation for each method that you want to retrieve and the using reflection pull that method from the object.

您可能需要使用注释。您可以为您想要检索的每个方法创建一个自定义注释,并使用反射从对象中提取该方法。

You can safely rename the method and your code will work.

您可以安全地重命名该方法,您的代码将会工作。

If you want to be able to retrieve many methods then use only one annotation with a string value which will change per method and then your reflection code will look for those annotations with that string value. You can still rename your method as long as you leave the string value of the annotation the same.

如果您想要检索许多方法,那么只需使用一个带有字符串值的注释,该值将对每个方法进行更改,然后您的反射代码将查找那些带有字符串值的注释。您仍然可以重命名您的方法,只要您将注释的字符串值保持不变。

#7


0  

You can use IDE refactoring which take care about all string occurences as well.

您可以使用IDE重构,它也会考虑所有出现的字符串。

You cannot reference a method using reflection otherwise than by its name.

不能使用反射引用方法,除非使用它的名称。

#8


0  

By using reflection you're giving up compile-time safety, just by its nature.

通过使用反射,你放弃了编译时的安全,就像它的本质一样。

Instead consider whether reflection is really necessary here. You could represent your method with a Runnable, for example:

相反,我们应该考虑反射在这里是否真的必要。你可以用可运行的来表示你的方法,例如:

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

...

foo.run();

Or if you need to represent a method with a return type, look at Callable - or even better, Guava's Function.

或者,如果您需要表示带有返回类型的方法,请查看Callable——或者更好的是,Guava的函数。