当前位置: 首页 > 知识库问答 >
问题:

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

子车鸿运
2023-03-14

请查看以下代码:

Method methodInfo = MyClass.class.getMethod("myMethod");

这是可行的,但方法名是作为字符串传递的,因此即使myMethod不存在,也会编译。

另一方面,Java8引入了一个方法引用特性。它在编译时被检查。可以使用这个特性来获取方法信息吗?

printMethodName(MyClass::myMethod);

完整示例:

@FunctionalInterface
private interface Action {

    void invoke();
}

private static class MyClass {

    public static void myMethod() {
    }
}

private static void printMethodName(Action action) {
}

public static void main(String[] args) throws NoSuchMethodException {
    // This works, but method name is passed as a string, so this will compile
    // even if myMethod does not exist
    Method methodInfo = MyClass.class.getMethod("myMethod");

    // Here we pass reference to a method. It is somehow possible to
    // obtain java.lang.reflect.Method for myMethod inside printMethodName?
    printMethodName(MyClass::myMethod);
}

换句话说,我希望有一个与以下C#代码等效的代码:

    private static class InnerClass
    {
        public static void MyMethod()
        {
            Console.WriteLine("Hello");
        }
    }

    static void PrintMethodName(Action action)
    {
        // Can I get java.lang.reflect.Method in the same way?
        MethodInfo methodInfo = action.GetMethodInfo();
    }

    static void Main()
    {
        PrintMethodName(InnerClass.MyMethod);
    }

共有3个答案

能逸清
2023-03-14

虽然我自己没有尝试过,但我认为答案是“不”,因为方法引用在语义上与lambda相同。

洪承天
2023-03-14

在我的例子中,我正在寻找一种方法来在单元测试中摆脱它:

Point p = getAPoint();
assertEquals(p.getX(), 4, "x");
assertEquals(p.getY(), 6, "x");

正如您所看到的,有人正在测试方法getAPoint,并检查坐标是否符合预期,但在每个断言的描述中都复制了,并且与检查的内容不同步。最好只写一次。

根据@ddan的想法,我使用Mockito构建了一个代理解决方案:

private<T> void assertPropertyEqual(final T object, final Function<T, ?> getter, final Object expected) {
    final String methodName = getMethodName(object.getClass(), getter);
    assertEquals(getter.apply(object), expected, methodName);
}

@SuppressWarnings("unchecked")
private<T> String getMethodName(final Class<?> clazz, final Function<T, ?> getter) {
    final Method[] method = new Method[1];
    getter.apply((T)Mockito.mock(clazz, Mockito.withSettings().invocationListeners(methodInvocationReport -> {
        method[0] = ((InvocationOnMock) methodInvocationReport.getInvocation()).getMethod();
    })));
    return method[0].getName();
}

不,我可以简单地使用

assertPropertyEqual(p, Point::getX, 4);
assertPropertyEqual(p, Point::getY, 6);

并且断言的描述保证与代码同步

下降趋势:

  • 会比上面稍微慢一点
  • 需要Mockito工作
  • 除了上面的用法,几乎没有什么用处。

然而,它确实展示了一种如何做到这一点的方法。

督建柏
2023-03-14

不,没有可靠的、受支持的方法来做到这一点。您将方法引用分配给函数式接口的实例,但该实例是由LambdaMetaFactory编写的,并且无法深入其中以找到您最初绑定的方法。

Java中的lambda和方法引用的工作方式与C#中的委托截然不同。有关一些有趣的背景知识,请阅读invokedynamic。

这里的其他答案和注释表明,目前可以通过一些额外的工作来检索绑定方法,但请确保您理解这些注意事项。

 类似资料:
  • 主要内容:1 Java8 方法引用的介绍,2 Java8 方法引用的分类,3 Java8 方法引用:引用静态方法,4 Java8 方法引用:引用实例方法,5 Java8 方法引用:引用构造方法1 Java8 方法引用的介绍 Java提供了一个新功能,称为Java 8中的方法引用。方法引用用于引用功能接口的方法。它是lambda表达式的紧凑和简单形式。每次使用lambda表达式仅引用方法时,都可以将lambda表达式替换为方法引用。在本教程中,我们将详细解释方法参考概念。 2 Java8 方法引用

  • 我有一个Employee类,如下所示 我正在尝试使用MethodReference获得如下所示的工资 知道如何只使用MethodReference获得工资吗 现在在toString看到一个问题

  • 本文向大家介绍使用Java8中的方法引用来引用实例方法,包括了使用Java8中的方法引用来引用实例方法的使用技巧和注意事项,需要的朋友参考一下 Java中的Lambda表达式使您可以将功能作为参数传递给方法。您也可以使用lambda表达式调用现有方法。 方法引用是简单,易于阅读的lambda表达式,可通过lambda表达式中的名称来调用/引用和现有方法。 语法 以下是在Java中引用实例方法的语法

  • 我对方法引用在Java8中是如何工作的有些困惑。我编写了下面的代码段用于过滤文件夹中的隐藏文件。他们正在产生正确的结果。我不理解->listFiles方法的方法签名是如何在这个代码段的选项2中工作的。 这是我在Java8文档中发现的

  • 我正在通过一个例子,它从与方法引用相关的当前目录中提取一个隐藏文件数组,如下所述 使用匿名内部类实现 使用方法参考实现 我的问题是接口只有一个抽象方法(),而实现accept-method-using-method-reference在类中使用的有效性如何。我了解到,只有当参数与抽象方法匹配时,我们才能应用方法引用,但是这里method有一个类型的参数,但是没有参数。你能解释一下它的有效性吗。

  • Obj.TestPredicate(list,String::Contains); 我在“String::Contains”中得到错误:不能从静态上下文引用非静态方法。但contains不是静态方法。我被那些小费弄糊涂了。 我的代码如下: (2)如果func是一个实例方法,那么someClass::func是一个lambda,它使用第一个参数作为实例,正如您所想的:(a,b,c)->a.func(