< prev index next >

src/java.base/share/classes/java/lang/invoke/MethodHandles.java

Print this page
rev 13766 : 8143410: augment pseudo-code descriptions in MethodHandles API
Reviewed-by: psandoz


2628      * It is an error if there are elements of {@code filters}
2629      * (null or not)
2630      * which do not correspond to argument positions in the target.
2631      * <p><b>Example:</b>
2632      * <blockquote><pre>{@code
2633 import static java.lang.invoke.MethodHandles.*;
2634 import static java.lang.invoke.MethodType.*;
2635 ...
2636 MethodHandle cat = lookup().findVirtual(String.class,
2637   "concat", methodType(String.class, String.class));
2638 MethodHandle upcase = lookup().findVirtual(String.class,
2639   "toUpperCase", methodType(String.class));
2640 assertEquals("xy", (String) cat.invokeExact("x", "y"));
2641 MethodHandle f0 = filterArguments(cat, 0, upcase);
2642 assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy
2643 MethodHandle f1 = filterArguments(cat, 1, upcase);
2644 assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
2645 MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
2646 assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
2647      * }</pre></blockquote>
2648      * <p> Here is pseudocode for the resulting adapter:








2649      * <blockquote><pre>{@code
2650      * V target(P... p, A[i]... a[i], B... b);
2651      * A[i] filter[i](V[i]);
2652      * T adapter(P... p, V[i]... v[i], B... b) {
2653      *   return target(p..., f[i](v[i])..., b...);
2654      * }
2655      * }</pre></blockquote>
2656      * <p>
2657      * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
2658      * variable-arity method handle}, even if the original target method handle was.
2659      *
2660      * @param target the method handle to invoke after arguments are filtered
2661      * @param pos the position of the first argument to filter
2662      * @param filters method handles to call initially on filtered arguments
2663      * @return method handle which incorporates the specified argument filtering logic
2664      * @throws NullPointerException if the target is null
2665      *                              or if the {@code filters} array is null
2666      * @throws IllegalArgumentException if a non-null element of {@code filters}
2667      *          does not match a corresponding argument type of target as described above,
2668      *          or if the {@code pos+filters.length} is greater than {@code target.type().parameterCount()},
2669      *          or if the resulting method handle's type would have
2670      *          <a href="MethodHandle.html#maxarity">too many parameters</a>
2671      */
2672     public static
2673     MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {


2745 
2746 MethodHandle ts1 = deepToString.asCollector(String[].class, 1);
2747 assertEquals("[strange]", (String) ts1.invokeExact("strange"));
2748 
2749 MethodHandle ts2 = deepToString.asCollector(String[].class, 2);
2750 assertEquals("[up, down]", (String) ts2.invokeExact("up", "down"));
2751 
2752 MethodHandle ts3 = deepToString.asCollector(String[].class, 3);
2753 MethodHandle ts3_ts2 = collectArguments(ts3, 1, ts2);
2754 assertEquals("[top, [up, down], strange]",
2755              (String) ts3_ts2.invokeExact("top", "up", "down", "strange"));
2756 
2757 MethodHandle ts3_ts2_ts1 = collectArguments(ts3_ts2, 3, ts1);
2758 assertEquals("[top, [up, down], [strange]]",
2759              (String) ts3_ts2_ts1.invokeExact("top", "up", "down", "strange"));
2760 
2761 MethodHandle ts3_ts2_ts3 = collectArguments(ts3_ts2, 1, ts3);
2762 assertEquals("[top, [[up, down, strange], charm], bottom]",
2763              (String) ts3_ts2_ts3.invokeExact("top", "up", "down", "strange", "charm", "bottom"));
2764      * }</pre></blockquote>
2765      * <p> Here is pseudocode for the resulting adapter:










2766      * <blockquote><pre>{@code
2767      * T target(A...,V,C...);
2768      * V filter(B...);
2769      * T adapter(A... a,B... b,C... c) {
2770      *   V v = filter(b...);
2771      *   return target(a...,v,c...);
2772      * }
2773      * // and if the filter has no arguments:
2774      * T target2(A...,V,C...);
2775      * V filter2();
2776      * T adapter2(A... a,C... c) {
2777      *   V v = filter2();
2778      *   return target2(a...,v,c...);
2779      * }
2780      * // and if the filter has a void return:
2781      * T target3(A...,C...);
2782      * void filter3(B...);
2783      * void adapter3(A... a,B... b,C... c) {
2784      *   filter3(b...);
2785      *   return target3(a...,c...);
2786      * }
2787      * }</pre></blockquote>
2788      * <p>
2789      * A collection adapter {@code collectArguments(mh, 0, coll)} is equivalent to
2790      * one which first "folds" the affected arguments, and then drops them, in separate
2791      * steps as follows:
2792      * <blockquote><pre>{@code
2793      * mh = MethodHandles.dropArguments(mh, 1, coll.type().parameterList()); //step 2
2794      * mh = MethodHandles.foldArguments(mh, coll); //step 1
2795      * }</pre></blockquote>
2796      * If the target method handle consumes no arguments besides than the result
2797      * (if any) of the filter {@code coll}, then {@code collectArguments(mh, 0, coll)}
2798      * is equivalent to {@code filterReturnValue(coll, mh)}.
2799      * If the filter method handle {@code coll} consumes one argument and produces
2800      * a non-void result, then {@code collectArguments(mh, N, coll)}
2801      * is equivalent to {@code filterArguments(mh, N, coll)}.
2802      * Other equivalences are possible but would require argument permutation.
2803      * <p>


2859      * If the target returns void, the filter must accept no arguments.
2860      * <p>
2861      * The return type of the filter
2862      * replaces the return type of the target
2863      * in the resulting adapted method handle.
2864      * The argument type of the filter (if any) must be identical to the
2865      * return type of the target.
2866      * <p><b>Example:</b>
2867      * <blockquote><pre>{@code
2868 import static java.lang.invoke.MethodHandles.*;
2869 import static java.lang.invoke.MethodType.*;
2870 ...
2871 MethodHandle cat = lookup().findVirtual(String.class,
2872   "concat", methodType(String.class, String.class));
2873 MethodHandle length = lookup().findVirtual(String.class,
2874   "length", methodType(int.class));
2875 System.out.println((String) cat.invokeExact("x", "y")); // xy
2876 MethodHandle f0 = filterReturnValue(cat, length);
2877 System.out.println((int) f0.invokeExact("x", "y")); // 2
2878      * }</pre></blockquote>
2879      * <p> Here is pseudocode for the resulting adapter:
2880      * <blockquote><pre>{@code
2881      * V target(A...);
2882      * T filter(V);
2883      * T adapter(A... a) {
2884      *   V v = target(a...);
2885      *   return filter(v);




2886      * }
2887      * // and if the target has a void return:
2888      * void target2(A...);
2889      * T filter2();
2890      * T adapter2(A... a) {
2891      *   target2(a...);
2892      *   return filter2();
2893      * }
2894      * // and if the filter has a void return:
2895      * V target3(A...);
2896      * void filter3(V);
2897      * void adapter3(A... a) {
2898      *   V v = target3(a...);
2899      *   filter3(v);
2900      * }
2901      * }</pre></blockquote>
2902      * <p>
2903      * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
2904      * variable-arity method handle}, even if the original target method handle was.
2905      * @param target the method handle to invoke before filtering the return value
2906      * @param filter method handle to call on the return value
2907      * @return method handle which incorporates the specified return value filtering logic
2908      * @throws NullPointerException if either argument is null
2909      * @throws IllegalArgumentException if the argument list of {@code filter}
2910      *          does not match the return type of target as described above
2911      */
2912     public static
2913     MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) {
2914         MethodType targetType = target.type();
2915         MethodType filterType = filter.type();
2916         filterReturnValueChecks(targetType, filterType);
2917         BoundMethodHandle result = target.rebind();
2918         BasicType rtype = BasicType.basicType(filterType.returnType());
2919         LambdaForm lform = result.editor().filterReturnForm(rtype, false);


2962      * that either the combiner or the target does not wish to receive.
2963      * If some of the incoming arguments are destined only for the combiner,
2964      * consider using {@link MethodHandle#asCollector asCollector} instead, since those
2965      * arguments will not need to be live on the stack on entry to the
2966      * target.)
2967      * <p><b>Example:</b>
2968      * <blockquote><pre>{@code
2969 import static java.lang.invoke.MethodHandles.*;
2970 import static java.lang.invoke.MethodType.*;
2971 ...
2972 MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class,
2973   "println", methodType(void.class, String.class))
2974     .bindTo(System.out);
2975 MethodHandle cat = lookup().findVirtual(String.class,
2976   "concat", methodType(String.class, String.class));
2977 assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
2978 MethodHandle catTrace = foldArguments(cat, trace);
2979 // also prints "boo":
2980 assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
2981      * }</pre></blockquote>
2982      * <p> Here is pseudocode for the resulting adapter:








2983      * <blockquote><pre>{@code
2984      * // there are N arguments in A...
2985      * T target(V, A[N]..., B...);
2986      * V combiner(A...);
2987      * T adapter(A... a, B... b) {
2988      *   V v = combiner(a...);
2989      *   return target(v, a..., b...);
2990      * }
2991      * // and if the combiner has a void return:
2992      * T target2(A[N]..., B...);
2993      * void combiner2(A...);
2994      * T adapter2(A... a, B... b) {
2995      *   combiner2(a...);
2996      *   return target2(a..., b...);
2997      * }
2998      * }</pre></blockquote>
2999      * <p>
3000      * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
3001      * variable-arity method handle}, even if the original target method handle was.
3002      * @param target the method handle to invoke after arguments are combined


3023         boolean ok = (targetType.parameterCount() >= afterInsertPos + foldArgs);
3024         if (ok && !(combinerType.parameterList()
3025                     .equals(targetType.parameterList().subList(afterInsertPos,
3026                                                                afterInsertPos + foldArgs))))
3027             ok = false;
3028         if (ok && foldVals != 0 && combinerType.returnType() != targetType.parameterType(foldPos))
3029             ok = false;
3030         if (!ok)
3031             throw misMatchedTypes("target and combiner types", targetType, combinerType);
3032         return rtype;
3033     }
3034 
3035     /**
3036      * Makes a method handle which adapts a target method handle,
3037      * by guarding it with a test, a boolean-valued method handle.
3038      * If the guard fails, a fallback handle is called instead.
3039      * All three method handles must have the same corresponding
3040      * argument and return types, except that the return type
3041      * of the test must be boolean, and the test is allowed
3042      * to have fewer arguments than the other two method handles.
3043      * <p> Here is pseudocode for the resulting adapter:





3044      * <blockquote><pre>{@code
3045      * boolean test(A...);
3046      * T target(A...,B...);
3047      * T fallback(A...,B...);
3048      * T adapter(A... a,B... b) {
3049      *   if (test(a...))
3050      *     return target(a..., b...);
3051      *   else
3052      *     return fallback(a..., b...);
3053      * }
3054      * }</pre></blockquote>
3055      * Note that the test arguments ({@code a...} in the pseudocode) cannot
3056      * be modified by execution of the test, and so are passed unchanged
3057      * from the caller to the target or fallback as appropriate.
3058      * @param test method handle used for test, must return boolean
3059      * @param target method handle to call if test passes
3060      * @param fallback method handle to call if test fails
3061      * @return method handle which incorporates the specified if/then/else logic
3062      * @throws NullPointerException if any argument is null
3063      * @throws IllegalArgumentException if {@code test} does not return boolean,


3085             gtype = test.type();
3086         }
3087         return MethodHandleImpl.makeGuardWithTest(test, target, fallback);
3088     }
3089 
3090     static <T> RuntimeException misMatchedTypes(String what, T t1, T t2) {
3091         return newIllegalArgumentException(what + " must match: " + t1 + " != " + t2);
3092     }
3093 
3094     /**
3095      * Makes a method handle which adapts a target method handle,
3096      * by running it inside an exception handler.
3097      * If the target returns normally, the adapter returns that value.
3098      * If an exception matching the specified type is thrown, the fallback
3099      * handle is called instead on the exception, plus the original arguments.
3100      * <p>
3101      * The target and handler must have the same corresponding
3102      * argument and return types, except that handler may omit trailing arguments
3103      * (similarly to the predicate in {@link #guardWithTest guardWithTest}).
3104      * Also, the handler must have an extra leading parameter of {@code exType} or a supertype.
3105      * <p> Here is pseudocode for the resulting adapter:






3106      * <blockquote><pre>{@code
3107      * T target(A..., B...);
3108      * T handler(ExType, A...);
3109      * T adapter(A... a, B... b) {
3110      *   try {
3111      *     return target(a..., b...);
3112      *   } catch (ExType ex) {
3113      *     return handler(ex, a...);
3114      *   }
3115      * }
3116      * }</pre></blockquote>
3117      * Note that the saved arguments ({@code a...} in the pseudocode) cannot
3118      * be modified by execution of the target, and so are passed unchanged
3119      * from the caller to the handler, if the handler is invoked.
3120      * <p>
3121      * The target and handler must return the same type, even if the handler
3122      * always throws.  (This might happen, for instance, because the handler
3123      * is simulating a {@code finally} clause).
3124      * To create such a throwing handler, compose the handler creation logic
3125      * with {@link #throwException throwException},


3934      * This method is closely related to {@link #foldArguments(MethodHandle, MethodHandle)}, but allows to control the
3935      * position in the parameter list at which folding takes place. The argument controlling this, {@code pos}, is a
3936      * zero-based index. The aforementioned method {@link #foldArguments(MethodHandle, MethodHandle)} assumes position
3937      * 0.
3938      * <p>
3939      * @apiNote Example:
3940      * <blockquote><pre>{@code
3941     import static java.lang.invoke.MethodHandles.*;
3942     import static java.lang.invoke.MethodType.*;
3943     ...
3944     MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class,
3945     "println", methodType(void.class, String.class))
3946     .bindTo(System.out);
3947     MethodHandle cat = lookup().findVirtual(String.class,
3948     "concat", methodType(String.class, String.class));
3949     assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
3950     MethodHandle catTrace = foldArguments(cat, 1, trace);
3951     // also prints "jum":
3952     assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
3953      * }</pre></blockquote>
3954      * <p> Here is pseudocode for the resulting adapter:









3955      * <blockquote><pre>{@code
3956      * // there are N arguments in A...
3957      * T target(Z..., V, A[N]..., B...);
3958      * V combiner(A...);
3959      * T adapter(Z... z, A... a, B... b) {
3960      *   V v = combiner(a...);
3961      *   return target(z..., v, a..., b...);
3962      * }
3963      * // and if the combiner has a void return:
3964      * T target2(Z..., A[N]..., B...);
3965      * void combiner2(A...);
3966      * T adapter2(Z... z, A... a, B... b) {
3967      *   combiner2(a...);
3968      *   return target2(z..., a..., b...);
3969      * }
3970      * }</pre></blockquote>
3971      * <p>
3972      * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
3973      * variable-arity method handle}, even if the original target method handle was.
3974      *




2628      * It is an error if there are elements of {@code filters}
2629      * (null or not)
2630      * which do not correspond to argument positions in the target.
2631      * <p><b>Example:</b>
2632      * <blockquote><pre>{@code
2633 import static java.lang.invoke.MethodHandles.*;
2634 import static java.lang.invoke.MethodType.*;
2635 ...
2636 MethodHandle cat = lookup().findVirtual(String.class,
2637   "concat", methodType(String.class, String.class));
2638 MethodHandle upcase = lookup().findVirtual(String.class,
2639   "toUpperCase", methodType(String.class));
2640 assertEquals("xy", (String) cat.invokeExact("x", "y"));
2641 MethodHandle f0 = filterArguments(cat, 0, upcase);
2642 assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy
2643 MethodHandle f1 = filterArguments(cat, 1, upcase);
2644 assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
2645 MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
2646 assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
2647      * }</pre></blockquote>
2648      * <p>Here is pseudocode for the resulting adapter. In the code, {@code T}
2649      * denotes the return type of both the {@code target} and resulting adapter.
2650      * {@code P}/{@code p} and {@code B}/{@code b} represent the types / values
2651      * of the parameters / arguments that precede / follow the filter position
2652      * {@code pos}, respectively. {@code A[i]}/{@code a[i]} stand for the types /
2653      * values of the filtered parameters / arguments; they also represent the
2654      * return types of the {@code filter[i]} handles. The latter accept arguments
2655      * {@code v[i]} of type {@code V[i]}, which also appear in the signature of
2656      * the resulting adapter.
2657      * <blockquote><pre>{@code
2658      * T target(P... p, A[i]... a[i], B... b);
2659      * A[i] filter[i](V[i]);
2660      * T adapter(P... p, V[i]... v[i], B... b) {
2661      *   return target(p..., filter[i](v[i])..., b...);
2662      * }
2663      * }</pre></blockquote>
2664      * <p>
2665      * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
2666      * variable-arity method handle}, even if the original target method handle was.
2667      *
2668      * @param target the method handle to invoke after arguments are filtered
2669      * @param pos the position of the first argument to filter
2670      * @param filters method handles to call initially on filtered arguments
2671      * @return method handle which incorporates the specified argument filtering logic
2672      * @throws NullPointerException if the target is null
2673      *                              or if the {@code filters} array is null
2674      * @throws IllegalArgumentException if a non-null element of {@code filters}
2675      *          does not match a corresponding argument type of target as described above,
2676      *          or if the {@code pos+filters.length} is greater than {@code target.type().parameterCount()},
2677      *          or if the resulting method handle's type would have
2678      *          <a href="MethodHandle.html#maxarity">too many parameters</a>
2679      */
2680     public static
2681     MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {


2753 
2754 MethodHandle ts1 = deepToString.asCollector(String[].class, 1);
2755 assertEquals("[strange]", (String) ts1.invokeExact("strange"));
2756 
2757 MethodHandle ts2 = deepToString.asCollector(String[].class, 2);
2758 assertEquals("[up, down]", (String) ts2.invokeExact("up", "down"));
2759 
2760 MethodHandle ts3 = deepToString.asCollector(String[].class, 3);
2761 MethodHandle ts3_ts2 = collectArguments(ts3, 1, ts2);
2762 assertEquals("[top, [up, down], strange]",
2763              (String) ts3_ts2.invokeExact("top", "up", "down", "strange"));
2764 
2765 MethodHandle ts3_ts2_ts1 = collectArguments(ts3_ts2, 3, ts1);
2766 assertEquals("[top, [up, down], [strange]]",
2767              (String) ts3_ts2_ts1.invokeExact("top", "up", "down", "strange"));
2768 
2769 MethodHandle ts3_ts2_ts3 = collectArguments(ts3_ts2, 1, ts3);
2770 assertEquals("[top, [[up, down, strange], charm], bottom]",
2771              (String) ts3_ts2_ts3.invokeExact("top", "up", "down", "strange", "charm", "bottom"));
2772      * }</pre></blockquote>
2773      * <p>Here is pseudocode for the resulting adapter. In the code, {@code T}
2774      * represents the return type of the {@code target} and resulting adapter.
2775      * {@code V}/{@code v} stand for the return type and value of the
2776      * {@code filter}, which are also found in the signature and arguments of
2777      * the {@code target}, respectively, unless {@code V} is {@code void}.
2778      * {@code A}/{@code a} and {@code C}/{@code c} represent the parameter types
2779      * and values preceding and following the collection position, {@code pos},
2780      * in the {@code target}'s signature. They also turn up in the resulting
2781      * adapter's signature and arguments, where they surround
2782      * {@code B}/{@code b}, which represent the parameter types and arguments
2783      * to the {@code filter} (if any).
2784      * <blockquote><pre>{@code
2785      * T target(A...,V,C...);
2786      * V filter(B...);
2787      * T adapter(A... a,B... b,C... c) {
2788      *   V v = filter(b...);
2789      *   return target(a...,v,c...);
2790      * }
2791      * // and if the filter has no arguments:
2792      * T target2(A...,V,C...);
2793      * V filter2();
2794      * T adapter2(A... a,C... c) {
2795      *   V v = filter2();
2796      *   return target2(a...,v,c...);
2797      * }
2798      * // and if the filter has a void return:
2799      * T target3(A...,C...);
2800      * void filter3(B...);
2801      * T adapter3(A... a,B... b,C... c) {
2802      *   filter3(b...);
2803      *   return target3(a...,c...);
2804      * }
2805      * }</pre></blockquote>
2806      * <p>
2807      * A collection adapter {@code collectArguments(mh, 0, coll)} is equivalent to
2808      * one which first "folds" the affected arguments, and then drops them, in separate
2809      * steps as follows:
2810      * <blockquote><pre>{@code
2811      * mh = MethodHandles.dropArguments(mh, 1, coll.type().parameterList()); //step 2
2812      * mh = MethodHandles.foldArguments(mh, coll); //step 1
2813      * }</pre></blockquote>
2814      * If the target method handle consumes no arguments besides than the result
2815      * (if any) of the filter {@code coll}, then {@code collectArguments(mh, 0, coll)}
2816      * is equivalent to {@code filterReturnValue(coll, mh)}.
2817      * If the filter method handle {@code coll} consumes one argument and produces
2818      * a non-void result, then {@code collectArguments(mh, N, coll)}
2819      * is equivalent to {@code filterArguments(mh, N, coll)}.
2820      * Other equivalences are possible but would require argument permutation.
2821      * <p>


2877      * If the target returns void, the filter must accept no arguments.
2878      * <p>
2879      * The return type of the filter
2880      * replaces the return type of the target
2881      * in the resulting adapted method handle.
2882      * The argument type of the filter (if any) must be identical to the
2883      * return type of the target.
2884      * <p><b>Example:</b>
2885      * <blockquote><pre>{@code
2886 import static java.lang.invoke.MethodHandles.*;
2887 import static java.lang.invoke.MethodType.*;
2888 ...
2889 MethodHandle cat = lookup().findVirtual(String.class,
2890   "concat", methodType(String.class, String.class));
2891 MethodHandle length = lookup().findVirtual(String.class,
2892   "length", methodType(int.class));
2893 System.out.println((String) cat.invokeExact("x", "y")); // xy
2894 MethodHandle f0 = filterReturnValue(cat, length);
2895 System.out.println((int) f0.invokeExact("x", "y")); // 2
2896      * }</pre></blockquote>
2897      * <p>Here is pseudocode for the resulting adapter. In the code,
2898      * {@code T}/{@code t} represent the result type and value of the
2899      * {@code target}; {@code V}, the result type of the {@code filter}; and
2900      * {@code A}/{@code a}, the types / values of the parameters / arguments
2901      * of the {@code target} as well as the resulting adapter.
2902      * <blockquote><pre>{@code
2903      * T target(A...);
2904      * V filter(T);
2905      * V adapter(A... a) {
2906      *   T t = target(a...);
2907      *   return filter(t);
2908      * }
2909      * // and if the target has a void return:
2910      * void target2(A...);
2911      * V filter2();
2912      * V adapter2(A... a) {
2913      *   target2(a...);
2914      *   return filter2();
2915      * }
2916      * // and if the filter has a void return:
2917      * T target3(A...);
2918      * void filter3(V);
2919      * void adapter3(A... a) {
2920      *   T t = target3(a...);
2921      *   filter3(t);
2922      * }
2923      * }</pre></blockquote>
2924      * <p>
2925      * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
2926      * variable-arity method handle}, even if the original target method handle was.
2927      * @param target the method handle to invoke before filtering the return value
2928      * @param filter method handle to call on the return value
2929      * @return method handle which incorporates the specified return value filtering logic
2930      * @throws NullPointerException if either argument is null
2931      * @throws IllegalArgumentException if the argument list of {@code filter}
2932      *          does not match the return type of target as described above
2933      */
2934     public static
2935     MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) {
2936         MethodType targetType = target.type();
2937         MethodType filterType = filter.type();
2938         filterReturnValueChecks(targetType, filterType);
2939         BoundMethodHandle result = target.rebind();
2940         BasicType rtype = BasicType.basicType(filterType.returnType());
2941         LambdaForm lform = result.editor().filterReturnForm(rtype, false);


2984      * that either the combiner or the target does not wish to receive.
2985      * If some of the incoming arguments are destined only for the combiner,
2986      * consider using {@link MethodHandle#asCollector asCollector} instead, since those
2987      * arguments will not need to be live on the stack on entry to the
2988      * target.)
2989      * <p><b>Example:</b>
2990      * <blockquote><pre>{@code
2991 import static java.lang.invoke.MethodHandles.*;
2992 import static java.lang.invoke.MethodType.*;
2993 ...
2994 MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class,
2995   "println", methodType(void.class, String.class))
2996     .bindTo(System.out);
2997 MethodHandle cat = lookup().findVirtual(String.class,
2998   "concat", methodType(String.class, String.class));
2999 assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
3000 MethodHandle catTrace = foldArguments(cat, trace);
3001 // also prints "boo":
3002 assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
3003      * }</pre></blockquote>
3004      * <p>Here is pseudocode for the resulting adapter. In the code, {@code T}
3005      * represents the result type of the {@code target} and resulting adapter.
3006      * {@code V}/{@code v} represent the type / value of the parameter / argument
3007      * of {@code target} that precedes the folding position; {@code V} also is
3008      * the result type of the {@code combiner}. {@code A}/{@code a} denote the
3009      * types / values of the {@code N} parameters / arguments at the folding
3010      * position. {@code B}/{@code b} represent the types / values of the
3011      * {@code target} parameters / arguments that follow the folded parameters /
3012      * arguments.
3013      * <blockquote><pre>{@code
3014      * // there are N arguments in A...
3015      * T target(V, A[N]..., B...);
3016      * V combiner(A...);
3017      * T adapter(A... a, B... b) {
3018      *   V v = combiner(a...);
3019      *   return target(v, a..., b...);
3020      * }
3021      * // and if the combiner has a void return:
3022      * T target2(A[N]..., B...);
3023      * void combiner2(A...);
3024      * T adapter2(A... a, B... b) {
3025      *   combiner2(a...);
3026      *   return target2(a..., b...);
3027      * }
3028      * }</pre></blockquote>
3029      * <p>
3030      * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
3031      * variable-arity method handle}, even if the original target method handle was.
3032      * @param target the method handle to invoke after arguments are combined


3053         boolean ok = (targetType.parameterCount() >= afterInsertPos + foldArgs);
3054         if (ok && !(combinerType.parameterList()
3055                     .equals(targetType.parameterList().subList(afterInsertPos,
3056                                                                afterInsertPos + foldArgs))))
3057             ok = false;
3058         if (ok && foldVals != 0 && combinerType.returnType() != targetType.parameterType(foldPos))
3059             ok = false;
3060         if (!ok)
3061             throw misMatchedTypes("target and combiner types", targetType, combinerType);
3062         return rtype;
3063     }
3064 
3065     /**
3066      * Makes a method handle which adapts a target method handle,
3067      * by guarding it with a test, a boolean-valued method handle.
3068      * If the guard fails, a fallback handle is called instead.
3069      * All three method handles must have the same corresponding
3070      * argument and return types, except that the return type
3071      * of the test must be boolean, and the test is allowed
3072      * to have fewer arguments than the other two method handles.
3073      * <p>Here is pseudocode for the resulting adapter. In the code, {@code T}
3074      * represents the uniform result type of the three involved handles;
3075      * {@code A}/{@code a}, the types / values of the {@code target}
3076      * parameters / arguments that are consumed by the {@code test}; and
3077      * {@code B}/{@code b}, those types / values of the {@code target}
3078      * parameters / arguments that are not consumed by the {@code test}.
3079      * <blockquote><pre>{@code
3080      * boolean test(A...);
3081      * T target(A...,B...);
3082      * T fallback(A...,B...);
3083      * T adapter(A... a,B... b) {
3084      *   if (test(a...))
3085      *     return target(a..., b...);
3086      *   else
3087      *     return fallback(a..., b...);
3088      * }
3089      * }</pre></blockquote>
3090      * Note that the test arguments ({@code a...} in the pseudocode) cannot
3091      * be modified by execution of the test, and so are passed unchanged
3092      * from the caller to the target or fallback as appropriate.
3093      * @param test method handle used for test, must return boolean
3094      * @param target method handle to call if test passes
3095      * @param fallback method handle to call if test fails
3096      * @return method handle which incorporates the specified if/then/else logic
3097      * @throws NullPointerException if any argument is null
3098      * @throws IllegalArgumentException if {@code test} does not return boolean,


3120             gtype = test.type();
3121         }
3122         return MethodHandleImpl.makeGuardWithTest(test, target, fallback);
3123     }
3124 
3125     static <T> RuntimeException misMatchedTypes(String what, T t1, T t2) {
3126         return newIllegalArgumentException(what + " must match: " + t1 + " != " + t2);
3127     }
3128 
3129     /**
3130      * Makes a method handle which adapts a target method handle,
3131      * by running it inside an exception handler.
3132      * If the target returns normally, the adapter returns that value.
3133      * If an exception matching the specified type is thrown, the fallback
3134      * handle is called instead on the exception, plus the original arguments.
3135      * <p>
3136      * The target and handler must have the same corresponding
3137      * argument and return types, except that handler may omit trailing arguments
3138      * (similarly to the predicate in {@link #guardWithTest guardWithTest}).
3139      * Also, the handler must have an extra leading parameter of {@code exType} or a supertype.
3140      * <p>
3141      * Here is pseudocode for the resulting adapter. In the code, {@code T}
3142      * represents the return type of the {@code target} and {@code handler},
3143      * and correspondingly that of the resulting adapter; {@code A}/{@code a},
3144      * the types and values of arguments to the resulting handle consumed by
3145      * {@code handler}; and {@code B}/{@code b}, those of arguments to the
3146      * resulting handle discarded by {@code handler}.
3147      * <blockquote><pre>{@code
3148      * T target(A..., B...);
3149      * T handler(ExType, A...);
3150      * T adapter(A... a, B... b) {
3151      *   try {
3152      *     return target(a..., b...);
3153      *   } catch (ExType ex) {
3154      *     return handler(ex, a...);
3155      *   }
3156      * }
3157      * }</pre></blockquote>
3158      * Note that the saved arguments ({@code a...} in the pseudocode) cannot
3159      * be modified by execution of the target, and so are passed unchanged
3160      * from the caller to the handler, if the handler is invoked.
3161      * <p>
3162      * The target and handler must return the same type, even if the handler
3163      * always throws.  (This might happen, for instance, because the handler
3164      * is simulating a {@code finally} clause).
3165      * To create such a throwing handler, compose the handler creation logic
3166      * with {@link #throwException throwException},


3975      * This method is closely related to {@link #foldArguments(MethodHandle, MethodHandle)}, but allows to control the
3976      * position in the parameter list at which folding takes place. The argument controlling this, {@code pos}, is a
3977      * zero-based index. The aforementioned method {@link #foldArguments(MethodHandle, MethodHandle)} assumes position
3978      * 0.
3979      * <p>
3980      * @apiNote Example:
3981      * <blockquote><pre>{@code
3982     import static java.lang.invoke.MethodHandles.*;
3983     import static java.lang.invoke.MethodType.*;
3984     ...
3985     MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class,
3986     "println", methodType(void.class, String.class))
3987     .bindTo(System.out);
3988     MethodHandle cat = lookup().findVirtual(String.class,
3989     "concat", methodType(String.class, String.class));
3990     assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
3991     MethodHandle catTrace = foldArguments(cat, 1, trace);
3992     // also prints "jum":
3993     assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
3994      * }</pre></blockquote>
3995      * <p>Here is pseudocode for the resulting adapter. In the code, {@code T}
3996      * represents the result type of the {@code target} and resulting adapter.
3997      * {@code V}/{@code v} represent the type / value of the parameter / argument
3998      * of {@code target} that precedes the folding position; {@code V} also is
3999      * the result type of the {@code combiner}. {@code A}/{@code a} denote the
4000      * types / values of the {@code N} parameters / arguments at the folding
4001      * position. {@code Z}/{@code z} and {@code B}/{@code b} represent the types
4002      * / values of the {@code target} parameters / arguments that precede and
4003      * follow the folded parameters / arguments starting at {@code pos},
4004      * respectively.
4005      * <blockquote><pre>{@code
4006      * // there are N arguments in A...
4007      * T target(Z..., V, A[N]..., B...);
4008      * V combiner(A...);
4009      * T adapter(Z... z, A... a, B... b) {
4010      *   V v = combiner(a...);
4011      *   return target(z..., v, a..., b...);
4012      * }
4013      * // and if the combiner has a void return:
4014      * T target2(Z..., A[N]..., B...);
4015      * void combiner2(A...);
4016      * T adapter2(Z... z, A... a, B... b) {
4017      *   combiner2(a...);
4018      *   return target2(z..., a..., b...);
4019      * }
4020      * }</pre></blockquote>
4021      * <p>
4022      * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
4023      * variable-arity method handle}, even if the original target method handle was.
4024      *


< prev index next >