2635 * as if by the {@code astore} bytecode.
2636 * The type of the method handle will have a void return type.
2637 * Its last argument will be the array's element type.
2638 * The first and second arguments will be the array type and int.
2639 *
2640 * <p> When the returned method handle is invoked,
2641 * the array reference and array index are checked.
2642 * A {@code NullPointerException} will be thrown if the array reference
2643 * is {@code null} and an {@code ArrayIndexOutOfBoundsException} will be
2644 * thrown if the index is negative or if it is greater than or equal to
2645 * the length of the array.
2646 *
2647 * @param arrayClass the class of an array
2648 * @return a method handle which can store values into the array type
2649 * @throws NullPointerException if the argument is null
2650 * @throws IllegalArgumentException if arrayClass is not an array type
2651 * @jvms 6.5 {@code aastore} Instruction
2652 */
2653 public static
2654 MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
2655 if (arrayClass.isValue()) {
2656 throw new UnsupportedOperationException();
2657 }
2658 return MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.SET);
2659 }
2660
2661 /**
2662 * Produces a VarHandle giving access to elements of an array of type
2663 * {@code arrayClass}. The VarHandle's variable type is the component type
2664 * of {@code arrayClass} and the list of coordinate types is
2665 * {@code (arrayClass, int)}, where the {@code int} coordinate type
2666 * corresponds to an argument that is an index into an array.
2667 * <p>
2668 * Certain access modes of the returned VarHandle are unsupported under
2669 * the following conditions:
2670 * <ul>
2671 * <li>if the component type is anything other than {@code byte},
2672 * {@code short}, {@code char}, {@code int}, {@code long},
2673 * {@code float}, or {@code double} then numeric atomic update access
2674 * modes are unsupported.
2675 * <li>if the field type is anything other than {@code boolean},
3412 /**
3413 * Produces a constant method handle of the requested return type which
3414 * returns the default value for that type every time it is invoked.
3415 * The resulting constant method handle will have no side effects.
3416 * <p>The returned method handle is equivalent to {@code empty(methodType(type))}.
3417 * It is also equivalent to {@code explicitCastArguments(constant(Object.class, null), methodType(type))},
3418 * since {@code explicitCastArguments} converts {@code null} to default values.
3419 * @param type the expected return type of the desired method handle
3420 * @return a constant method handle that takes no arguments
3421 * and returns the default value of the given type (or void, if the type is void)
3422 * @throws NullPointerException if the argument is null
3423 * @see MethodHandles#constant
3424 * @see MethodHandles#empty
3425 * @see MethodHandles#explicitCastArguments
3426 * @since 9
3427 */
3428 public static MethodHandle zero(Class<?> type) {
3429 Objects.requireNonNull(type);
3430 if (type.isPrimitive()) {
3431 return zero(Wrapper.forPrimitiveType(type), type);
3432 } else if (type.isValue()) {
3433 throw new UnsupportedOperationException();
3434 } else {
3435 return zero(Wrapper.OBJECT, type);
3436 }
3437 }
3438
3439 private static MethodHandle identityOrVoid(Class<?> type) {
3440 return type == void.class ? zero(type) : identity(type);
3441 }
3442
3443 /**
3444 * Produces a method handle of the requested type which ignores any arguments, does nothing,
3445 * and returns a suitable default depending on the return type.
3446 * That is, it returns a zero primitive value, a {@code null}, or {@code void}.
3447 * <p>The returned method handle is equivalent to
3448 * {@code dropArguments(zero(type.returnType()), 0, type.parameterList())}.
3449 *
3450 * @apiNote Given a predicate and target, a useful "if-then" construct can be produced as
3451 * {@code guardWithTest(pred, target, empty(target.type())}.
3452 * @param type the type of the desired method handle
|
2635 * as if by the {@code astore} bytecode.
2636 * The type of the method handle will have a void return type.
2637 * Its last argument will be the array's element type.
2638 * The first and second arguments will be the array type and int.
2639 *
2640 * <p> When the returned method handle is invoked,
2641 * the array reference and array index are checked.
2642 * A {@code NullPointerException} will be thrown if the array reference
2643 * is {@code null} and an {@code ArrayIndexOutOfBoundsException} will be
2644 * thrown if the index is negative or if it is greater than or equal to
2645 * the length of the array.
2646 *
2647 * @param arrayClass the class of an array
2648 * @return a method handle which can store values into the array type
2649 * @throws NullPointerException if the argument is null
2650 * @throws IllegalArgumentException if arrayClass is not an array type
2651 * @jvms 6.5 {@code aastore} Instruction
2652 */
2653 public static
2654 MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
2655 if (arrayClass.isInlineClass()) {
2656 throw new UnsupportedOperationException();
2657 }
2658 return MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.SET);
2659 }
2660
2661 /**
2662 * Produces a VarHandle giving access to elements of an array of type
2663 * {@code arrayClass}. The VarHandle's variable type is the component type
2664 * of {@code arrayClass} and the list of coordinate types is
2665 * {@code (arrayClass, int)}, where the {@code int} coordinate type
2666 * corresponds to an argument that is an index into an array.
2667 * <p>
2668 * Certain access modes of the returned VarHandle are unsupported under
2669 * the following conditions:
2670 * <ul>
2671 * <li>if the component type is anything other than {@code byte},
2672 * {@code short}, {@code char}, {@code int}, {@code long},
2673 * {@code float}, or {@code double} then numeric atomic update access
2674 * modes are unsupported.
2675 * <li>if the field type is anything other than {@code boolean},
3412 /**
3413 * Produces a constant method handle of the requested return type which
3414 * returns the default value for that type every time it is invoked.
3415 * The resulting constant method handle will have no side effects.
3416 * <p>The returned method handle is equivalent to {@code empty(methodType(type))}.
3417 * It is also equivalent to {@code explicitCastArguments(constant(Object.class, null), methodType(type))},
3418 * since {@code explicitCastArguments} converts {@code null} to default values.
3419 * @param type the expected return type of the desired method handle
3420 * @return a constant method handle that takes no arguments
3421 * and returns the default value of the given type (or void, if the type is void)
3422 * @throws NullPointerException if the argument is null
3423 * @see MethodHandles#constant
3424 * @see MethodHandles#empty
3425 * @see MethodHandles#explicitCastArguments
3426 * @since 9
3427 */
3428 public static MethodHandle zero(Class<?> type) {
3429 Objects.requireNonNull(type);
3430 if (type.isPrimitive()) {
3431 return zero(Wrapper.forPrimitiveType(type), type);
3432 } else if (type.isInlineClass()) {
3433 throw new UnsupportedOperationException();
3434 } else {
3435 return zero(Wrapper.OBJECT, type);
3436 }
3437 }
3438
3439 private static MethodHandle identityOrVoid(Class<?> type) {
3440 return type == void.class ? zero(type) : identity(type);
3441 }
3442
3443 /**
3444 * Produces a method handle of the requested type which ignores any arguments, does nothing,
3445 * and returns a suitable default depending on the return type.
3446 * That is, it returns a zero primitive value, a {@code null}, or {@code void}.
3447 * <p>The returned method handle is equivalent to
3448 * {@code dropArguments(zero(type.returnType()), 0, type.parameterList())}.
3449 *
3450 * @apiNote Given a predicate and target, a useful "if-then" construct can be produced as
3451 * {@code guardWithTest(pred, target, empty(target.type())}.
3452 * @param type the type of the desired method handle
|