import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; class Main { void fooInt() throws Throwable { MethodHandle handle = MethodHandles.lookup().findVirtual(Test.class, "foo", MethodType.methodType(int.class, int.class)); Test instance = new Test(); int exactSignature1 = (int) handle.invokeWithArguments(instance, 1); int exactSignature2 = (int) handle.invoke(instance, 2); int exactSignature3 = (int) handle.invokeExact(instance, 3); Object object = 123; int objectArgument1 = (int) handle.invokeWithArguments(instance, object); int objectArgument2 = (int) handle.invoke(instance, object); int objectArgument3 = (int) handle.invokeExact(instance, object); Object objectResult = handle.invokeWithArguments(instance, 1); objectResult = handle.invoke(instance, 2); objectResult = handle.invokeExact(instance, 3); Object objectResult1 = handle.invokeExact(instance, 3); int argumentsArray1 = (int) handle.invokeWithArguments(new Object[]{instance, 1}); int argumentsArray2 = (int) handle.invoke(new Object[]{instance, 2}); int argumentsArray3 = (int) handle.invokeExact(new Object[]{instance, 3}); int boxedArgument1 = (int) handle.invokeWithArguments(instance, Integer.valueOf(1)); int boxedArgument2 = (int) handle.invoke(instance, Integer.valueOf(2)); int boxedArgument3 = (int) handle.invokeExact(instance, Integer.valueOf(3)); Integer boxedResult1 = (Integer) handle.invokeWithArguments(instance, 1); Integer boxedResult2 = (Integer) handle.invoke(instance, 2); Integer boxedResult3 = (Integer) handle.invokeExact(instance, 3); int incompatibleArgument1 = (int) handle.invokeWithArguments(instance, "a"); int incompatibleArgument2 = (int) handle.invoke(instance, "b"); int incompatibleArgument3 = (int) handle.invokeExact(instance, "c"); String incompatibleResult1 = (String) handle.invokeWithArguments(instance, 1); String incompatibleResult2 = (String) handle.invoke(instance, 2); String incompatibleResult3 = (String) handle.invokeExact(instance, 3); int nullReceiver1 = (int) handle.invokeWithArguments( null, 1); int nullReceiver2 = (int) handle.invoke(null, 2); int nullReceiver3 = (int) handle.invokeExact(null, 3); int nullArgument1 = (int) handle.invokeWithArguments(instance, null); int nullArgument2 = (int) handle.invoke(instance, null); int nullArgument3 = (int) handle.invokeExact(instance, null); int incompatibleReceiver1 = (int) handle.invokeWithArguments(42, 1); int incompatibleReceiver2 = (int) handle.invoke(42, 2); int incompatibleReceiver3 = (int) handle.invokeExact(42, 3); int tooFewArguments1 = (int) handle.invokeWithArguments(1); int tooFewArguments2 = (int) handle.invoke(2); int tooFewArguments3 = (int) handle.invokeExact(3); int tooManyArguments1 = (int) handle.invokeWithArguments(instance, 1, "a"); int tooManyArguments2 = (int) handle.invoke(instance, 2, "b"); int tooManyArguments3 = (int) handle.invokeExact(instance, 3, "c"); } void fooStr() throws Throwable { MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodHandle handle = lookup.findVirtual(Test.class, "foo", MethodType.methodType(String.class, String.class)); Test instance = new Test(); String exactSignature1 = (String) handle.invokeWithArguments(instance, "a"); String exactSignature2 = (String) handle.invoke(instance, "b"); String exactSignature3 = (String) handle.invokeExact(instance, "c"); Object object = "abc"; String objectArgument1 = (String) handle.invokeWithArguments(instance, object); String objectArgument2 = (String) handle.invoke(instance, object); String objectArgument3 = (String) handle.invokeExact(instance, object); Object objectResult = handle.invokeWithArguments(instance, "a"); objectResult = handle.invoke(instance, "b"); objectResult = handle.invokeExact(instance, "c"); Object objectResult1 = handle.invokeExact(instance, "c"); String argumentsArray1 = (String) handle.invokeWithArguments(new Object[]{instance, "a"}); String argumentsArray2 = (String) handle.invoke(new Object[]{instance, "b"}); String argumentsArray3 = (String) handle.invokeExact(new Object[]{instance, "c"}); String incompatibleArgument1 = (String) handle.invokeWithArguments(instance, 1); String incompatibleArgument2 = (String) handle.invoke(instance, 2); String incompatibleArgument3 = (String) handle.invokeExact(instance, 3); int incompatibleResult1 = (int) handle.invokeWithArguments(instance, "a"); int incompatibleResult2 = (int) handle.invoke(instance, "b"); int incompatibleResult3 = (int) handle.invokeExact(instance, "c"); String nullReceiver1 = (String) handle.invokeWithArguments(null, "a"); String nullReceiver2 = (String) handle.invoke(null, "b"); String nullReceiver3 = (String) handle.invokeExact(null, "c"); String nullArgument1 = (String) handle.invokeWithArguments(instance, null); String nullArgument2 = (String) handle.invoke(instance, null); String nullArgument3 = (String) handle.invokeExact(instance, null); String incompatibleReceiver1 = (String) handle.invokeWithArguments("x", "a"); String incompatibleReceiver2 = (String) handle.invoke("x", "b"); String incompatibleReceiver3 = (String) handle.invokeExact("x", "c"); String tooFewArguments1 = (String) handle.invokeWithArguments("a"); String tooFewArguments2 = (String) handle.invoke("b"); String tooFewArguments3 = (String) handle.invokeExact("c"); String tooManyArguments1 = (String) handle.invokeWithArguments(instance, "a", 1); String tooManyArguments2 = (String) handle.invoke(instance, "b", 2); String tooManyArguments3 = (String) handle.invokeExact(instance, "c", 3); String superclassArgument1 = (String) handle.invokeWithArguments(instance, charSequence()); String superclassArgument2 = (String) handle.invoke(instance, charSequence()); String superclassArgument3 = (String) handle.invokeExact(instance, charSequence()); CharSequence superclassResult1 = (CharSequence) handle.invokeWithArguments(instance, "a"); CharSequence superclassResult2 = (CharSequence) handle.invoke(instance, "b"); CharSequence superclassResult3 = (CharSequence) handle.invokeExact(instance, "c"); } void fooVariousTypesVariousMethodTypes() throws Throwable { MethodHandles.Lookup lookup = MethodHandles.lookup(); Test instance = new Test(); MethodType methodTypeFromArraysAsList = MethodType.methodType(long.class, Arrays.asList(int.class, long.class)); MethodHandle methodHandle0 = lookup.findVirtual(Test.class, "foo", methodTypeFromArraysAsList); methodHandle0.invoke(instance, 1, 2, 3); MethodType methodTypeFromListOf = MethodType.methodType(long.class, (List.of(int.class, long.class))); MethodHandle methodHandle1 = lookup.findVirtual(Test.class, "foo", methodTypeFromListOf); methodHandle1.invoke(instance, 1, 2, 3); MethodHandle methodHandle2 = lookup.findVirtual(Test.class, "foo", MethodType.methodType(long.class, MethodType.methodType(Object.class, int.class, long.class))); methodHandle2.invoke(instance, 1, 2, 3); MethodHandle methodHandle3 = lookup.findVirtual(Test.class, "foo", MethodType.methodType(long.class, new Class[]{int.class, long.class})); methodHandle3.invoke(instance, 1, 2, 3); MethodHandle methodHandle4 = lookup.findVirtual(Test.class, "foo", MethodType.methodType(long.class, new Class[]{int.class, long.class})); methodHandle4.invoke(instance, 1, 2, 3); MethodType nestedMethodType5 = MethodType.methodType(long.class, new Class[]{int.class, long.class}); MethodHandle methodHandle5 = lookup.findVirtual(Test.class, "foo", MethodType.methodType(long.class, nestedMethodType5)); methodHandle5.invoke(instance, 1, 2, 3); List> noWarningsForMutableLists = Arrays.asList(int.class, String.class); noWarningsForMutableLists.set(1, long.class); MethodHandle methodHandle6 = lookup.findVirtual(Test.class, "foo", MethodType.methodType(long.class, noWarningsForMutableLists)); methodHandle6.invoke(instance, 1, 2L); MethodType noStackOverflowError = MethodType.methodType(long.class, noStackOverflowError); MethodHandle methodHandle7 = lookup.findVirtual(Test.class, "foo", noStackOverflowError); methodHandle7.invoke(instance, 1, 2L); } private static CharSequence charSequence() { return "abc"; } } class Test { public int foo(int n) {return n;} public String foo(String s) {return s;} public long foo(int i, long l) { return l + i; } }