我们可以使用java.util.function获得方法名称吗?

Mar*_*lla 11 java methods functional-programming java-8 method-reference

我试着做:

public class HelloWorld {
     public static void main(String... args){
        final String string = "a";
        final Supplier<?> supplier = string::isEmpty;
        System.out.println(supplier);
     }
}
Run Code Online (Sandbox Code Playgroud)

我得到:

HelloWorld$$Lambda$1/471910020@548c4f57
Run Code Online (Sandbox Code Playgroud)

我想拿线isEmpty。我怎样才能做到这一点?

编辑:我创建的方法的代码是此之一:

public class EnumHelper {
    private final static String values = "values";
    private final static String errorTpl = "Can't find element with value `{0}` for enum {1} using getter {2}()";

    public static <T extends Enum<T>, U> T getFromValue(T enumT, U value, String getter) {
        @SuppressWarnings("unchecked")
        final T[] elements = (T[]) ReflectionHelper.callMethod(enumT, values);

        for (final T enm: elements) {
            if (ReflectionHelper.callMethod(enm, getter).equals(value)) {
                return enm;
            }
        }

        throw new InvalidParameterException(MessageFormat.format(errorTpl, value, enumT, getter));
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是我无法作为参数T :: getValue传递,因为getValue不是静态的。而且我无法传递someEnumElem :: getValue,因为get()将会返回该元素的值。我可以在for循环内使用:

Supplier<U> getterSupllier = enm:getValue;
if (getterSupllier.get().equals(value)) {
    [...]
}
Run Code Online (Sandbox Code Playgroud)

但是这种方式getValue是固定的,我无法将其作为参数传递。我可以使用某些第三方库来执行eval(),但是我真的不想打开那个Pandora花瓶:D

编辑2:Function确实没有参数方法,但只能在Java11 中使用。不幸的是,我坚持使用Java8。

And*_*lko 8

string::isEmpty将通过LambdaMetafactory.metafactory其中具有implMethod参数的方法来构造。

final String methodName = implMethod.internalMemberName().getName();
Run Code Online (Sandbox Code Playgroud)

"isEmpty"如果我们可以访问传递给此工厂方法的参数implMethod,尤其是参数,则将返回方法名称(此处为)。由JVM向上调用生成的参数,该参数为java.lang.invokeAPI 提供了非常具体的信息。

例如,为了初始化一个DirectMethodHandlestring::isEmpty代表,JVM将调用以下方法。

/**
 * The JVM is resolving a CONSTANT_MethodHandle CP entry.  And it wants our help.
 * It will make an up-call to this method.  (Do not change the name or signature.)
 * The type argument is a Class for field requests and a MethodType for non-fields.
 * <p>
 * Recent versions of the JVM may also pass a resolved MemberName for the type.
 * In that case, the name is ignored and may be null.
 */
static MethodHandle linkMethodHandleConstant(Class<?> callerClass, int refKind,
                                             Class<?> defc, String name, Object type) 
Run Code Online (Sandbox Code Playgroud)

那个name(恰好是您所请求的)将由JVM放置在那里,并且我们无法访问它。目前。

阅读:


Joa*_*uer 7

简而言之:不。

一旦使用了方法引用,您将拥有所请求的功能接口的实现(Supplier<?>在这种情况下),但是该对象的所有具体细节基本上都是未定义的(或者确切地说是实现定义的)。

规范没有说明它是一个单独的对象,它toString()必须是什么,或者您可以用它做什么。这是一个Supplier<?>,基本上没有别的。

同样的情况适用于lambda表达式。

因此,如果您曾经使用过

final Supplier<?> supplier = () -> string.isEmpty();
Run Code Online (Sandbox Code Playgroud)

Supplier会做同样的事情,你也无法获得回拉姆达的“代码”。