2786 * If the returned method handle is invoked, the constructor's class will
2787 * be initialized, if it has not already been initialized.
2788 * <p><b>Example:</b>
2789 * {@snippet lang="java" :
2790 import static java.lang.invoke.MethodHandles.*;
2791 import static java.lang.invoke.MethodType.*;
2792 ...
2793 MethodHandle MH_newArrayList = publicLookup().findConstructor(
2794 ArrayList.class, methodType(void.class, Collection.class));
2795 Collection orig = Arrays.asList("x", "y");
2796 Collection copy = (ArrayList) MH_newArrayList.invokeExact(orig);
2797 assert(orig != copy);
2798 assertEquals(orig, copy);
2799 // a variable-arity constructor:
2800 MethodHandle MH_newProcessBuilder = publicLookup().findConstructor(
2801 ProcessBuilder.class, methodType(void.class, String[].class));
2802 ProcessBuilder pb = (ProcessBuilder)
2803 MH_newProcessBuilder.invoke("x", "y", "z");
2804 assertEquals("[x, y, z]", pb.command().toString());
2805 * }
2806 * @param refc the class or interface from which the method is accessed
2807 * @param type the type of the method, with the receiver argument omitted, and a void return type
2808 * @return the desired method handle
2809 * @throws NoSuchMethodException if the constructor does not exist
2810 * @throws IllegalAccessException if access checking fails
2811 * or if the method's variable arity modifier bit
2812 * is set and {@code asVarargsCollector} fails
2813 * @throws SecurityException if a security manager is present and it
2814 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
2815 * @throws NullPointerException if any argument is null
2816 */
2817 public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
2818 if (refc.isArray()) {
2819 throw new NoSuchMethodException("no constructor for array class: " + refc.getName());
2820 }
2821 String name = ConstantDescs.INIT_NAME;
2822 MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type);
2823 return getDirectConstructor(refc, ctor);
2824 }
2825
2826 /**
2827 * Looks up a class by name from the lookup context defined by this {@code Lookup} object,
2828 * <a href="MethodHandles.Lookup.html#equiv">as if resolved</a> by an {@code ldc} instruction.
2829 * Such a resolution, as specified in JVMS {@jvms 5.4.3.1}, attempts to locate and load the class,
2830 * and then determines whether the class is accessible to this lookup object.
2831 * <p>
2832 * For a class or an interface, the name is the {@linkplain ClassLoader##binary-name binary name}.
2833 * For an array class of {@code n} dimensions, the name begins with {@code n} occurrences
2834 * of {@code '['} and followed by the element type as encoded in the
2835 * {@linkplain Class##nameFormat table} specified in {@link Class#getName}.
2836 * <p>
2837 * The lookup context here is determined by the {@linkplain #lookupClass() lookup class},
2838 * its class loader, and the {@linkplain #lookupModes() lookup modes}.
2839 *
2840 * @param targetName the {@linkplain ClassLoader##binary-name binary name} of the class
4069 final boolean doRestrict = false;
4070 final boolean checkSecurity = true;
4071 return getDirectMethodCommon(REF_invokeSpecial, refc, method, checkSecurity, doRestrict, callerLookup);
4072 }
4073 /** Check access and get the requested method, eliding security manager checks. */
4074 private MethodHandle getDirectMethodNoSecurityManager(byte refKind, Class<?> refc, MemberName method, Lookup callerLookup) throws IllegalAccessException {
4075 final boolean doRestrict = true;
4076 final boolean checkSecurity = false; // not needed for reflection or for linking CONSTANT_MH constants
4077 return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerLookup);
4078 }
4079 /** Common code for all methods; do not call directly except from immediately above. */
4080 private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
4081 boolean checkSecurity,
4082 boolean doRestrict,
4083 Lookup boundCaller) throws IllegalAccessException {
4084 checkMethod(refKind, refc, method);
4085 // Optionally check with the security manager; this isn't needed for unreflect* calls.
4086 if (checkSecurity)
4087 checkSecurityManager(refc, method);
4088 assert(!method.isMethodHandleInvoke());
4089
4090 if (refKind == REF_invokeSpecial &&
4091 refc != lookupClass() &&
4092 !refc.isInterface() && !lookupClass().isInterface() &&
4093 refc != lookupClass().getSuperclass() &&
4094 refc.isAssignableFrom(lookupClass())) {
4095 assert(!method.getName().equals(ConstantDescs.INIT_NAME)); // not this code path
4096
4097 // Per JVMS 6.5, desc. of invokespecial instruction:
4098 // If the method is in a superclass of the LC,
4099 // and if our original search was above LC.super,
4100 // repeat the search (symbolic lookup) from LC.super
4101 // and continue with the direct superclass of that class,
4102 // and so forth, until a match is found or no further superclasses exist.
4103 // FIXME: MemberName.resolve should handle this instead.
4104 Class<?> refcAsSuper = lookupClass();
4105 MemberName m2;
4106 do {
4107 refcAsSuper = refcAsSuper.getSuperclass();
4108 m2 = new MemberName(refcAsSuper,
4109 method.getName(),
5169 }
5170
5171 /**
5172 * Produces a constant method handle of the requested return type which
5173 * returns the default value for that type every time it is invoked.
5174 * The resulting constant method handle will have no side effects.
5175 * <p>The returned method handle is equivalent to {@code empty(methodType(type))}.
5176 * It is also equivalent to {@code explicitCastArguments(constant(Object.class, null), methodType(type))},
5177 * since {@code explicitCastArguments} converts {@code null} to default values.
5178 * @param type the expected return type of the desired method handle
5179 * @return a constant method handle that takes no arguments
5180 * and returns the default value of the given type (or void, if the type is void)
5181 * @throws NullPointerException if the argument is null
5182 * @see MethodHandles#constant
5183 * @see MethodHandles#empty
5184 * @see MethodHandles#explicitCastArguments
5185 * @since 9
5186 */
5187 public static MethodHandle zero(Class<?> type) {
5188 Objects.requireNonNull(type);
5189 return type.isPrimitive() ? zero(Wrapper.forPrimitiveType(type), type) : zero(Wrapper.OBJECT, type);
5190 }
5191
5192 private static MethodHandle identityOrVoid(Class<?> type) {
5193 return type == void.class ? zero(type) : identity(type);
5194 }
5195
5196 /**
5197 * Produces a method handle of the requested type which ignores any arguments, does nothing,
5198 * and returns a suitable default depending on the return type.
5199 * That is, it returns a zero primitive value, a {@code null}, or {@code void}.
5200 * <p>The returned method handle is equivalent to
5201 * {@code dropArguments(zero(type.returnType()), 0, type.parameterList())}.
5202 *
5203 * @apiNote Given a predicate and target, a useful "if-then" construct can be produced as
5204 * {@code guardWithTest(pred, target, empty(target.type())}.
5205 * @param type the type of the desired method handle
5206 * @return a constant method handle of the given type, which returns a default value of the given return type
5207 * @throws NullPointerException if the argument is null
5208 * @see MethodHandles#zero
5209 * @see MethodHandles#constant
|
2786 * If the returned method handle is invoked, the constructor's class will
2787 * be initialized, if it has not already been initialized.
2788 * <p><b>Example:</b>
2789 * {@snippet lang="java" :
2790 import static java.lang.invoke.MethodHandles.*;
2791 import static java.lang.invoke.MethodType.*;
2792 ...
2793 MethodHandle MH_newArrayList = publicLookup().findConstructor(
2794 ArrayList.class, methodType(void.class, Collection.class));
2795 Collection orig = Arrays.asList("x", "y");
2796 Collection copy = (ArrayList) MH_newArrayList.invokeExact(orig);
2797 assert(orig != copy);
2798 assertEquals(orig, copy);
2799 // a variable-arity constructor:
2800 MethodHandle MH_newProcessBuilder = publicLookup().findConstructor(
2801 ProcessBuilder.class, methodType(void.class, String[].class));
2802 ProcessBuilder pb = (ProcessBuilder)
2803 MH_newProcessBuilder.invoke("x", "y", "z");
2804 assertEquals("[x, y, z]", pb.command().toString());
2805 * }
2806 *
2807 *
2808 * @param refc the class or interface from which the method is accessed
2809 * @param type the type of the method, with the receiver argument omitted, and a void return type
2810 * @return the desired method handle
2811 * @throws NoSuchMethodException if the constructor does not exist
2812 * @throws IllegalAccessException if access checking fails
2813 * or if the method's variable arity modifier bit
2814 * is set and {@code asVarargsCollector} fails
2815 * @throws SecurityException if a security manager is present and it
2816 * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
2817 * @throws NullPointerException if any argument is null
2818 */
2819 public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
2820 if (refc.isArray()) {
2821 throw new NoSuchMethodException("no constructor for array class: " + refc.getName());
2822 }
2823 if (type.returnType() != void.class) {
2824 throw new NoSuchMethodException("Constructors must have void return type: " + refc.getName());
2825 }
2826 String name = ConstantDescs.INIT_NAME;
2827 MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type);
2828 return getDirectConstructor(refc, ctor);
2829 }
2830
2831 /**
2832 * Looks up a class by name from the lookup context defined by this {@code Lookup} object,
2833 * <a href="MethodHandles.Lookup.html#equiv">as if resolved</a> by an {@code ldc} instruction.
2834 * Such a resolution, as specified in JVMS {@jvms 5.4.3.1}, attempts to locate and load the class,
2835 * and then determines whether the class is accessible to this lookup object.
2836 * <p>
2837 * For a class or an interface, the name is the {@linkplain ClassLoader##binary-name binary name}.
2838 * For an array class of {@code n} dimensions, the name begins with {@code n} occurrences
2839 * of {@code '['} and followed by the element type as encoded in the
2840 * {@linkplain Class##nameFormat table} specified in {@link Class#getName}.
2841 * <p>
2842 * The lookup context here is determined by the {@linkplain #lookupClass() lookup class},
2843 * its class loader, and the {@linkplain #lookupModes() lookup modes}.
2844 *
2845 * @param targetName the {@linkplain ClassLoader##binary-name binary name} of the class
4074 final boolean doRestrict = false;
4075 final boolean checkSecurity = true;
4076 return getDirectMethodCommon(REF_invokeSpecial, refc, method, checkSecurity, doRestrict, callerLookup);
4077 }
4078 /** Check access and get the requested method, eliding security manager checks. */
4079 private MethodHandle getDirectMethodNoSecurityManager(byte refKind, Class<?> refc, MemberName method, Lookup callerLookup) throws IllegalAccessException {
4080 final boolean doRestrict = true;
4081 final boolean checkSecurity = false; // not needed for reflection or for linking CONSTANT_MH constants
4082 return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerLookup);
4083 }
4084 /** Common code for all methods; do not call directly except from immediately above. */
4085 private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
4086 boolean checkSecurity,
4087 boolean doRestrict,
4088 Lookup boundCaller) throws IllegalAccessException {
4089 checkMethod(refKind, refc, method);
4090 // Optionally check with the security manager; this isn't needed for unreflect* calls.
4091 if (checkSecurity)
4092 checkSecurityManager(refc, method);
4093 assert(!method.isMethodHandleInvoke());
4094 if (refKind == REF_invokeSpecial &&
4095 refc != lookupClass() &&
4096 !refc.isInterface() && !lookupClass().isInterface() &&
4097 refc != lookupClass().getSuperclass() &&
4098 refc.isAssignableFrom(lookupClass())) {
4099 assert(!method.getName().equals(ConstantDescs.INIT_NAME)); // not this code path
4100
4101 // Per JVMS 6.5, desc. of invokespecial instruction:
4102 // If the method is in a superclass of the LC,
4103 // and if our original search was above LC.super,
4104 // repeat the search (symbolic lookup) from LC.super
4105 // and continue with the direct superclass of that class,
4106 // and so forth, until a match is found or no further superclasses exist.
4107 // FIXME: MemberName.resolve should handle this instead.
4108 Class<?> refcAsSuper = lookupClass();
4109 MemberName m2;
4110 do {
4111 refcAsSuper = refcAsSuper.getSuperclass();
4112 m2 = new MemberName(refcAsSuper,
4113 method.getName(),
5173 }
5174
5175 /**
5176 * Produces a constant method handle of the requested return type which
5177 * returns the default value for that type every time it is invoked.
5178 * The resulting constant method handle will have no side effects.
5179 * <p>The returned method handle is equivalent to {@code empty(methodType(type))}.
5180 * It is also equivalent to {@code explicitCastArguments(constant(Object.class, null), methodType(type))},
5181 * since {@code explicitCastArguments} converts {@code null} to default values.
5182 * @param type the expected return type of the desired method handle
5183 * @return a constant method handle that takes no arguments
5184 * and returns the default value of the given type (or void, if the type is void)
5185 * @throws NullPointerException if the argument is null
5186 * @see MethodHandles#constant
5187 * @see MethodHandles#empty
5188 * @see MethodHandles#explicitCastArguments
5189 * @since 9
5190 */
5191 public static MethodHandle zero(Class<?> type) {
5192 Objects.requireNonNull(type);
5193 if (type.isPrimitive()) {
5194 return zero(Wrapper.forPrimitiveType(type), type);
5195 } else {
5196 return zero(Wrapper.OBJECT, type);
5197 }
5198 }
5199
5200 private static MethodHandle identityOrVoid(Class<?> type) {
5201 return type == void.class ? zero(type) : identity(type);
5202 }
5203
5204 /**
5205 * Produces a method handle of the requested type which ignores any arguments, does nothing,
5206 * and returns a suitable default depending on the return type.
5207 * That is, it returns a zero primitive value, a {@code null}, or {@code void}.
5208 * <p>The returned method handle is equivalent to
5209 * {@code dropArguments(zero(type.returnType()), 0, type.parameterList())}.
5210 *
5211 * @apiNote Given a predicate and target, a useful "if-then" construct can be produced as
5212 * {@code guardWithTest(pred, target, empty(target.type())}.
5213 * @param type the type of the desired method handle
5214 * @return a constant method handle of the given type, which returns a default value of the given return type
5215 * @throws NullPointerException if the argument is null
5216 * @see MethodHandles#zero
5217 * @see MethodHandles#constant
|