2

For example:

@FunctionalInterface
public interface MyRPC {
    Object execute(Object input);
}

public class MyImpl{
    public Object rpc1(Object input) {
        System.out.Println(input)
        return 100;
    }

    public static Object invokeRpc(MyRPC rpc, Object input) {
        // TODO: How can I get the name of the method passed in, like "rpc1" or "MyImpl::rpc1" here?
        return rpc.execute(input);
    }

    public static void main(String[] args) {
        final MyWfImpl myc = new MyWfImpl();
        invokeRpc(myc::rpc1, 1)
    }
}


In invokeRpc, How can I get the rpc name like "rpc1" or "MyImpl::rpc1"?

Long Quanzheng
  • 2,076
  • 1
  • 10
  • 22
  • 4
    It's impossible to get that. – rzwitserloot Apr 13 '23 at 04:02
  • you can set a breakpoint (or print stacktrace) to see the call hierarchy.... – Martin Frank Apr 13 '23 at 05:15
  • Does this answer your question? [Printing debug info on errors with java 8 lambda expressions](https://stackoverflow.com/questions/21860875/printing-debug-info-on-errors-with-java-8-lambda-expressions) – samabcde Apr 13 '23 at 15:41
  • Thanks. I think that question is related yeah. But not quite exactly. I think even my problem is more on Java reflection and looks like there is no solution due to the limitation of Java lambda. But this may change in the future (hopefully) – Long Quanzheng Apr 13 '23 at 16:43

2 Answers2

2

You cannot do that. Lambdas do not carry that information in a way that you can access.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
2

This is doable, but only via a hack, so there's no guarantee it will work on each VM.

With that out of the way, here's how to do it:

1. Make your functional interface extend Serializable:

@FunctionalInterface
public interface MyRPC extends Serializable {
    Object execute(Object input);
}

Its instances will now have an internal method called writeReplace that can be used to extract a SerializedLambda that will contain metadata.

2. Extract the class/method info from SerializedLambda (you can add the code to some utility class, or the functional interface itself):

@FunctionalInterface
public interface MyRPC extends Serializable {
    Object execute(Object input);
    
    default SerializedLambda serialized() {
        try {
            Method replaceMethod = getClass().getDeclaredMethod("writeReplace");
            replaceMethod.setAccessible(true);
            return (SerializedLambda) replaceMethod.invoke(this);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    default String getImplClassName() {
        return serialized().getImplClass().replaceAll("/", ".");
    }

    default String getImplMethodName() {
        return serialized().getImplMethodName();
    }
}

3. Enjoy the fruits of your hackery:

public static Object invokeRpc(MyRPC rpc, Object input) {
    System.out.println(rpc.getImplMethodName()); //
    return rpc.execute(input);
}
kaqqao
  • 12,984
  • 10
  • 64
  • 118