Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  Main.java

  Sprache: JAVA
 

/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.lang.invoke.VarHandle;
import java.lang.invoke.WrongMethodTypeException;

public class Main {
  public static void main(String[] args) throws Throwable {
    testThrowException();
    testDropArguments();
    testCatchException();
    testGuardWithTest();
    testArrayElementGetter();
    testArrayElementSetter();
    testIdentity();
    testConstant();
    testBindTo();
    testFilterReturnValue();
    testPermuteArguments();
    testInvokers();
    testSpreaders_reference();
    testSpreaders_primitive();
    testInvokeWithArguments();
    testAsCollector();
    testFilterArguments();
    testCollectArguments();
    testInsertArguments();
    testFoldArguments();
  }

  public static void testThrowException() throws Throwable {
    MethodHandle handle = MethodHandles.throwException(String.class,
        IllegalArgumentException.class);

    if (handle.type().returnType() != String.class) {
      fail("Unexpected return type for handle: " + handle +
          " [ " + handle.type() + "]");
    }

    final IllegalArgumentException iae = new IllegalArgumentException("boo!");
    try {
      handle.invoke(iae);
      fail("Expected an exception of type: java.lang.IllegalArgumentException");
    } catch (IllegalArgumentException expected) {
      if (expected != iae) {
        fail("Wrong exception: expected " + iae + " but was " + expected);
      }
    }
  }

  public static void dropArguments_delegate(String message, long message2) {
    System.out.println("Message: " + message + ", Message2: " + message2);
  }

  public static void testDropArguments() throws Throwable {
    MethodHandle delegate = MethodHandles.lookup().findStatic(Main.class,
        "dropArguments_delegate",
        MethodType.methodType(void.classnew Class<?>[] { String.classlong.class }));

    MethodHandle transform = MethodHandles.dropArguments(delegate, 0int.class, Object.class);

    // The transformer will accept two additional arguments at position zero.
    try {
      transform.invokeExact("foo"42l);
      fail();
    } catch (WrongMethodTypeException expected) {
    }

    transform.invokeExact(45new Object(), "foo"42l);
    transform.invoke(45new Object(), "foo"42l);

    // Additional arguments at position 1.
    transform = MethodHandles.dropArguments(delegate, 1int.class, Object.class);
    transform.invokeExact("foo"45new Object(), 42l);
    transform.invoke("foo"45new Object(), 42l);

    // Additional arguments at position 2.
    transform = MethodHandles.dropArguments(delegate, 2int.class, Object.class);
    transform.invokeExact("foo"42l, 45new Object());
    transform.invoke("foo"42l, 45new 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, 0int.class, Object.class);
    transform = transform.asType(MethodType.methodType(void.class,
          new Class<?>[] { short.class, Object.class, String.classlong.class }));
    transform.invokeExact((short45new Object(), "foo"42l);

    // Invalid argument location, should not be allowed.
    try {
      MethodHandles.dropArguments(delegate, -1int.class, Object.class);
      fail();
    } catch (IllegalArgumentException expected) {
    }

    // Invalid argument location, should not be allowed.
    try {
      MethodHandles.dropArguments(delegate, 3int.class, Object.class);
      fail();
    } catch (IllegalArgumentException expected) {
    }

    try {
      MethodHandles.dropArguments(delegate, 1void.class);
      fail();
    } catch (IllegalArgumentException expected) {
    }
  }

  public static String testCatchException_target(String arg1, long arg2, String exceptionMessage)
      throws Throwable {
    if (exceptionMessage != null) {
      throw new IllegalArgumentException(exceptionMessage);
    }

    System.out.println("Target: Arg1: " + arg1 + ", Arg2: " + arg2);
    return "target";
  }

  public static String testCatchException_handler(IllegalArgumentException iae, String arg1, long arg2,
      String exMsg) {
    System.out.println("Handler: " + iae + ", Arg1: " + arg1 + ", Arg2: " + arg2 + ", ExMsg: " + exMsg);
    return "handler1";
  }

  public static String testCatchException_handler2(IllegalArgumentException iae, String arg1) {
    System.out.println("Handler: " + iae + ", Arg1: " + arg1);
    return "handler2";
  }

  public static void testCatchException() throws Throwable {
    MethodHandle target = MethodHandles.lookup().findStatic(Main.class,
        "testCatchException_target",
        MethodType.methodType(String.classnew Class<?>[] { String.classlong.class, String.class }));

    MethodHandle handler = MethodHandles.lookup().findStatic(Main.class,
        "testCatchException_handler",
        MethodType.methodType(String.classnew Class<?>[] { IllegalArgumentException.class,
            String.classlong.class, String.class }));

    MethodHandle adapter = MethodHandles.catchException(target, IllegalArgumentException.class,
        handler);

    String returnVal = null;

    // 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"42null);
    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);

    handler = MethodHandles.lookup().findStatic(Main.class,
        "testCatchException_handler2",
        MethodType.methodType(String.classnew Class<?>[] { IllegalArgumentException.class,
            String.class }));
    adapter = MethodHandles.catchException(target, IllegalArgumentException.class, handler);

    returnVal = (String) adapter.invoke("foo"42"exceptionMessage");
    assertEquals("handler2", returnVal);
    returnVal = (String) adapter.invokeExact("foo"42l, "exceptionMessage");
    assertEquals("handler2", 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);

    returnVal = (String) adapter.invoke("foo"42"exceptionMessage");
    assertEquals("java.lang.IllegalArgumentException: exceptionMessage", returnVal);
    returnVal = (String) adapter.invokeExact("foo"42l, "exceptionMessage2");
    assertEquals("java.lang.IllegalArgumentException: exceptionMessage2", returnVal);

    // Check that asType works as expected.
    adapter = MethodHandles.catchException(target, IllegalArgumentException.class,
        handler);
    adapter = adapter.asType(MethodType.methodType(String.class,
          new Class<?>[] { String.classint.class, String.class }));
    returnVal = (String) adapter.invokeExact("foo"42"exceptionMessage");
    assertEquals("java.lang.IllegalArgumentException: exceptionMessage", returnVal);
  }

  public static boolean testGuardWithTest_test(String arg1, long arg2) {
    return "target".equals(arg1) && 42 == arg2;
  }

  public static String testGuardWithTest_target(String arg1, long arg2, int arg3) {
    System.out.println("target: " + arg1 + ", " + arg2  + ", " + arg3);
    return "target";
  }

  public static String testGuardWithTest_fallback(String arg1, long arg2, int arg3) {
    System.out.println("fallback: " + arg1 + ", " + arg2  + ", " + arg3);
    return "fallback";
  }

  public static void testGuardWithTest() throws Throwable {
    MethodHandle test = MethodHandles.lookup().findStatic(Main.class,
        "testGuardWithTest_test",
        MethodType.methodType(boolean.classnew Class<?>[] { String.classlong.class }));

    final MethodType type = MethodType.methodType(String.class,
        new Class<?>[] { String.classlong.classint.class });

    final MethodHandle target = MethodHandles.lookup().findStatic(Main.class,
        "testGuardWithTest_target", type);
    final MethodHandle fallback = MethodHandles.lookup().findStatic(Main.class,
        "testGuardWithTest_fallback", type);

    MethodHandle adapter = MethodHandles.guardWithTest(test, target, fallback);

    String returnVal = null;

    returnVal = (String) adapter.invoke("target"4256);
    assertEquals("target", returnVal);
    returnVal = (String) adapter.invokeExact("target"42l, 56);
    assertEquals("target", returnVal);

    returnVal = (String) adapter.invoke("fallback"42l, 56);
    assertEquals("fallback", returnVal);
    returnVal = (String) adapter.invokeExact("target"42l, 56);
    assertEquals("target", returnVal);

    // Check that asType works as expected.
    adapter = adapter.asType(MethodType.methodType(String.class,
          new Class<?>[] { String.classint.classint.class }));
    returnVal = (String) adapter.invokeExact("target"4256);
    assertEquals("target", returnVal);
  }

  public static void testArrayElementGetter() throws Throwable {
    MethodHandle getter = MethodHandles.arrayElementGetter(int[].class);

    {
      int[] array = new int[1];
      array[0] = 42;
      int value = (int) getter.invoke(array, 0);
      if (value != 42) {
        fail("Unexpected value: " + value);
      }

      try {
        value = (int) getter.invoke(array, -1);
        fail();
      } catch (ArrayIndexOutOfBoundsException expected) {
      }

      try {
        value = (int) getter.invoke(null, -1);
        fail();
      } catch (NullPointerException expected) {
      }
    }

    {
      getter = MethodHandles.arrayElementGetter(long[].class);
      long[] array = new long[1];
      array[0] = 42;
      long value = (long) getter.invoke(array, 0);
      if (value != 42l) {
        fail("Unexpected value: " + value);
      }
    }

    {
      getter = MethodHandles.arrayElementGetter(short[].class);
      short[] array = new short[1];
      array[0] = 42;
      short value = (short) getter.invoke(array, 0);
      if (value != 42l) {
        fail("Unexpected value: " + value);
      }
    }

    {
      getter = MethodHandles.arrayElementGetter(char[].class);
      char[] array = new char[1];
      array[0] = 42;
      char value = (char) getter.invoke(array, 0);
      if (value != 42l) {
        fail("Unexpected value: " + value);
      }
    }

    {
      getter = MethodHandles.arrayElementGetter(byte[].class);
      byte[] array = new byte[1];
      array[0] = (byte0x8;
      byte value = (byte) getter.invoke(array, 0);
      if (value != (byte0x8) {
        fail("Unexpected value: " + value);
      }
    }

    {
      getter = MethodHandles.arrayElementGetter(boolean[].class);
      boolean[] array = new boolean[1];
      array[0] = true;
      boolean value = (boolean) getter.invoke(array, 0);
      if (!value) {
        fail("Unexpected value: " + value);
      }
    }

    {
      getter = MethodHandles.arrayElementGetter(float[].class);
      float[] array = new float[1];
      array[0] = 42.0f;
      float value = (float) getter.invoke(array, 0);
      if (value != 42.0f) {
        fail("Unexpected value: " + value);
      }
    }

    {
      getter = MethodHandles.arrayElementGetter(double[].class);
      double[] array = new double[1];
      array[0] = 42.0;
      double value = (double) getter.invoke(array, 0);
      if (value != 42.0) {
        fail("Unexpected value: " + value);
      }
    }

    {
      getter = MethodHandles.arrayElementGetter(String[].class);
      String[] array = new String[3];
      array[0] = "42";
      array[1] = "48";
      array[2] = "54";
      String value = (String) getter.invoke(array, 0);
      assertEquals("42", value);
      value = (String) getter.invoke(array, 1);
      assertEquals("48", value);
      value = (String) getter.invoke(array, 2);
      assertEquals("54", value);
    }
  }

  public static void testArrayElementSetter() throws Throwable {
    MethodHandle setter = MethodHandles.arrayElementSetter(int[].class);

    {
      int[] array = new int[2];
      setter.invoke(array, 042);
      setter.invoke(array, 143);

      if (array[0] != 42) {
        fail("Unexpected value: " + array[0]);
      }
      if (array[1] != 43) {
        fail("Unexpected value: " + array[1]);
      }

      try {
        setter.invoke(array, -142);
        fail();
      } catch (ArrayIndexOutOfBoundsException expected) {
      }

      try {
        setter.invoke(null042);
        fail();
      } catch (NullPointerException expected) {
      }
    }

    {
      setter = MethodHandles.arrayElementSetter(long[].class);
      long[] array = new long[1];
      setter.invoke(array, 042l);
      if (array[0] != 42l) {
        fail("Unexpected value: " + array[0]);
      }
    }

    {
      setter = MethodHandles.arrayElementSetter(short[].class);
      short[] array = new short[1];
      setter.invoke(array, 0, (short42);
      if (array[0] != 42l) {
        fail("Unexpected value: " + array[0]);
      }
    }

    {
      setter = MethodHandles.arrayElementSetter(char[].class);
      char[] array = new char[1];
      setter.invoke(array, 0, (char42);
      if (array[0] != 42) {
        fail("Unexpected value: " + array[0]);
      }
    }

    {
      setter = MethodHandles.arrayElementSetter(byte[].class);
      byte[] array = new byte[1];
      setter.invoke(array, 0, (byte0x8);
      if (array[0] != (byte0x8) {
        fail("Unexpected value: " + array[0]);
      }
    }

    {
      setter = MethodHandles.arrayElementSetter(boolean[].class);
      boolean[] array = new boolean[1];
      setter.invoke(array, 0true);
      if (!array[0]) {
        fail("Unexpected value: " + array[0]);
      }
    }

    {
      setter = MethodHandles.arrayElementSetter(float[].class);
      float[] array = new float[1];
      setter.invoke(array, 042.0f);
      if (array[0] != 42.0f) {
        fail("Unexpected value: " + array[0]);
      }
    }

    {
      setter = MethodHandles.arrayElementSetter(double[].class);
      double[] array = new double[1];
      setter.invoke(array, 042.0);
      if (array[0] != 42.0) {
        fail("Unexpected value: " + array[0]);
      }
    }

    {
      setter = MethodHandles.arrayElementSetter(String[].class);
      String[] array = new String[3];
      setter.invoke(array, 0"42");
      setter.invoke(array, 1"48");
      setter.invoke(array, 2"54");
      assertEquals("42", array[0]);
      assertEquals("48", array[1]);
      assertEquals("54", array[2]);
    }
  }

  public static void testIdentity() throws Throwable {
    {
      MethodHandle identity = MethodHandles.identity(boolean.class);
      boolean value = (boolean) identity.invoke(false);
      if (value) {
        fail("Unexpected value: " + value);
      }
    }

    {
      MethodHandle identity = MethodHandles.identity(byte.class);
      byte value = (byte) identity.invoke((byte0x8);
      if (value != (byte0x8) {
        fail("Unexpected value: " + value);
      }
    }

    {
      MethodHandle identity = MethodHandles.identity(char.class);
      char value = (char) identity.invoke((char) -56);
      if (value != (char) -56) {
        fail("Unexpected value: " + value);
      }
    }

    {
      MethodHandle identity = MethodHandles.identity(short.class);
      short value = (short) identity.invoke((short) -59);
      if (value != (short) -59) {
        fail("Unexpected value: " + Short.toString(value));
      }
    }

    {
      MethodHandle identity = MethodHandles.identity(int.class);
      int value = (int) identity.invoke(52);
      if (value != 52) {
        fail("Unexpected value: " + value);
      }
    }

    {
      MethodHandle identity = MethodHandles.identity(long.class);
      long value = (long) identity.invoke(-76l);
      if (value != (long) -76) {
        fail("Unexpected value: " + value);
      }
    }

    {
      MethodHandle identity = MethodHandles.identity(float.class);
      float value = (float) identity.invoke(56.0f);
      if (value != (float56.0f) {
        fail("Unexpected value: " + value);
      }
    }

    {
      MethodHandle identity = MethodHandles.identity(double.class);
      double value = (double) identity.invoke((double72.0);
      if (value != (double72.0) {
        fail("Unexpected value: " + value);
      }
    }

    {
      MethodHandle identity = MethodHandles.identity(String.class);
      String value = (String) identity.invoke("bazman");
      assertEquals("bazman", value);
    }
  }

  public static void testConstant() throws Throwable {
    // int constants.
    {
      MethodHandle constant = MethodHandles.constant(int.class56);
      int value = (int) constant.invoke();
      if (value != 56) {
        fail("Unexpected value: " + value);
      }

      // short constant values are converted to int.
      constant = MethodHandles.constant(int.class, (short52);
      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, (byte0x1);
      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.classfalse);
        fail();
      } catch (ClassCastException expected) {
      }

      try {
        MethodHandles.constant(int.class0.1f);
        fail();
      } catch (ClassCastException expected) {
      }

      try {
        MethodHandles.constant(int.class0.2);
        fail();
      } catch (ClassCastException expected) {
      }

      try {
        MethodHandles.constant(int.class73l);
        fail();
      } catch (ClassCastException expected) {
      }
    }

    // long constants.
    {
      MethodHandle constant = MethodHandles.constant(long.class56l);
      long value = (long) constant.invoke();
      if (value != 56l) {
        fail("Unexpected value: " + value);
      }

      constant = MethodHandles.constant(long.class, (int56);
      value = (long) constant.invoke();
      if (value != 56l) {
        fail("Unexpected value: " + value);
      }
    }

    // byte constants.
    {
      MethodHandle constant = MethodHandles.constant(byte.class, (byte0x12);
      byte value = (byte) constant.invoke();
      if (value != (byte0x12) {
        fail("Unexpected value: " + value);
      }
    }

    // boolean constants.
    {
      MethodHandle constant = MethodHandles.constant(boolean.classtrue);
      boolean value = (boolean) constant.invoke();
      if (!value) {
        fail("Unexpected value: " + value);
      }
    }

    // char constants.
    {
      MethodHandle constant = MethodHandles.constant(char.class'f');
      char value = (char) constant.invoke();
      if (value != 'f') {
        fail("Unexpected value: " + value);
      }
    }

    // short constants.
    {
      MethodHandle constant = MethodHandles.constant(short.class, (short123);
      short value = (short) constant.invoke();
      if (value != (short123) {
        fail("Unexpected value: " + value);
      }
    }

    // float constants.
    {
      MethodHandle constant = MethodHandles.constant(float.class56.0f);
      float value = (float) constant.invoke();
      if (value != 56.0f) {
        fail("Unexpected value: " + value);
      }
    }

    // double constants.
    {
      MethodHandle constant = MethodHandles.constant(double.class256.0);
      double value = (double) constant.invoke();
      if (value != 256.0) {
        fail("Unexpected value: " + value);
      }
    }

    // reference constants.
    {
      MethodHandle constant = MethodHandles.constant(String.class"256.0");
      String value = (String) constant.invoke();
      assertEquals("256.0", value);
    }
  }

  public static void testBindTo() throws Throwable {
    MethodHandle stringCharAt = MethodHandles.lookup().findVirtual(
        String.class"charAt", MethodType.methodType(char.classint.class));

    char value = (char) stringCharAt.invoke("foo"0);
    if (value != 'f') {
      fail("Unexpected value: " + value);
    }

    MethodHandle bound = stringCharAt.bindTo("foo");
    value = (char) bound.invoke(0);
    if (value != 'f') {
      fail("Unexpected value: " + value);
    }

    try {
      stringCharAt.bindTo(new Object());
      fail();
    } catch (ClassCastException expected) {
    }

    bound = stringCharAt.bindTo(null);
    try {
      bound.invoke(0);
      fail();
    } catch (NullPointerException expected) {
    }

    MethodHandle integerParseInt = MethodHandles.lookup().findStatic(
        Integer.class"parseInt", MethodType.methodType(int.class, String.class));

    bound = integerParseInt.bindTo("78452");
    int intValue = (int) bound.invoke();
    if (intValue != 78452) {
      fail("Unexpected value: " + intValue);
    }

    class Locals {
        public int intValue;
    };

    MethodHandle setter1 = MethodHandles.lookup().findSetter(Locals.class"intValue"int.class);
    Locals locals = new Locals();
    setter1.invoke(locals, 1);
    assertEquals(1, locals.intValue);

    MethodHandle setter2 =
        MethodHandles.insertArguments(setter1.bindTo(locals), 0, Integer.valueOf(2));
    setter2.invoke();
    assertEquals(2, locals.intValue);

    VarHandle vh = MethodHandles.lookup().findVarHandle(Locals.class,  "intValue"int.class);
    MethodHandle setter3 = vh.toMethodHandle(VarHandle.AccessMode.GET_AND_SET);
    assertEquals(setter3.type().toString(),
                 MethodType.methodType(int.class, Locals.classint.class).toString());
    assertEquals(2, (int) setter3.invoke(locals, 3));

    MethodHandle setter4 =
        MethodHandles.varHandleInvoker(VarHandle.AccessMode.GET_AND_SET,
                                       MethodType.methodType(int.class, Locals.classint.class));
    assertEquals(3, (int) setter4.invoke(vh, locals, 4));

    MethodHandle setter5 = setter4.bindTo(vh);
    assertEquals(4, (int) setter5.invoke(locals, 5));

    MethodHandle setter6 = MethodHandles.insertArguments(setter5, 0, locals, 6);
    assertEquals(5, (int) setter6.invoke());
    assertEquals(locals.intValue, 6);
  }

  public static String filterReturnValue_target(int a) {
    return "ReturnValue" + a;
  }

  public static boolean filterReturnValue_filter(String value) {
    return value.indexOf("42") != -1;
  }

  public static int filterReturnValue_intTarget(String a) {
    return Integer.parseInt(a);
  }

  public static int filterReturnValue_intFilter(int b) {
    return b + 1;
  }

  public static void filterReturnValue_voidTarget() {
  }

  public static int filterReturnValue_voidFilter() {
    return 42;
  }

  public static void testFilterReturnValue() throws Throwable {
    // A target that returns a reference.
    {
      final MethodHandle target = MethodHandles.lookup().findStatic(Main.class,
          "filterReturnValue_target", MethodType.methodType(String.classint.class));
      final MethodHandle filter = MethodHandles.lookup().findStatic(Main.class,
          "filterReturnValue_filter", MethodType.methodType(boolean.class, String.class));

      MethodHandle adapter = MethodHandles.filterReturnValue(target, filter);

      boolean value = (boolean) adapter.invoke((int42);
      if (!value) {
        fail("Unexpected value: " + value);
      }
      value = (boolean) adapter.invoke((int43);
      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.classint.class));

      MethodHandle adapter = MethodHandles.filterReturnValue(target, filter);

      int value = (int) adapter.invoke("56");
      if (value != 57) {
        fail("Unexpected value: " + value);
      }
    }

    // A target that returns void.
    {
      final MethodHandle target = MethodHandles.lookup().findStatic(Main.class,
          "filterReturnValue_voidTarget", MethodType.methodType(void.class));
      final MethodHandle filter = MethodHandles.lookup().findStatic(Main.class,
          "filterReturnValue_voidFilter", MethodType.methodType(int.class));

      MethodHandle adapter = MethodHandles.filterReturnValue(target, filter);

      int value = (int) adapter.invoke();
      if (value != 42) {
        fail("Unexpected value: " + value);
      }
    }
  }

  public static void 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 == (short56 &&
        e == 78 && f == (long97 && g == 98.0f && f == 97.0) {
      return;
    }

    fail("Unexpected arguments: " + a + ", " + b + ", " + c
        + ", " + d + ", " + e + ", " + f + ", " + g + ", " + h);
  }

  public static void permuteArguments_boxingCallee(boolean a, Integer b) {
    if (a && b.intValue() == 42) {
      return;
    }

    fail("Unexpected arguments: " + a + ", " + b);
  }

  public static void testPermuteArguments() throws Throwable {
    {
      final MethodHandle target = MethodHandles.lookup().findStatic(
          Main.class"permuteArguments_callee",
          MethodType.methodType(void.classnew Class<?>[] {
            boolean.classbyte.classchar.classshort.classint.class,
            long.classfloat.classdouble.class }));

      final MethodType newType = MethodType.methodType(void.classnew Class<?>[] {
        double.classfloat.classlong.classint.classshort.classchar.class,
        byte.classboolean.class });

      final MethodHandle permutation = MethodHandles.permuteArguments(
          target, newType, new int[] { 76543210 });

      permutation.invoke((double97.0, (float98.0f, (long9778,
          (short56'c', (byte'b', (booleantrue);

      // The permutation array was not of the right length.
      try {
        MethodHandles.permuteArguments(target, newType,
            new int[] { 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,
            new int[] { 86543210 });
        fail();
      } catch (IllegalArgumentException expected) {
      }

      // The permutation array maps to an incorrect type.
      try {
        MethodHandles.permuteArguments(target, newType,
            new int[] { 77543210 });
        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);

      assertEquals("foobar", (String) target.invoke("foo""bar"));

      MethodHandle permutation = MethodHandles.permuteArguments(target,
          newType, new int[] { 10 });
      assertEquals("barfoo", (String) permutation.invoke("foo""bar"));

      permutation = MethodHandles.permuteArguments(target, newType, new int[] { 00 });
      assertEquals("foofoo", (String) permutation.invoke("foo""bar"));

      permutation = MethodHandles.permuteArguments(target, newType, new int[] { 11 });
      assertEquals("barbar", (String) permutation.invoke("foo""bar"));
    }

    // Tests for boxing and unboxing.
    {
      final MethodHandle target = MethodHandles.lookup().findStatic(
          Main.class"permuteArguments_boxingCallee",
          MethodType.methodType(void.classnew Class<?>[] { boolean.class, Integer.class }));

      final MethodType newType = MethodType.methodType(void.class,
          new Class<?>[] { Integer.classboolean.class });

      MethodHandle permutation = MethodHandles.permuteArguments(target,
          newType, new int[] { 10 });

      permutation.invoke(42true);
      permutation.invoke(42Boolean.TRUE);
      permutation.invoke(Integer.valueOf(42), true);
      permutation.invoke(Integer.valueOf(42), Boolean.TRUE);
    }
  }

  private static Object returnBar() {
    return "bar";
  }

  public static void testInvokers() throws Throwable {
    final MethodType targetType = MethodType.methodType(String.class, String.class);
    final MethodHandle target = MethodHandles.lookup().findVirtual(
        String.class"concat", targetType);

    MethodHandle invoker = MethodHandles.invoker(target.type());
    assertEquals("barbar", (String) invoker.invoke(target, "bar""bar"));
    assertEquals("barbar", (String) invoker.invoke(target, (Object) returnBar(), "bar"));
    try {
      String foo = (String) invoker.invoke(target, "bar""bar"24);
      fail();
    } catch (WrongMethodTypeException expected) {
    }

    MethodHandle exactInvoker = MethodHandles.exactInvoker(target.type());
    assertEquals("barbar", (String) exactInvoker.invoke(target, "bar""bar"));
    assertEquals("barbar", (String) exactInvoker.invoke(target, (Object) returnBar(), "bar"));
    try {
      assertEquals("barbar", (String) invoker.invoke(target, (Object) Integer.valueOf(7), "bar"));
      fail();
    } catch (ClassCastException expected) {
    }
    try {
      assertEquals("barbar", (String) invoker.invoke(target, (Object) null"bar"));
      fail();
    } catch (NullPointerException expected) {
    }
    exactInvoker.invoke(target, (Object) returnBar(), "bar");

    try {
      String foo = (String) exactInvoker.invoke(target, "bar""bar"24);
      fail();
    } catch (WrongMethodTypeException expected) {
    }
  }

  public static int spreadReferences(String a, String b, String c) {
    System.out.println("a: " + a + ", b:" + b + ", c: " + c);
    return 42;
  }

  public static int spreadReferences_Unbox(String a, int b) {
    System.out.println("a: " + a + ", b:" + b);
    return 43;
  }

  public static void testSpreaders_reference() throws Throwable {
    MethodType methodType = MethodType.methodType(int.class,
        new Class<?>[] { String.class, String.class, String.class });
    MethodHandle delegate = MethodHandles.lookup().findStatic(
        Main.class"spreadReferences", methodType);

    // Basic checks on array lengths.
    //
    // Array size = 0
    MethodHandle mhAsSpreader = delegate.asSpreader(String[].class0);
    int ret = (int) mhAsSpreader.invoke("a""b""c"new String[] {});
    assertEquals(42, ret);
    // Array size = 1
    mhAsSpreader = delegate.asSpreader(String[].class1);
    ret = (int) mhAsSpreader.invoke("a""b"new String[] { "c" });
    assertEquals(42, ret);
    // Array size = 2
    mhAsSpreader = delegate.asSpreader(String[].class2);
    ret = (int) mhAsSpreader.invoke("a"new String[] { "b""c" });
    assertEquals(42, ret);
    // Array size = 3
    mhAsSpreader = delegate.asSpreader(String[].class3);
    ret = (int) mhAsSpreader.invoke(new String[] { "a""b""c"});
    assertEquals(42, ret);

    // Exception case, array size = 4 is illegal.
    try {
      delegate.asSpreader(String[].class4);
      fail();
    } catch (IllegalArgumentException expected) {
    }

    // Exception case, calling with an arg of the wrong size.
    // Array size = 3
    mhAsSpreader = delegate.asSpreader(String[].class3);
    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[].class2);
    ret = (int) mhAsSpreader.invoke("a"new String[] { "b""c" });
    assertEquals(42, ret);

    mhAsSpreader = delegate.asSpreader(Object[].class2);
    ret = (int) mhAsSpreader.invoke("a"new Object[] { "b""c" });
    assertEquals(42, ret);

    mhAsSpreader = delegate.asSpreader(Object[].class2);
    ret = (int) mhAsSpreader.invoke("a", (Object) new Object[] { "b""c" });
    assertEquals(42, ret);

    // Test implicit unboxing.
    MethodType methodType2 = MethodType.methodType(int.class,
        new Class<?>[] { String.classint.class });
    MethodHandle delegate2 = MethodHandles.lookup().findStatic(
        Main.class"spreadReferences_Unbox", methodType2);

    // .. with an Integer[] array.
    mhAsSpreader = delegate2.asSpreader(Integer[].class1);
    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[].class1);
    ret = (int) mhAsSpreader.invoke("a"new Integer[] { 43 });
    assertEquals(43, ret);

    // .. with an Object[] array.
    mhAsSpreader = delegate2.asSpreader(Object[].class1);
    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);
  }

  public static int spreadBoolean(String a, Boolean b, boolean c) {
    System.out.println("a: " + a + ", b:" + b + ", c: " + c);
    return 44;
  }

  public static int 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);
    return 45;
  }

  public static int 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);
    return 46;
  }

  public static int 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);
    return 47;
  }

  public static int 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);
    return 48;
  }

  public static int spreadLong(String a, Long b, long c, float d, double e) {
    System.out.println("a: " + a + ", b:" + b + ", c: " + c +
        ", d: " + d + ", e: " + e);
    return 49;
  }

  public static int spreadFloat(String a, Float b, float c, double d) {
    System.out.println("a: " + a + ", b:" + b + ", c: " + c + ", d: " + d);
    return 50;
  }

  public static int spreadDouble(String a, Double b, double c) {
    System.out.println("a: " + a + ", b:" + b + ", c: " + c);
    return 51;
  }

  public static void testSpreaders_primitive() throws Throwable {
    // boolean[]
    // ---------------------
    MethodType type = MethodType.methodType(int.class,
        new Class<?>[] { String.classBoolean.classboolean.class });
    MethodHandle delegate = MethodHandles.lookup().findStatic(
        Main.class"spreadBoolean", type);

    MethodHandle spreader = delegate.asSpreader(boolean[].class2);
    int ret = (int) spreader.invokeExact("a"new boolean[] { truefalse });
    assertEquals(44, ret);
    ret = (int) spreader.invoke("a"new boolean[] { truefalse });
    assertEquals(44, ret);

    // boolean can't be cast to String (the first argument to the method).
    try {
      delegate.asSpreader(boolean[].class3);
      fail();
    } catch (WrongMethodTypeException expected) {
    }

    // int can't be cast to boolean to supply the last argument to the method.
    try {
      delegate.asSpreader(int[].class1);
      fail();
    } catch (WrongMethodTypeException expected) {
    }

    // byte[]
    // ---------------------
    type = MethodType.methodType(int.class,
        new Class<?>[] {
          String.classByte.classbyte.class,
          short.classint.classlong.class,
          float.classdouble.class });
    delegate = MethodHandles.lookup().findStatic(Main.class"spreadByte", type);

    spreader = delegate.asSpreader(byte[].class7);
    ret = (int) spreader.invokeExact("a",
        new byte[] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 });
    assertEquals(45, ret);
    ret = (int) spreader.invoke("a",
        new byte[] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 });
    assertEquals(45, ret);

    // char[]
    // ---------------------
    type = MethodType.methodType(int.class,
        new Class<?>[] {
          String.class, Character.class,char.class,
          int.classlong.classfloat.classdouble.class });
    delegate = MethodHandles.lookup().findStatic(Main.class"spreadChar", type);

    spreader = delegate.asSpreader(char[].class6);
    ret = (int) spreader.invokeExact("a",
        new char[] { '1''2''3''4''5''6' });
    assertEquals(46, ret);
    ret = (int) spreader.invokeExact("a",
        new char[] { '1''2''3''4''5''6' });
    assertEquals(46, ret);

    // short[]
    // ---------------------
    type = MethodType.methodType(int.class,
        new Class<?>[] {
          String.classShort.classshort.class,
          int.classlong.classfloat.classdouble.class });
    delegate = MethodHandles.lookup().findStatic(Main.class"spreadShort", type);

    spreader = delegate.asSpreader(short[].class6);
    ret = (int) spreader.invokeExact("a",
        new short[] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6 });
    assertEquals(47, ret);
    ret = (int) spreader.invoke("a",
        new short[] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6 });
    assertEquals(47, ret);

    // int[]
    // ---------------------
    type = MethodType.methodType(int.class,
        new Class<?>[] {
          String.class, Integer.classint.class,
          long.classfloat.classdouble.class });
    delegate = MethodHandles.lookup().findStatic(Main.class"spreadInt", type);

    spreader = delegate.asSpreader(int[].class5);
    ret = (int) spreader.invokeExact("a"new int[] { 12345 });
    assertEquals(48, ret);
    ret = (int) spreader.invokeExact("a"new int[] { 12345 });
    assertEquals(48, ret);

    // long[]
    // ---------------------
    type = MethodType.methodType(int.class,
        new Class<?>[] {
          String.classLong.classlong.classfloat.classdouble.class });
    delegate = MethodHandles.lookup().findStatic(Main.class"spreadLong", type);

    spreader = delegate.asSpreader(long[].class4);
    ret = (int) spreader.invokeExact("a",
        new long[] { 0x1, 0x2, 0x3, 0x4 });
    assertEquals(49, ret);
    ret = (int) spreader.invoke("a",
        new long[] { 0x1, 0x2, 0x3, 0x4 });
    assertEquals(49, ret);

    // float[]
    // ---------------------
    type = MethodType.methodType(int.class,
        new Class<?>[] {
          String.classFloat.classfloat.classdouble.class });
    delegate = MethodHandles.lookup().findStatic(Main.class"spreadFloat", type);

    spreader = delegate.asSpreader(float[].class3);
    ret = (int) spreader.invokeExact("a",
        new float[] { 1.0f, 2.0f, 3.0f });
    assertEquals(50, ret);
    ret = (int) spreader.invokeExact("a",
        new float[] { 1.0f, 2.0f, 3.0f });
    assertEquals(50, ret);

    // double[]
    // ---------------------
    type = MethodType.methodType(int.class,
        new Class<?>[] { String.classDouble.classdouble.class });
    delegate = MethodHandles.lookup().findStatic(Main.class"spreadDouble", type);

    spreader = delegate.asSpreader(double[].class2);
    ret = (int) spreader.invokeExact("a"new double[] { 1.02.0 });
    assertEquals(51, ret);
    ret = (int) spreader.invokeExact("a"new double[] { 1.02.0 });
    assertEquals(51, ret);
  }

  public static void testInvokeWithArguments() throws Throwable {
    MethodType methodType = MethodType.methodType(int.class,
        new Class<?>[] { String.class, String.class, String.class });
    MethodHandle handle = MethodHandles.lookup().findStatic(
        Main.class"spreadReferences", methodType);

    Object ret = handle.invokeWithArguments(new Object[] { "a""b""c"});
    assertEquals(42, (int) ret);
    handle.invokeWithArguments(new String[] { "a""b""c" });
    assertEquals(42, (int) ret);

    // Pass in an array that's too small. Should throw an IAE.
    try {
      handle.invokeWithArguments(new Object[] { "a""b" });
      fail();
    } catch (IllegalArgumentException expected) {
    } catch (WrongMethodTypeException expected) {
    }

    // Test implicit unboxing.
    MethodType methodType2 = MethodType.methodType(int.class,
        new Class<?>[] { String.classint.class });
    MethodHandle handle2 = MethodHandles.lookup().findStatic(
        Main.class"spreadReferences_Unbox", methodType2);

    ret = (int) handle2.invokeWithArguments(new Object[] { "a"43 });
    assertEquals(43, (int) ret);
  }

  public static int collectBoolean(String a, boolean[] b) {
    System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]);
    return 44;
  }

  public static int collectByte(String a, byte[] b) {
    System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]);
    return 45;
  }

  public static int collectChar(String a, char[] b) {
    System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]);
    return 46;
  }

  public static int collectShort(String a, short[] b) {
    System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]);
    return 47;
  }

  public static int collectInt(String a, int[] b) {
    System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]);
    return 48;
  }

  public static int collectLong(String a, long[] b) {
    System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]);
    return 49;
  }

  public static int collectFloat(String a, float[] b) {
    System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]);
    return 50;
  }

  public static int collectDouble(String a, double[] b) {
    System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]);
    return 51;
  }

  public static int collectCharSequence(String a, CharSequence[] b) {
    System.out.println("a: " + a + ", b:" + b[0] + ", c: " + b[1]);
    return 99;
  }

  public static void testAsCollector() throws Throwable {
    // Reference arrays.
    // -------------------
    MethodHandle trailingRef = MethodHandles.lookup().findStatic(
        Main.class"collectCharSequence",
        MethodType.methodType(int.class, String.class, CharSequence[].class));

    // int[] is not convertible to CharSequence[].class.
    try {
      trailingRef.asCollector(int[].class1);
      fail();
    } catch (IllegalArgumentException expected) {
    }

    // Object[] is not convertible to CharSequence[].class.
    try {
      trailingRef.asCollector(Object[].class1);
      fail();
    } catch (IllegalArgumentException expected) {
    }

    // String[].class is convertible to CharSequence.class
    MethodHandle collector = trailingRef.asCollector(String[].class2);
    assertEquals(99, (int) collector.invoke("a""b""c"));

    // Too few arguments should fail with a WMTE.
    try {
      collector.invoke("a""b");
      fail();
    } catch (WrongMethodTypeException expected) {
    }

    // Too many arguments should fail with a WMTE.
    try {
      collector.invoke("a""b""c""d");
      fail();
    } catch (WrongMethodTypeException expected) {
    }

    // Checks on other array types.

    MethodHandle target = MethodHandles.lookup().findStatic(
        Main.class"collectBoolean",
        MethodType.methodType(int.class, String.classboolean[].class));
    assertEquals(44, (int) target.asCollector(boolean[].class2).invoke("a"truefalse));

    target = MethodHandles.lookup().findStatic(Main.class"collectByte",
        MethodType.methodType(int.class, String.classbyte[].class));
    assertEquals(45, (int) target.asCollector(byte[].class2).invoke("a", (byte1, (byte2));

    target = MethodHandles.lookup().findStatic(Main.class"collectChar",
        MethodType.methodType(int.class, String.classchar[].class));
    assertEquals(46, (int) target.asCollector(char[].class2).invoke("a"'a''b'));

    target = MethodHandles.lookup().findStatic(Main.class"collectShort",
        MethodType.methodType(int.class, String.classshort[].class));
    assertEquals(47, (int) target.asCollector(short[].class2).invoke("a", (short3, (short4));

    target = MethodHandles.lookup().findStatic(Main.class"collectInt",
        MethodType.methodType(int.class, String.classint[].class));
    assertEquals(48, (int) target.asCollector(int[].class2).invoke("a"4243));

    target = MethodHandles.lookup().findStatic(Main.class"collectLong",
        MethodType.methodType(int.class, String.classlong[].class));
    assertEquals(49, (int) target.asCollector(long[].class2).invoke("a"10099));

    target = MethodHandles.lookup().findStatic(Main.class"collectFloat",
        MethodType.methodType(int.class, String.classfloat[].class));
    assertEquals(50, (int) target.asCollector(float[].class2).invoke("a"8.9f, 9.1f));

    target = MethodHandles.lookup().findStatic(Main.class"collectDouble",
        MethodType.methodType(int.class, String.classdouble[].class));
    assertEquals(51, (int) target.asCollector(double[].class2).invoke("a"6.77.8));
  }

  public static String filter1(char a) {
    return String.valueOf(a);
  }

  public static char filter2(String b) {
    return b.charAt(0);
  }

  public static String badFilter1(char a, char b) {
    return "bad";
  }

  public static int filterTarget(String a, char b, String c, char d) {
    System.out.println("a: " + a + ", b: " + b + ", c:" + c + ", d:" + d);
    return 56;
  }

  public static void testFilterArguments() throws Throwable {
    MethodHandle filter1 = MethodHandles.lookup().findStatic(
        Main.class"filter1", MethodType.methodType(String.classchar.class));
    MethodHandle filter2 = MethodHandles.lookup().findStatic(
        Main.class"filter2", MethodType.methodType(char.class, String.class));

    MethodHandle target = MethodHandles.lookup().findStatic(
        Main.class"filterTarget", MethodType.methodType(int.class,
          String.classchar.class, String.classchar.class));

    // 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'));

    // Filter arguments [1, 2].
    adapter = MethodHandles.filterArguments(target, 1, filter2, filter1);
    assertEquals(56, (int) adapter.invokeExact("a""bXXXX"'c''d'));

    // Filter arguments [2, 3].
    adapter = MethodHandles.filterArguments(target, 2, filter1, filter2);
    assertEquals(56, (int) adapter.invokeExact("a"'b''c'"dXXXXX"));

    // Try out a few error cases :

    // 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.classchar.classchar.class));

    try {
      adapter = MethodHandles.filterArguments(target, 0, badFilter1, filter2);
      fail();
    } catch (IllegalArgumentException expected) {
    }
  }

  static void voidFilter(char a, char b) {
    System.out.println("voidFilter");
  }

  static String filter(char a, char b) {
    return String.valueOf(a) + "+" + b;
  }

  static char badFilter(char a, char b) {
    return 0;
  }

  static int target(String a, String b, String c) {
    System.out.println("a: " + a + ", b: " + b + ", c: " + c);
    return 57;
  }

  public static void testCollectArguments() throws Throwable {
    // Test non-void filters.
    MethodHandle filter = MethodHandles.lookup().findStatic(
        Main.class"filter",
        MethodType.methodType(String.classchar.classchar.class));

    MethodHandle target = MethodHandles.lookup().findStatic(
        Main.class"target",
        MethodType.methodType(int.class, String.class, String.class, String.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.classchar.classchar.class));
    adapter = MethodHandles.collectArguments(target, 0, filter);
    assertEquals(57, (int) adapter.invokeExact('a''b'"a""b""c"));

    adapter = MethodHandles.collectArguments(target, 1, filter);
    assertEquals(57, (int) adapter.invokeExact("a"'a''b'"b""c"));

    // Test out a few failure cases.
    filter = MethodHandles.lookup().findStatic(
        Main.class"filter",
        MethodType.methodType(String.classchar.classchar.class));

    // Bogus filter position.
    try {
      adapter = MethodHandles.collectArguments(target, 3, filter);
      fail();
    } catch (IndexOutOfBoundsException | IllegalArgumentException expected) {
    }

    // Mismatch in filter return type.
    filter = MethodHandles.lookup().findStatic(
        Main.class"badFilter",
        MethodType.methodType(char.classchar.classchar.class));
    try {
      adapter = MethodHandles.collectArguments(target, 0, filter);
      fail();
    } catch (IllegalArgumentException expected) {
    }
  }

  static int insertReceiver(String a, int b, Integer c, String d) {
    System.out.println("a: " + a + ", b:" + b + ", c:" + c + ", d:" + d);
    return 73;
  }

  public static void testInsertArguments() throws Throwable {
    MethodHandle target = MethodHandles.lookup().findStatic(
        Main.class"insertReceiver",
        MethodType.methodType(int.class,
          String.classint.class, Integer.class, String.class));

    // Basic single element array inserted at position 0.
    MethodHandle adapter = MethodHandles.insertArguments(
        target, 0new Object[] { "foo" });
    assertEquals(73, (int) adapter.invokeExact(45, Integer.valueOf(56), "bar"));

    // Exercise unboxing.
    adapter = MethodHandles.insertArguments(
        target, 1new Object[] { Integer.valueOf(56), 57 });
    assertEquals(73, (int) adapter.invokeExact("foo""bar"));

    // Exercise a widening conversion.
    adapter = MethodHandles.insertArguments(
        target, 1new Object[] { (short56, Integer.valueOf(57) });
    assertEquals(73, (int) adapter.invokeExact("foo""bar"));

    // Insert an argument at the last position.
    adapter = MethodHandles.insertArguments(
        target, 3new 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, 3new Object[] { new Object() });
      fail();
    } catch (ClassCastException expected) {
    }

    // A boxed type that can't be unboxed correctly.
    try {
      MethodHandles.insertArguments(target, 1new Object[] { Long.valueOf(56) });
      fail();
    } catch (ClassCastException expected) {
    }
  }

  public static String foldFilter(char a, char b) {
    return String.valueOf(a) + "+" + b;
  }

  public static void voidFoldFilter(String e, char a, char b) {
    System.out.println(String.valueOf(a) + "+" + b);
  }

  public static int foldTarget(String a, char b, char c, String d) {
    System.out.println("a: " + a + " ,b:" + b + " ,c:" + c + " ,d:" + d);
    return 89;
  }

  public static void mismatchedVoidFilter(Integer a) {
  }

  public static Integer mismatchedNonVoidFilter(char a, char b) {
    return null;
  }

  public static void testFoldArguments() throws Throwable {
    // Test non-void filters.
    MethodHandle filter = MethodHandles.lookup().findStatic(
        Main.class"foldFilter",
        MethodType.methodType(String.classchar.classchar.class));

    MethodHandle target = MethodHandles.lookup().findStatic(
        Main.class"foldTarget",
        MethodType.methodType(int.class, String.class,
          char.classchar.class, String.class));

    // Folder with a non-void type.
    MethodHandle adapter = MethodHandles.foldArguments(target, filter);
    assertEquals(89, (int) adapter.invokeExact('c''d'"e"));

    // Folder with a void type.
    filter = MethodHandles.lookup().findStatic(
        Main.class"voidFoldFilter",
        MethodType.methodType(void.class, String.classchar.classchar.class));
    adapter = MethodHandles.foldArguments(target, filter);
    assertEquals(89, (int) adapter.invokeExact("a"'c''d'"e"));

    // Test a few erroneous cases.

    filter = MethodHandles.lookup().findStatic(
        Main.class"mismatchedVoidFilter",
        MethodType.methodType(void.class, Integer.class));
    try {
      adapter = MethodHandles.foldArguments(target, filter);
      fail();
    } catch (IllegalArgumentException expected) {
    }

    filter = MethodHandles.lookup().findStatic(
        Main.class"mismatchedNonVoidFilter",
        MethodType.methodType(Integer.classchar.classchar.class));
    try {
      adapter = MethodHandles.foldArguments(target, filter);
      fail();
    } catch (IllegalArgumentException expected) {
    }
  }

  public static void fail() {
    System.out.println("FAIL");
    Thread.dumpStack();
  }

  public static void fail(String message) {
    System.out.println("fail: " + message);
    Thread.dumpStack();
  }

  public static void assertEquals(int i1, int i2) {
    if (i1 != i2) throw new AssertionError("Expected: " + i1 + " was " + i2);
  }

  public static void assertEquals(String s1, String s2) {
    if (s1 == s2) {
      return;
    }

    if (s1 != null && s2 != null && s1.equals(s2)) {
      return;
    }

    throw new AssertionError("assertEquals s1: " + s1 + ", s2: " + s2);
  }
}

Messung V0.5 in Prozent
C=91 H=98 G=94

¤ Dauer der Verarbeitung: 0.26 Sekunden  (vorverarbeitet am  2026-06-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik