import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.Arrays;

interface MyFunctionalInterface {
    Object invokeMethodReference(Object... args) throws Throwable;
}

public class Test {
    public Object m(Object ... args) {
        System.out.println("m: " + Arrays.toString(args));
        return "m";
    }
    public static void main(String argv[]) throws Throwable {
        MethodHandles.Lookup lookup = MethodHandles.lookup();
        MethodType mt = MethodType.methodType(String.class, char.class, char.class);
        MethodHandle ms = lookup.findVirtual(String.class, "replace", mt);

        System.out.println("result: " + ms.invoke("some string to search", 's', 'o'));

        MyFunctionalInterface methodRefSimple = new Test()::m;

        methodRefSimple.invokeMethodReference("first", "second");
        MyFunctionalInterface methodRefSignPoly = ms::invoke;
        System.out.println(methodRefSignPoly.invokeMethodReference("some string to search", 's', 'o'));
    }
}