相关疑难解决方法(0)

如何在不使用方法字符串名称的情况下在Java中获取Method对象

我正在寻找一种从方法中获取Method对象的方便的解决方法.想法:

Method fooMethod = getMethod( new MyObject().foo() ) // returns method "foo" in MyObject
Run Code Online (Sandbox Code Playgroud)

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

Method fooMethod = MyObject.class.getMethod("foo")
Run Code Online (Sandbox Code Playgroud)

但我想避免这种情况,因为如果我重命名foo()代码将停止工作或我在所有使用它的地方重命名字符串.

用例是我想使用类似于ProperyChangeListeners的东西,但是那些依赖于方法名称作为字符串.我想使用实际的方法(安全)而不依赖于字符串.

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

更新:我想找到一个不依赖IDE功能的纯Java解决方案

java reflection

15
推荐指数
4
解决办法
2万
查看次数

使用java 8 lambda表达式打印有关错误的调试信息

我想使用静态方法作为setter helper来捕获异常并打印有关失败操作的调试信息.我不希望只有例外细节.我想显示正在设置的属性,以便详细帮助快速调试问题.我正在使用Java 8.

我应该如何提供或检测所设置的财产?

我希望删除示例中的"名称"字符串并获得相同的结果.

我知道我不能对提供的提供的setter方法使用反射,该方法转换为lambda表达式然后转换为BiConsumer.

我得到了这个,但需要提供属性名称.

/** setter helper method **/
private static <E, V> void set(E o, BiConsumer<E, V> setter,
        Supplier<V> valueSupplier, String propertyName) {
    try {
        setter.accept(o, valueSupplier.get());
    } catch (RuntimeException e) {
        throw new RuntimeException("Failed to set the value of " + propertyName, e);
    }
}
Run Code Online (Sandbox Code Playgroud)

例:

    Person p = new Person();
    Supplier<String> nameSupplier1 = () ->  "MyName";
    Supplier<String> nameSupplier2 = () -> { throw new RuntimeException(); };
    set(p, Person::setName, nameSupplier1, "name");
    System.out.println(p.getName()); // prints MyName …
Run Code Online (Sandbox Code Playgroud)

java reflection debugging lambda java-8

9
推荐指数
1
解决办法
2615
查看次数

如何通过反射获取方法引用?

假设我有一些像Function这样的函数接口和一些不同类的方法,我可以为它们提供方法引用,例如:

class A {
   public int getPrimitive() { return 0; }
   public Integer getBoxed() { return 0; }
   public static int getStaticPrimitive(A a) { return 1; }
}

Function<A, Integer> primitive = A::getPrimitive;
Function<A, Integer> boxed = A::getBoxed;
Function<A, Integer> staticPrimitive = A::getStaticPrimitive;
Run Code Online (Sandbox Code Playgroud)

我如何通过反射获取从A类转换为Function接口实例的所有可能的方法引用?

更新:

到目前为止,这个问题与评论中提到的任何问题都不重复,但多亏了Holger在评论中提到的两个问题,我已经设法做了我需要的事情:

    class Test {
    public static void main(String[] args) throws Throwable {
        HashMap<String, Function<A, Integer>> map = new HashMap<>();

        Collection<MethodType> supportedTypes = Arrays.asList(
                MethodType.methodType(int.class, A.class),
                MethodType.methodType(Integer.class, A.class)
        );

        MethodType inT = MethodType.methodType(Function.class);
        MethodHandles.Lookup …
Run Code Online (Sandbox Code Playgroud)

java reflection java-8 method-reference

6
推荐指数
0
解决办法
93
查看次数

如何找到Java8方法引用的目标?

我想捕获对模拟对象的调用

public interface Service {
    public String stringify(Object o);
}
service = mockery.mock(Service.class);
mockery.allowing(service::stringify).with(42).will(() -> "42");
Run Code Online (Sandbox Code Playgroud)

所以里面allowing我有一个Function<Object, String>

是否有任何reflecto-magic可以让我从方法参考创建的函数中找到服务?

public WithClause allowing(Function<T,R> f) {
    Object myServiceBackAgain = findTargetOf(function);
    ....
}
Run Code Online (Sandbox Code Playgroud)

我知道函数将始终来自这些方法引用,所以我很乐意尽可能地向下转换.

这与相关的问题不同是否可以将方法引用转换为MethodHandle?因为,一开始它不是同一个问题,只是在相关领域.即使我可以得到一个MethodHandle,我也无法从中获取目标.

java reflection java-8

6
推荐指数
1
解决办法
867
查看次数

如何获取lambda导致的方法名称

从简单的角度来看,lambda表达式被编译成static方法,因为它们不捕获this(即不访问实例成员).

public class App {
  public static void foo(){
      Consumer<Integer> c1 = n -> {};
      Consumer<Integer> c2 = n -> {};
  }

  public static void main(String [] args) {
    Supplier<String> sup1 = () -> "I am sup1";
    Supplier<String> sup2 = () -> "I am sup2";
    Supplier<String> sup3 = () -> "I am sup3";

    Stream.of(App.class.getDeclaredMethods()).forEach(System.out::println);
  }
}
Run Code Online (Sandbox Code Playgroud)

运行前面的例子,并检查与生成的字节码javap工具,我们可以看到,通过变量称为lambda表达式c1,c2,sup1,sup2,sup3被编译成与名称的方法:

  • lambda$foo$0
  • lambda$foo$1
  • lambda$main$2
  • lambda$main$3
  • lambda$main$4

然而,如果我们打印出getClass() …

lambda java-8

6
推荐指数
1
解决办法
2199
查看次数

是否有可能(如何)在 Java 运行时获取方法引用的名称?

我最近使用了很多方法引用和 lambda,并且想知道在运行时是否可以打印以屏幕 lambda 的源(即它的名称),只是出于调试原因。我认为可以使用反射,通过在 getName() 中调用 getClass() 来实现,但我找不到用于查找原始源引用名称的方法。

我有一个功能界面,例如:

@FunctionalInterface
public interface FooInterface {
    // function etc etc irrelevant
    public void method();

    public default String getName() {
        // returns the name of the method reference which this is used to define
    }
}
Run Code Online (Sandbox Code Playgroud)

然后假设我希望测试运行该界面,并将功能界面的源代码打印到屏幕上。

public static void doStuff(FooInterface f) {
    // prints the lambda name that is used to create f
    System.out.println(f.getName());

    // runs the method itself
    f.method();
}
Run Code Online (Sandbox Code Playgroud)

所以如果我这样做:

doStuff(Foo::aMethodReference);
Run Code Online (Sandbox Code Playgroud)

它应该在屏幕上打印类似:“aMethodReference”的内容,这样我就可以知道在运行时正在运行哪些方法,以什么顺序运行等。

考虑到 lambda 不完全是对象,我很怀疑这是可能的,但是嘿,我想可能有一个解决方法。此外,eclipse调试工具只是说它是一个lambda,没有任何其他信息,lambda是否保留任何这些信息?或者在运行时全部丢失?

干杯。(如果有什么区别的话,我正在使用 JDK 11)

java reflection lambda java-8 method-reference

3
推荐指数
1
解决办法
2194
查看次数

如何获取 Java 14 方法引用的 MethodInfo?

我本质上是在问与这个老问题相同的问题,但针对的是 Java 14 而不是 Java 8。为了避免回答者导航到老问题的麻烦,我将在这里重新表述。我想从引用的方法中获取函数的名称。下面的 Java 代码应该能让您明白:

public class Main
{
    public static void main(String[] args)
    {
       printMethodName(Main::main);
    }

    private static void printMethodName(Consumer<String[]> theFunc)
    {
        String funcName = // somehow get name from theFunc
        System.out.println(funcName)
    }
 }
Run Code Online (Sandbox Code Playgroud)

C# 中的等效内容是:

public class Main
{
    public static void Main()
    {
        var method = Main.Main;
        PrintMethodName(method)
    }

    private static void PrintMethodName(Action action)
    {
        Console.WriteLine(action.GetMethodInfo().Name);
    }
}
Run Code Online (Sandbox Code Playgroud)

根据老问题的公认答案,如果没有大量的工作,这在 Java 8 中是不可能的,例如这个解决方案。Java 14中有更优雅的解决方案吗?

java reflection lambda java-14

0
推荐指数
1
解决办法
182
查看次数