Share via


MethodHandles.TryFinally(MethodHandle, MethodHandle) Method

Definition

Makes a method handle that adapts a target method handle by wrapping it in a try-finally block.

[Android.Runtime.Register("tryFinally", "(Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle;", "", ApiSince=33)]
public static Java.Lang.Invoke.MethodHandle? TryFinally (Java.Lang.Invoke.MethodHandle? target, Java.Lang.Invoke.MethodHandle? cleanup);
[<Android.Runtime.Register("tryFinally", "(Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle;", "", ApiSince=33)>]
static member TryFinally : Java.Lang.Invoke.MethodHandle * Java.Lang.Invoke.MethodHandle -> Java.Lang.Invoke.MethodHandle

Parameters

target
MethodHandle

the handle whose execution is to be wrapped in a try block.

cleanup
MethodHandle

the handle that is invoked in the finally block.

Returns

a method handle embodying the try-finally block composed of the two arguments.

Attributes

Remarks

Makes a method handle that adapts a target method handle by wrapping it in a try-finally block. Another method handle, cleanup, represents the functionality of the finally block. Any exception thrown during the execution of the target handle will be passed to the cleanup handle. The exception will be rethrown, unless cleanup handle throws an exception first. The value returned from the cleanup handle's execution will be the result of the execution of the try-finally handle.

The cleanup handle will be passed one or two additional leading arguments. The first is the exception thrown during the execution of the target handle, or null if no exception was thrown. The second is the result of the execution of the target handle, or, if it throws an exception, a null, zero, or false value of the required type is supplied as a placeholder. The second argument is not present if the target handle has a void return type. (Note that, except for argument type conversions, combinators represent void values in parameter lists by omitting the corresponding paradoxical arguments, not by inserting null or zero values.)

The target and cleanup handles must have the same corresponding argument and return types, except that the cleanup handle may omit trailing arguments. Also, the cleanup handle must have one or two extra leading parameters:<ul> <li>a Throwable, which will carry the exception thrown by the target handle (if any); and <li>a parameter of the same type as the return type of both target and cleanup, which will carry the result from the execution of the target handle. This parameter is not present if the target returns void. </ul>

The pseudocode for the resulting adapter looks as follows. In the code, V represents the result type of the try/finally construct; A/a, the types and values of arguments to the resulting handle consumed by the cleanup; and B/b, those of arguments to the resulting handle discarded by the cleanup. <blockquote>

{@code
            V target(A..., B...);
            V cleanup(Throwable, V, A...);
            V adapter(A... a, B... b) {
              V result = (zero value for V);
              Throwable throwable = null;
              try {
                result = target(a..., b...);
              } catch (Throwable t) {
                throwable = t;
                throw t;
              } finally {
                result = cleanup(throwable, result, a...);
              }
              return result;
            }
            }

</blockquote>

Note that the saved arguments (a... in the pseudocode) cannot be modified by execution of the target, and so are passed unchanged from the caller to the cleanup, if it is invoked.

The target and cleanup must return the same type, even if the cleanup always throws. To create such a throwing cleanup, compose the cleanup logic with #throwException throwException, in order to create a method handle of the correct return type.

Note that tryFinally never converts exceptions into normal returns. In rare cases where exceptions must be converted in that way, first wrap the target with #catchException(MethodHandle, Class, MethodHandle) to capture an outgoing exception, and then wrap with tryFinally.

It is recommended that the first parameter type of cleanup be declared Throwable rather than a narrower subtype. This ensures cleanup will always be invoked with whatever exception that target throws. Declaring a narrower type may result in a ClassCastException being thrown by the try-finally handle if the type of the exception thrown by target is not assignable to the first parameter type of cleanup. Note that various exception types of VirtualMachineError, LinkageError, and RuntimeException can in principle be thrown by almost any kind of Java code, and a finally clause that catches (say) only IOException would mask any of the others behind a ClassCastException.

Added in 9.

Java documentation for java.lang.invoke.MethodHandles.tryFinally(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle).

Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.

Applies to