// The transformer will accept two additional arguments at position zero. try {
transform.invokeExact("foo", 42l);
fail();
} catch (WrongMethodTypeException expected) {
}
transform.invokeExact(45, new Object(), "foo", 42l);
transform.invoke(45, new Object(), "foo", 42l);
// Additional arguments at position 1.
transform = MethodHandles.dropArguments(delegate, 1, int.class, Object.class);
transform.invokeExact("foo", 45, new Object(), 42l);
transform.invoke("foo", 45, new Object(), 42l);
// Additional arguments at position 2.
transform = MethodHandles.dropArguments(delegate, 2, int.class, Object.class);
transform.invokeExact("foo", 42l, 45, new Object());
transform.invoke("foo", 42l, 45, new Object());
// Note that we still perform argument conversions even for the arguments that // are subsequently dropped. try {
transform.invoke("foo", 42l, 45l, new Object());
fail();
} catch (WrongMethodTypeException expected) {
} catch (IllegalArgumentException expected) { // TODO(narayan): We currently throw the wrong type of exception here, // it's IAE and should be WMTE instead.
}
// Check that asType works as expected.
transform = MethodHandles.dropArguments(delegate, 0, int.class, Object.class);
transform = transform.asType(MethodType.methodType(void.class, newClass<?>[] { short.class, Object.class, String.class, long.class }));
transform.invokeExact((short) 45, new Object(), "foo", 42l);
// Invalid argument location, should not be allowed. try {
MethodHandles.dropArguments(delegate, -1, int.class, Object.class);
fail();
} catch (IllegalArgumentException expected) {
}
// Invalid argument location, should not be allowed. try {
MethodHandles.dropArguments(delegate, 3, int.class, Object.class);
fail();
} catch (IllegalArgumentException expected) {
}
// These two should end up calling the target always. We're passing a null exception // message here, which means the target will not throw.
returnVal = (String) adapter.invoke("foo", 42, null);
assertEquals("target", returnVal);
returnVal = (String) adapter.invokeExact("foo", 42l, (String) null);
assertEquals("target", returnVal);
// We're passing a non-null exception message here, which means the target will throw, // which in turn means that the handler must be called for the next two invokes.
returnVal = (String) adapter.invoke("foo", 42, "exceptionMessage");
assertEquals("handler1", returnVal);
returnVal = (String) adapter.invokeExact("foo", 42l, "exceptionMessage");
assertEquals("handler1", returnVal);
// Test that the type of the invoke doesn't matter. Here we call // IllegalArgumentException.toString() on the exception that was thrown by // the target.
handler = MethodHandles.lookup().findVirtual(IllegalArgumentException.class, "toString", MethodType.methodType(String.class));
adapter = MethodHandles.catchException(target, IllegalArgumentException.class, handler);
publicstaticvoid testConstant() throws Throwable { // int constants.
{
MethodHandle constant = MethodHandles.constant(int.class, 56); int value = (int) constant.invoke(); if (value != 56) {
fail("Unexpected value: " + value);
}
// short constant values are converted to int.
constant = MethodHandles.constant(int.class, (short) 52);
value = (int) constant.invoke(); if (value != 52) {
fail("Unexpected value: " + value);
}
// char constant values are converted to int.
constant = MethodHandles.constant(int.class, (char) 'b');
value = (int) constant.invoke(); if (value != (int) 'b') {
fail("Unexpected value: " + value);
}
// int constant values are converted to int.
constant = MethodHandles.constant(int.class, (byte) 0x1);
value = (int) constant.invoke(); if (value != 1) {
fail("Unexpected value: " + value);
}
// boolean, float, double and long primitive constants are not convertible // to int, so the handle creation must fail with a CCE. try {
MethodHandles.constant(int.class, false);
fail();
} catch (ClassCastException expected) {
}
publicstaticvoid testFilterReturnValue() throws Throwable { // A target that returns a reference.
{ final MethodHandle target = MethodHandles.lookup().findStatic(Main.class, "filterReturnValue_target", MethodType.methodType(String.class, int.class)); final MethodHandle filter = MethodHandles.lookup().findStatic(Main.class, "filterReturnValue_filter", MethodType.methodType(boolean.class, String.class));
boolean value = (boolean) adapter.invoke((int) 42); if (!value) {
fail("Unexpected value: " + value);
}
value = (boolean) adapter.invoke((int) 43); if (value) {
fail("Unexpected value: " + value);
}
}
// A target that returns a primitive.
{ final MethodHandle target = MethodHandles.lookup().findStatic(Main.class, "filterReturnValue_intTarget", MethodType.methodType(int.class, String.class)); final MethodHandle filter = MethodHandles.lookup().findStatic(Main.class, "filterReturnValue_intFilter", MethodType.methodType(int.class, int.class));
int value = (int) adapter.invoke(); if (value != 42) {
fail("Unexpected value: " + value);
}
}
}
publicstaticvoid permuteArguments_callee(boolean a, byte b, char c, short d, int e, long f, float g, double h) { if (a == true && b == (byte) 'b' && c == 'c' && d == (short) 56 &&
e == 78 && f == (long) 97 && g == 98.0f && f == 97.0) { return;
}
fail("Unexpected arguments: " + a + ", " + b + ", " + c
+ ", " + d + ", " + e + ", " + f + ", " + g + ", " + h);
}
publicstaticvoid permuteArguments_boxingCallee(boolean a, Integer b) { if (a && b.intValue() == 42) { return;
}
// The permutation array was not of the right length. try {
MethodHandles.permuteArguments(target, newType, newint[] { 7 });
fail();
} catch (IllegalArgumentException expected) {
}
// The permutation array has an element that's out of bounds // (there's no argument with idx == 8). try {
MethodHandles.permuteArguments(target, newType, newint[] { 8, 6, 5, 4, 3, 2, 1, 0 });
fail();
} catch (IllegalArgumentException expected) {
}
// Tests for reference arguments as well as permutations that // repeat arguments.
{ final MethodHandle target = MethodHandles.lookup().findVirtual(
String.class, "concat", MethodType.methodType(String.class, String.class));
final MethodType newType = MethodType.methodType(String.class, String.class,
String.class);
// Exception case, calling with an arg of the wrong size. // Array size = 3
mhAsSpreader = delegate.asSpreader(String[].class, 3); try {
ret = (int) mhAsSpreader.invoke(new String[] { "a", "b"});
} catch (IllegalArgumentException expected) {
}
// Various other hijinks, pass as Object[] arrays, Object etc.
mhAsSpreader = delegate.asSpreader(Object[].class, 2);
ret = (int) mhAsSpreader.invoke("a", new String[] { "b", "c" });
assertEquals(42, ret);
mhAsSpreader = delegate.asSpreader(Object[].class, 2);
ret = (int) mhAsSpreader.invoke("a", new Object[] { "b", "c" });
assertEquals(42, ret);
mhAsSpreader = delegate.asSpreader(Object[].class, 2);
ret = (int) mhAsSpreader.invoke("a", (Object) new Object[] { "b", "c" });
assertEquals(42, ret);
// .. with an Integer[] array.
mhAsSpreader = delegate2.asSpreader(Integer[].class, 1);
ret = (int) mhAsSpreader.invoke("a", new Integer[] { 43 });
assertEquals(43, ret);
// .. with an Integer[] array declared as an Object[] argument type.
mhAsSpreader = delegate2.asSpreader(Object[].class, 1);
ret = (int) mhAsSpreader.invoke("a", new Integer[] { 43 });
assertEquals(43, ret);
// .. with an Object[] array.
mhAsSpreader = delegate2.asSpreader(Object[].class, 1);
ret = (int) mhAsSpreader.invoke("a", new Object[] { Integer.valueOf(43)});
assertEquals(43, ret);
// -- Part 2-- // Run a subset of these tests on MethodHandles.spreadInvoker, which only accepts // a trailing argument type of Object[].
MethodHandle spreadInvoker = MethodHandles.spreadInvoker(methodType2, 1);
ret = (int) spreadInvoker.invoke(delegate2, "a", new Object[] { Integer.valueOf(43)});
assertEquals(43, ret);
ret = (int) spreadInvoker.invoke(delegate2, "a", new Integer[] { 43 });
assertEquals(43, ret);
// NOTE: Annoyingly, the second argument here is leadingArgCount and not // arrayLength.
spreadInvoker = MethodHandles.spreadInvoker(methodType, 3);
ret = (int) spreadInvoker.invoke(delegate, "a", "b", "c", new String[] {});
assertEquals(42, ret);
spreadInvoker = MethodHandles.spreadInvoker(methodType, 0);
ret = (int) spreadInvoker.invoke(delegate, new String[] { "a", "b", "c" });
assertEquals(42, ret);
// Exact invokes: Double check that the expected parameter type is // Object[] and not T[]. try {
spreadInvoker.invokeExact(delegate, new String[] { "a", "b", "c" });
fail();
} catch (WrongMethodTypeException expected) {
}
ret = (int) spreadInvoker.invoke(delegate, new Object[] { "a", "b", "c" });
assertEquals(42, ret);
}
publicstaticint spreadBoolean(String a, Boolean b, boolean c) {
System.out.println("a: " + a + ", b:" + b + ", c: " + c); return44;
}
publicstaticint spreadByte(String a, Byte b, byte c, short d, int e, long f, float g, double h) {
System.out.println("a: " + a + ", b:" + b + ", c: " + c + ", d: " + d + ", e: " + e + ", f:" + f + ", g: " + g + ", h: " + h); return45;
}
publicstaticint spreadChar(String a, Character b, char c, int d, long e, float f, double g) {
System.out.println("a: " + a + ", b:" + b + ", c: " + c + ", d: " + d + ", e: " + e + ", f:" + f + ", g: " + g); return46;
}
publicstaticint spreadShort(String a, Short b, short c, int d, long e, float f, double g) {
System.out.println("a: " + a + ", b:" + b + ", c: " + c + ", d: " + d + ", e: " + e + ", f:" + f + ", g:" + g); return47;
}
publicstaticint spreadInt(String a, Integer b, int c, long d, float e, double f) {
System.out.println("a: " + a + ", b:" + b + ", c: " + c + ", d: " + d + ", e: " + e + ", f:" + f); return48;
}
publicstaticint spreadLong(String a, Long b, long c, float d, double e) {
System.out.println("a: " + a + ", b:" + b + ", c: " + c + ", d: " + d + ", e: " + e); return49;
}
publicstaticint spreadFloat(String a, Float b, float c, double d) {
System.out.println("a: " + a + ", b:" + b + ", c: " + c + ", d: " + d); return50;
}
publicstaticint spreadDouble(String a, Double b, double c) {
System.out.println("a: " + a + ", b:" + b + ", c: " + c); return51;
}
MethodHandle spreader = delegate.asSpreader(boolean[].class, 2); int ret = (int) spreader.invokeExact("a", newboolean[] { true, false });
assertEquals(44, ret);
ret = (int) spreader.invoke("a", newboolean[] { true, false });
assertEquals(44, ret);
// boolean can't be cast to String (the first argument to the method). try {
delegate.asSpreader(boolean[].class, 3);
fail();
} catch (WrongMethodTypeException expected) {
}
// int can't be cast to boolean to supply the last argument to the method. try {
delegate.asSpreader(int[].class, 1);
fail();
} catch (WrongMethodTypeException expected) {
}
// In all the cases below, the values printed will be 'a', 'b', 'c', 'd'.
// Filter arguments [0, 1] - all other arguments are passed through // as is.
MethodHandle adapter = MethodHandles.filterArguments(
target, 0, filter1, filter2);
assertEquals(56, (int) adapter.invokeExact('a', "bXXXX", "c", 'd'));
// The return types of the filter doesn't align with the expected argument // type of the target. try {
adapter = MethodHandles.filterArguments(target, 2, filter2, filter1);
fail();
} catch (IllegalArgumentException expected) {
}
// There are more filters than arguments. try {
adapter = MethodHandles.filterArguments(target, 3, filter2, filter1);
fail();
} catch (IllegalArgumentException expected) {
}
// We pass in an obviously bogus position. try {
adapter = MethodHandles.filterArguments(target, -1, filter2, filter1);
fail();
} catch (ArrayIndexOutOfBoundsException expected) {
}
// We pass in a function that has more than one argument.
MethodHandle badFilter1 = MethodHandles.lookup().findStatic(
Main.class, "badFilter1",
MethodType.methodType(String.class, char.class, char.class));
// Filter at position 0.
MethodHandle adapter = MethodHandles.collectArguments(target, 0, filter);
assertEquals(57, (int) adapter.invokeExact('a', 'b', "c", "d"));
// Filter at position 1.
adapter = MethodHandles.collectArguments(target, 1, filter);
assertEquals(57, (int) adapter.invokeExact("a", 'b', 'c', "d"));
// Filter at position 2.
adapter = MethodHandles.collectArguments(target, 2, filter);
assertEquals(57, (int) adapter.invokeExact("a", "b", 'c', 'd'));
// Test void filters. Note that we're passing in one more argument // than usual because the filter returns nothing - we have to invoke with // the full set of filter args and the full set of target args.
filter = MethodHandles.lookup().findStatic(Main.class, "voidFilter",
MethodType.methodType(void.class, char.class, char.class));
adapter = MethodHandles.collectArguments(target, 0, filter);
assertEquals(57, (int) adapter.invokeExact('a', 'b', "a", "b", "c"));
// Test out a few failure cases.
filter = MethodHandles.lookup().findStatic(
Main.class, "filter",
MethodType.methodType(String.class, char.class, char.class));
// Basic single element array inserted at position 0.
MethodHandle adapter = MethodHandles.insertArguments(
target, 0, new Object[] { "foo" });
assertEquals(73, (int) adapter.invokeExact(45, Integer.valueOf(56), "bar"));
// Insert an argument at the last position.
adapter = MethodHandles.insertArguments(
target, 3, new Object[] { "bar" });
assertEquals(73, (int) adapter.invokeExact("foo", 45, Integer.valueOf(46)));
// Exercise a few error cases.
// A reference type that can't be cast to another reference type. try {
MethodHandles.insertArguments(target, 3, new Object[] { new Object() });
fail();
} catch (ClassCastException expected) {
}
// A boxed type that can't be unboxed correctly. try {
MethodHandles.insertArguments(target, 1, new Object[] { Long.valueOf(56) });
fail();
} catch (ClassCastException expected) {
}
}
publicstatic String foldFilter(char a, char b) { return String.valueOf(a) + "+" + b;
}
publicstaticvoid voidFoldFilter(String e, char a, char b) {
System.out.println(String.valueOf(a) + "+" + b);
}
publicstaticint foldTarget(String a, char b, char c, String d) {
System.out.println("a: " + a + " ,b:" + b + " ,c:" + c + " ,d:" + d); return89;
}
publicstaticvoid mismatchedVoidFilter(Integer a) {
}
publicstatic Integer mismatchedNonVoidFilter(char a, char b) { returnnull;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.