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;
}
}