提交 26aa37dc 编写于 作者: D darcy

8019357: Fix doclint warnings in java.lang.invoke

Reviewed-by: jrose
上级 325ecc06
/* /*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -29,21 +29,45 @@ package java.lang.invoke; ...@@ -29,21 +29,45 @@ package java.lang.invoke;
* LambdaConversionException * LambdaConversionException
*/ */
public class LambdaConversionException extends Exception { public class LambdaConversionException extends Exception {
/**
* Constructs a {@code LambdaConversionException}.
*/
public LambdaConversionException() { public LambdaConversionException() {
} }
/**
* Constructs a {@code LambdaConversionException} with a message.
* @param message the detail message
*/
public LambdaConversionException(String message) { public LambdaConversionException(String message) {
super(message); super(message);
} }
/**
* Constructs a {@code LambdaConversionException} with a message and cause.
* @param message the detail message
* @param cause the cause
*/
public LambdaConversionException(String message, Throwable cause) { public LambdaConversionException(String message, Throwable cause) {
super(message, cause); super(message, cause);
} }
/**
* Constructs a {@code LambdaConversionException} with a cause.
* @param cause the cause
*/
public LambdaConversionException(Throwable cause) { public LambdaConversionException(Throwable cause) {
super(cause); super(cause);
} }
/**
* Constructs a {@code LambdaConversionException} with a message,
* cause, and other settings.
* @param message the detail message
* @param cause the cause
* @param enableSuppression whether or not suppressed exceptions are enabled
* @param writableStackTrace whether or not the stack trace is writable
*/
public LambdaConversionException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { public LambdaConversionException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace); super(message, cause, enableSuppression, writableStackTrace);
} }
......
...@@ -111,7 +111,7 @@ package java.lang.invoke; ...@@ -111,7 +111,7 @@ package java.lang.invoke;
* done on return type, while a strict version is applied to arguments. * done on return type, while a strict version is applied to arguments.
* *
* <p>A type Q is considered adaptable to S as follows: * <p>A type Q is considered adaptable to S as follows:
* <table> * <table summary="adaptable types">
* <tr><th>Q</th><th>S</th><th>Link-time checks</th><th>Capture-time checks</th></tr> * <tr><th>Q</th><th>S</th><th>Link-time checks</th><th>Capture-time checks</th></tr>
* <tr> * <tr>
* <td>Primitive</td><td>Primitive</td> * <td>Primitive</td><td>Primitive</td>
...@@ -155,7 +155,7 @@ public class LambdaMetafactory { ...@@ -155,7 +155,7 @@ public class LambdaMetafactory {
private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0]; private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
/** /**
* Standard meta-factory for conversion of lambda expressions or method references to functional interfaces. * Standard meta-factory for conversion of lambda expressions or method references to functional interfaces.
* *
* @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges * @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges
...@@ -174,7 +174,7 @@ public class LambdaMetafactory { ...@@ -174,7 +174,7 @@ public class LambdaMetafactory {
* @param instantiatedMethodType The signature of the primary functional interface method after type variables * @param instantiatedMethodType The signature of the primary functional interface method after type variables
* are substituted with their instantiation from the capture site * are substituted with their instantiation from the capture site
* @return a CallSite, which, when invoked, will return an instance of the functional interface * @return a CallSite, which, when invoked, will return an instance of the functional interface
* @throws ReflectiveOperationException * @throws ReflectiveOperationException if the caller is not able to reconstruct one of the method handles
* @throws LambdaConversionException If any of the meta-factory protocol invariants are violated * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
*/ */
public static CallSite metaFactory(MethodHandles.Lookup caller, public static CallSite metaFactory(MethodHandles.Lookup caller,
...@@ -226,7 +226,7 @@ public class LambdaMetafactory { ...@@ -226,7 +226,7 @@ public class LambdaMetafactory {
* the first argument in the invocation signature will correspond to the receiver. * the first argument in the invocation signature will correspond to the receiver.
* @param args argument to pass, flags, marker interface count, and marker interfaces as described above * @param args argument to pass, flags, marker interface count, and marker interfaces as described above
* @return a CallSite, which, when invoked, will return an instance of the functional interface * @return a CallSite, which, when invoked, will return an instance of the functional interface
* @throws ReflectiveOperationException * @throws ReflectiveOperationException if the caller is not able to reconstruct one of the method handles
* @throws LambdaConversionException If any of the meta-factory protocol invariants are violated * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
*/ */
public static CallSite altMetaFactory(MethodHandles.Lookup caller, public static CallSite altMetaFactory(MethodHandles.Lookup caller,
......
...@@ -44,7 +44,7 @@ import java.util.logging.Logger; ...@@ -44,7 +44,7 @@ import java.util.logging.Logger;
* {@linkplain java.lang.invoke.MethodHandles#dropArguments deletion}, * {@linkplain java.lang.invoke.MethodHandles#dropArguments deletion},
* and {@linkplain java.lang.invoke.MethodHandles#filterArguments substitution}. * and {@linkplain java.lang.invoke.MethodHandles#filterArguments substitution}.
* *
* <h3>Method handle contents</h3> * <h1>Method handle contents</h1>
* Method handles are dynamically and strongly typed according to their parameter and return types. * Method handles are dynamically and strongly typed according to their parameter and return types.
* They are not distinguished by the name or the defining class of their underlying methods. * They are not distinguished by the name or the defining class of their underlying methods.
* A method handle must be invoked using a symbolic type descriptor which matches * A method handle must be invoked using a symbolic type descriptor which matches
...@@ -81,7 +81,7 @@ import java.util.logging.Logger; ...@@ -81,7 +81,7 @@ import java.util.logging.Logger;
* from its specific class, as the method handle class hierarchy (if any) * from its specific class, as the method handle class hierarchy (if any)
* may change from time to time or across implementations from different vendors. * may change from time to time or across implementations from different vendors.
* *
* <h3>Method handle compilation</h3> * <h1>Method handle compilation</h1>
* A Java method call expression naming {@code invokeExact} or {@code invoke} * A Java method call expression naming {@code invokeExact} or {@code invoke}
* can invoke a method handle from Java source code. * can invoke a method handle from Java source code.
* From the viewpoint of source code, these methods can take any arguments * From the viewpoint of source code, these methods can take any arguments
...@@ -111,7 +111,7 @@ import java.util.logging.Logger; ...@@ -111,7 +111,7 @@ import java.util.logging.Logger;
* The ambiguity with the type {@code Void} is harmless, since there are no references of type * The ambiguity with the type {@code Void} is harmless, since there are no references of type
* {@code Void} except the null reference. * {@code Void} except the null reference.
* *
* <h3>Method handle invocation</h3> * <h1>Method handle invocation</h1>
* The first time a {@code invokevirtual} instruction is executed * The first time a {@code invokevirtual} instruction is executed
* it is linked, by symbolically resolving the names in the instruction * it is linked, by symbolically resolving the names in the instruction
* and verifying that the method call is statically legal. * and verifying that the method call is statically legal.
...@@ -154,7 +154,7 @@ import java.util.logging.Logger; ...@@ -154,7 +154,7 @@ import java.util.logging.Logger;
* (<em>Note:</em> The adjusted method handle {@code M2} is not directly observable, * (<em>Note:</em> The adjusted method handle {@code M2} is not directly observable,
* and implementations are therefore not required to materialize it.) * and implementations are therefore not required to materialize it.)
* *
* <h3>Invocation checking</h3> * <h1>Invocation checking</h1>
* In typical programs, method handle type matching will usually succeed. * In typical programs, method handle type matching will usually succeed.
* But if a match fails, the JVM will throw a {@link WrongMethodTypeException}, * But if a match fails, the JVM will throw a {@link WrongMethodTypeException},
* either directly (in the case of {@code invokeExact}) or indirectly as if * either directly (in the case of {@code invokeExact}) or indirectly as if
...@@ -195,7 +195,7 @@ import java.util.logging.Logger; ...@@ -195,7 +195,7 @@ import java.util.logging.Logger;
* They should not be passed to untrusted code unless their use from * They should not be passed to untrusted code unless their use from
* the untrusted code would be harmless. * the untrusted code would be harmless.
* *
* <h3>Method handle creation</h3> * <h1>Method handle creation</h1>
* Java code can create a method handle that directly accesses * Java code can create a method handle that directly accesses
* any method, constructor, or field that is accessible to that code. * any method, constructor, or field that is accessible to that code.
* This is done via a reflective, capability-based API called * This is done via a reflective, capability-based API called
...@@ -249,7 +249,7 @@ import java.util.logging.Logger; ...@@ -249,7 +249,7 @@ import java.util.logging.Logger;
* receiver type. Such a method handle simulates the effect of * receiver type. Such a method handle simulates the effect of
* an {@code invokespecial} instruction to the same method. * an {@code invokespecial} instruction to the same method.
* *
* <h3>Usage examples</h3> * <h1>Usage examples</h1>
* Here are some examples of usage: * Here are some examples of usage:
* <p><blockquote><pre>{@code * <p><blockquote><pre>{@code
Object x, y; String s; int i; Object x, y; String s; int i;
...@@ -295,7 +295,7 @@ mh.invokeExact(System.out, "Hello, world."); ...@@ -295,7 +295,7 @@ mh.invokeExact(System.out, "Hello, world.");
* be a method which calls {@link java.util.Objects#equals(Object,Object) Objects.equals } * be a method which calls {@link java.util.Objects#equals(Object,Object) Objects.equals }
* on its arguments, and asserts that the result is true. * on its arguments, and asserts that the result is true.
* *
* <h3>Exceptions</h3> * <h1>Exceptions</h1>
* The methods {@code invokeExact} and {@code invoke} are declared * The methods {@code invokeExact} and {@code invoke} are declared
* to throw {@link java.lang.Throwable Throwable}, * to throw {@link java.lang.Throwable Throwable},
* which is to say that there is no static restriction on what a method handle * which is to say that there is no static restriction on what a method handle
...@@ -308,7 +308,7 @@ mh.invokeExact(System.out, "Hello, world."); ...@@ -308,7 +308,7 @@ mh.invokeExact(System.out, "Hello, world.");
* throwables locally, rethrowing only those which are legal in the context, * throwables locally, rethrowing only those which are legal in the context,
* and wrapping ones which are illegal. * and wrapping ones which are illegal.
* *
* <h3><a name="sigpoly"></a>Signature polymorphism</h3> * <h1><a name="sigpoly"></a>Signature polymorphism</h1>
* The unusual compilation and linkage behavior of * The unusual compilation and linkage behavior of
* {@code invokeExact} and plain {@code invoke} * {@code invokeExact} and plain {@code invoke}
* is referenced by the term <em>signature polymorphism</em>. * is referenced by the term <em>signature polymorphism</em>.
...@@ -333,7 +333,7 @@ mh.invokeExact(System.out, "Hello, world."); ...@@ -333,7 +333,7 @@ mh.invokeExact(System.out, "Hello, world.");
* Tools which determine symbolic linkage are required to accept such * Tools which determine symbolic linkage are required to accept such
* untransformed descriptors, without reporting linkage errors. * untransformed descriptors, without reporting linkage errors.
* *
* <h3>Interoperation between method handles and the Core Reflection API</h3> * <h1>Interoperation between method handles and the Core Reflection API</h1>
* Using factory methods in the {@link java.lang.invoke.MethodHandles.Lookup Lookup} API, * Using factory methods in the {@link java.lang.invoke.MethodHandles.Lookup Lookup} API,
* any class member represented by a Core Reflection API object * any class member represented by a Core Reflection API object
* can be converted to a behaviorally equivalent method handle. * can be converted to a behaviorally equivalent method handle.
...@@ -375,7 +375,7 @@ mh.invokeExact(System.out, "Hello, world."); ...@@ -375,7 +375,7 @@ mh.invokeExact(System.out, "Hello, world.");
* to call {@code invokeExact} or plain {@code invoke}, * to call {@code invokeExact} or plain {@code invoke},
* for any specified type descriptor . * for any specified type descriptor .
* *
* <h3>Interoperation between method handles and Java generics</h3> * <h1>Interoperation between method handles and Java generics</h1>
* A method handle can be obtained on a method, constructor, or field * A method handle can be obtained on a method, constructor, or field
* which is declared with Java generic types. * which is declared with Java generic types.
* As with the Core Reflection API, the type of the method handle * As with the Core Reflection API, the type of the method handle
...@@ -457,6 +457,8 @@ public abstract class MethodHandle { ...@@ -457,6 +457,8 @@ public abstract class MethodHandle {
* {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}, via JNI, * {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}, via JNI,
* or indirectly via {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect}, * or indirectly via {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect},
* it will throw an {@code UnsupportedOperationException}. * it will throw an {@code UnsupportedOperationException}.
* @param args the signature-polymorphic parameter list, statically represented using varargs
* @return the signature-polymorphic result, statically represented using {@code Object}
* @throws WrongMethodTypeException if the target's type is not identical with the caller's symbolic type descriptor * @throws WrongMethodTypeException if the target's type is not identical with the caller's symbolic type descriptor
* @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
*/ */
...@@ -491,6 +493,8 @@ public abstract class MethodHandle { ...@@ -491,6 +493,8 @@ public abstract class MethodHandle {
* {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}, via JNI, * {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}, via JNI,
* or indirectly via {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect}, * or indirectly via {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect},
* it will throw an {@code UnsupportedOperationException}. * it will throw an {@code UnsupportedOperationException}.
* @param args the signature-polymorphic parameter list, statically represented using varargs
* @return the signature-polymorphic result, statically represented using {@code Object}
* @throws WrongMethodTypeException if the target's type cannot be adjusted to the caller's symbolic type descriptor * @throws WrongMethodTypeException if the target's type cannot be adjusted to the caller's symbolic type descriptor
* @throws ClassCastException if the target's type can be adjusted to the caller, but a reference cast fails * @throws ClassCastException if the target's type can be adjusted to the caller, but a reference cast fails
* @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
...@@ -511,15 +515,26 @@ public abstract class MethodHandle { ...@@ -511,15 +515,26 @@ public abstract class MethodHandle {
* operations on outgoing argument values.) * operations on outgoing argument values.)
* The caller can assume that the incoming result value is part of the range * The caller can assume that the incoming result value is part of the range
* of the callee's return type. * of the callee's return type.
* @param args the signature-polymorphic parameter list, statically represented using varargs
* @return the signature-polymorphic result, statically represented using {@code Object}
*/ */
/*non-public*/ final native @PolymorphicSignature Object invokeBasic(Object... args) throws Throwable; /*non-public*/ final native @PolymorphicSignature Object invokeBasic(Object... args) throws Throwable;
/**
* Private method for trusted invocation of a MemberName of kind {@code REF_invokeVirtual}.
* The caller signature is restricted to basic types as with {@code invokeBasic}.
* The trailing (not leading) argument must be a MemberName.
* @param args the signature-polymorphic parameter list, statically represented using varargs
* @return the signature-polymorphic result, statically represented using {@code Object}
*/
/*non-public*/ static native @PolymorphicSignature Object linkToVirtual(Object... args) throws Throwable; /*non-public*/ static native @PolymorphicSignature Object linkToVirtual(Object... args) throws Throwable;
/** /**
* Private method for trusted invocation of a MemberName of kind {@code REF_invokeStatic}. * Private method for trusted invocation of a MemberName of kind {@code REF_invokeStatic}.
* The caller signature is restricted to basic types as with {@code invokeBasic}. * The caller signature is restricted to basic types as with {@code invokeBasic}.
* The trailing (not leading) argument must be a MemberName. * The trailing (not leading) argument must be a MemberName.
* @param args the signature-polymorphic parameter list, statically represented using varargs
* @return the signature-polymorphic result, statically represented using {@code Object}
*/ */
/*non-public*/ static native @PolymorphicSignature Object linkToStatic(Object... args) throws Throwable; /*non-public*/ static native @PolymorphicSignature Object linkToStatic(Object... args) throws Throwable;
...@@ -527,6 +542,8 @@ public abstract class MethodHandle { ...@@ -527,6 +542,8 @@ public abstract class MethodHandle {
* Private method for trusted invocation of a MemberName of kind {@code REF_invokeSpecial}. * Private method for trusted invocation of a MemberName of kind {@code REF_invokeSpecial}.
* The caller signature is restricted to basic types as with {@code invokeBasic}. * The caller signature is restricted to basic types as with {@code invokeBasic}.
* The trailing (not leading) argument must be a MemberName. * The trailing (not leading) argument must be a MemberName.
* @param args the signature-polymorphic parameter list, statically represented using varargs
* @return the signature-polymorphic result, statically represented using {@code Object}
*/ */
/*non-public*/ static native @PolymorphicSignature Object linkToSpecial(Object... args) throws Throwable; /*non-public*/ static native @PolymorphicSignature Object linkToSpecial(Object... args) throws Throwable;
...@@ -534,6 +551,8 @@ public abstract class MethodHandle { ...@@ -534,6 +551,8 @@ public abstract class MethodHandle {
* Private method for trusted invocation of a MemberName of kind {@code REF_invokeInterface}. * Private method for trusted invocation of a MemberName of kind {@code REF_invokeInterface}.
* The caller signature is restricted to basic types as with {@code invokeBasic}. * The caller signature is restricted to basic types as with {@code invokeBasic}.
* The trailing (not leading) argument must be a MemberName. * The trailing (not leading) argument must be a MemberName.
* @param args the signature-polymorphic parameter list, statically represented using varargs
* @return the signature-polymorphic result, statically represented using {@code Object}
*/ */
/*non-public*/ static native @PolymorphicSignature Object linkToInterface(Object... args) throws Throwable; /*non-public*/ static native @PolymorphicSignature Object linkToInterface(Object... args) throws Throwable;
......
...@@ -108,8 +108,9 @@ public class MethodHandleProxies { ...@@ -108,8 +108,9 @@ public class MethodHandleProxies {
* Future versions of this API may also equip wrapper instances * Future versions of this API may also equip wrapper instances
* with one or more additional public "marker" interfaces. * with one or more additional public "marker" interfaces.
* *
* @param <T> the desired type of the wrapper, a single-method interface
* @param intfc a class object representing {@code T}
* @param target the method handle to invoke from the wrapper * @param target the method handle to invoke from the wrapper
* @param intfc the desired type of the wrapper, a single-method interface
* @return a correctly-typed wrapper for the given target * @return a correctly-typed wrapper for the given target
* @throws NullPointerException if either argument is null * @throws NullPointerException if either argument is null
* @throws IllegalArgumentException if the {@code intfc} is not a * @throws IllegalArgumentException if the {@code intfc} is not a
......
...@@ -70,6 +70,7 @@ public class MethodHandles { ...@@ -70,6 +70,7 @@ public class MethodHandles {
* including direct method handles to private fields and methods. * including direct method handles to private fields and methods.
* This lookup object is a <em>capability</em> which may be delegated to trusted agents. * This lookup object is a <em>capability</em> which may be delegated to trusted agents.
* Do not store it in place where untrusted code can access it. * Do not store it in place where untrusted code can access it.
* @return a lookup object for the caller of this method
*/ */
@CallerSensitive @CallerSensitive
public static Lookup lookup() { public static Lookup lookup() {
...@@ -88,6 +89,7 @@ public class MethodHandles { ...@@ -88,6 +89,7 @@ public class MethodHandles {
* {@linkplain Lookup#in <code>publicLookup().in(C.class)</code>}. * {@linkplain Lookup#in <code>publicLookup().in(C.class)</code>}.
* Since all classes have equal access to public names, * Since all classes have equal access to public names,
* such a change would confer no new access rights. * such a change would confer no new access rights.
* @return a lookup object which is trusted minimally
*/ */
public static Lookup publicLookup() { public static Lookup publicLookup() {
return Lookup.PUBLIC_LOOKUP; return Lookup.PUBLIC_LOOKUP;
...@@ -111,72 +113,74 @@ public class MethodHandles { ...@@ -111,72 +113,74 @@ public class MethodHandles {
* on the {@code Lookup} object to create method handles for access-checked members. * on the {@code Lookup} object to create method handles for access-checked members.
* This includes all methods, constructors, and fields which are allowed to the lookup class, * This includes all methods, constructors, and fields which are allowed to the lookup class,
* even private ones. * even private ones.
* <p> *
* <h1><a name="lookups"></a>Lookup Factory Methods</h1>
* The factory methods on a {@code Lookup} object correspond to all major * The factory methods on a {@code Lookup} object correspond to all major
* use cases for methods, constructors, and fields. * use cases for methods, constructors, and fields.
* Here is a summary of the correspondence between these factory methods and * Here is a summary of the correspondence between these factory methods and
* the behavior the resulting method handles: * the behavior the resulting method handles:
* <code>
* <table border=1 cellpadding=5 summary="lookup method behaviors"> * <table border=1 cellpadding=5 summary="lookup method behaviors">
* <tr><th>lookup expression</th><th>member</th><th>behavior</th></tr> * <tr><th>lookup expression</th><th>member</th><th>behavior</th></tr>
* <tr> * <tr>
* <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)}</td> * <td>{@link java.lang.invoke.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)}</td>
* <td>FT f;</td><td>(T) this.f;</td> * <td>{@code FT f;}</td><td>{@code (T) this.f;}</td>
* </tr> * </tr>
* <tr> * <tr>
* <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)}</td> * <td>{@link java.lang.invoke.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)}</td>
* <td>static<br>FT f;</td><td>(T) C.f;</td> * <td>{@code static}<br>{@code FT f;}</td><td>{@code (T) C.f;}</td>
* </tr> * </tr>
* <tr> * <tr>
* <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findSetter lookup.findSetter(C.class,"f",FT.class)}</td> * <td>{@link java.lang.invoke.MethodHandles.Lookup#findSetter lookup.findSetter(C.class,"f",FT.class)}</td>
* <td>FT f;</td><td>this.f = x;</td> * <td>{@code FT f;}</td><td>{@code this.f = x;}</td>
* </tr> * </tr>
* <tr> * <tr>
* <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticSetter lookup.findStaticSetter(C.class,"f",FT.class)}</td> * <td>{@link java.lang.invoke.MethodHandles.Lookup#findStaticSetter lookup.findStaticSetter(C.class,"f",FT.class)}</td>
* <td>static<br>FT f;</td><td>C.f = arg;</td> * <td>{@code static}<br>{@code FT f;}</td><td>{@code C.f = arg;}</td>
* </tr> * </tr>
* <tr> * <tr>
* <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findVirtual lookup.findVirtual(C.class,"m",MT)}</td> * <td>{@link java.lang.invoke.MethodHandles.Lookup#findVirtual lookup.findVirtual(C.class,"m",MT)}</td>
* <td>T m(A*);</td><td>(T) this.m(arg*);</td> * <td>{@code T m(A*);}</td><td>{@code (T) this.m(arg*);}</td>
* </tr> * </tr>
* <tr> * <tr>
* <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStatic lookup.findStatic(C.class,"m",MT)}</td> * <td>{@link java.lang.invoke.MethodHandles.Lookup#findStatic lookup.findStatic(C.class,"m",MT)}</td>
* <td>static<br>T m(A*);</td><td>(T) C.m(arg*);</td> * <td>{@code static}<br>{@code T m(A*);}</td><td>{@code (T) C.m(arg*);}</td>
* </tr> * </tr>
* <tr> * <tr>
* <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findSpecial lookup.findSpecial(C.class,"m",MT,this.class)}</td> * <td>{@link java.lang.invoke.MethodHandles.Lookup#findSpecial lookup.findSpecial(C.class,"m",MT,this.class)}</td>
* <td>T m(A*);</td><td>(T) super.m(arg*);</td> * <td>{@code T m(A*);}</td><td>{@code (T) super.m(arg*);}</td>
* </tr> * </tr>
* <tr> * <tr>
* <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findConstructor lookup.findConstructor(C.class,MT)}</td> * <td>{@link java.lang.invoke.MethodHandles.Lookup#findConstructor lookup.findConstructor(C.class,MT)}</td>
* <td>C(A*);</td><td>(T) new C(arg*);</td> * <td>{@code C(A*);}</td><td>{@code new C(arg*);}</td>
* </tr> * </tr>
* <tr> * <tr>
* <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectGetter lookup.unreflectGetter(aField)}</td> * <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflectGetter lookup.unreflectGetter(aField)}</td>
* <td>(static)?<br>FT f;</td><td>(FT) aField.get(thisOrNull);</td> * <td>({@code static})?<br>{@code FT f;}</td><td>{@code (FT) aField.get(thisOrNull);}</td>
* </tr> * </tr>
* <tr> * <tr>
* <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectSetter lookup.unreflectSetter(aField)}</td> * <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflectSetter lookup.unreflectSetter(aField)}</td>
* <td>(static)?<br>FT f;</td><td>aField.set(thisOrNull, arg);</td> * <td>({@code static})?<br>{@code FT f;}</td><td>{@code aField.set(thisOrNull, arg);}</td>
* </tr> * </tr>
* <tr> * <tr>
* <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td> * <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
* <td>(static)?<br>T m(A*);</td><td>(T) aMethod.invoke(thisOrNull, arg*);</td> * <td>({@code static})?<br>{@code T m(A*);}</td><td>{@code (T) aMethod.invoke(thisOrNull, arg*);}</td>
* </tr> * </tr>
* <tr> * <tr>
* <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectConstructor lookup.unreflectConstructor(aConstructor)}</td> * <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflectConstructor lookup.unreflectConstructor(aConstructor)}</td>
* <td>C(A*);</td><td>(C) aConstructor.newInstance(arg*);</td> * <td>{@code C(A*);}</td><td>{@code (C) aConstructor.newInstance(arg*);}</td>
* </tr> * </tr>
* <tr> * <tr>
* <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td> * <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
* <td>(static)?<br>T m(A*);</td><td>(T) aMethod.invoke(thisOrNull, arg*);</td> * <td>({@code static})?<br>{@code T m(A*);}</td><td>{@code (T) aMethod.invoke(thisOrNull, arg*);}</td>
* </tr> * </tr>
* </table> * </table>
* </code> *
* Here, the type {@code C} is the class or interface being searched for a member, * Here, the type {@code C} is the class or interface being searched for a member,
* documented as a parameter named {@code refc} in the lookup methods. * documented as a parameter named {@code refc} in the lookup methods.
* The method or constructor type {@code MT} is composed from the return type {@code T} * The method type {@code MT} is composed from the return type {@code T}
* and the sequence of argument types {@code A*}. * and the sequence of argument types {@code A*}.
* The constructor also has a sequence of argument types {@code A*} and
* is deemed to return the newly-created object of type {@code C}.
* Both {@code MT} and the field type {@code FT} are documented as a parameter named {@code type}. * Both {@code MT} and the field type {@code FT} are documented as a parameter named {@code type}.
* The formal parameter {@code this} stands for the self-reference of type {@code C}; * The formal parameter {@code this} stands for the self-reference of type {@code C};
* if it is present, it is always the leading argument to the method handle invocation. * if it is present, it is always the leading argument to the method handle invocation.
...@@ -210,7 +214,7 @@ public class MethodHandles { ...@@ -210,7 +214,7 @@ public class MethodHandles {
* security manager checks. * security manager checks.
* </ul> * </ul>
* *
* <h3><a name="access"></a>Access checking</h3> * <h1><a name="access"></a>Access checking</h1>
* Access checks are applied in the factory methods of {@code Lookup}, * Access checks are applied in the factory methods of {@code Lookup},
* when a method handle is created. * when a method handle is created.
* This is a key difference from the Core Reflection API, since * This is a key difference from the Core Reflection API, since
...@@ -297,7 +301,7 @@ public class MethodHandles { ...@@ -297,7 +301,7 @@ public class MethodHandles {
* with static methods of {@link MethodHandles}, * with static methods of {@link MethodHandles},
* independently of any {@code Lookup} object. * independently of any {@code Lookup} object.
* *
* <h3>Security manager interactions</h3> * <h1>Security manager interactions</h1>
* <a name="secmgr"></a> * <a name="secmgr"></a>
* If a security manager is present, member lookups are subject to * If a security manager is present, member lookups are subject to
* additional checks. * additional checks.
...@@ -388,6 +392,7 @@ public class MethodHandles { ...@@ -388,6 +392,7 @@ public class MethodHandles {
* but the permissions may be additionally limited by the bitmask * but the permissions may be additionally limited by the bitmask
* {@link #lookupModes lookupModes}, which controls whether non-public members * {@link #lookupModes lookupModes}, which controls whether non-public members
* can be accessed. * can be accessed.
* @return the lookup class, on behalf of which this lookup object finds members
*/ */
public Class<?> lookupClass() { public Class<?> lookupClass() {
return lookupClass; return lookupClass;
...@@ -414,6 +419,7 @@ public class MethodHandles { ...@@ -414,6 +419,7 @@ public class MethodHandles {
* The purpose of this is to restrict access via the new lookup object, * The purpose of this is to restrict access via the new lookup object,
* so that it can access only names which can be reached by the original * so that it can access only names which can be reached by the original
* lookup object, and also by the new lookup class. * lookup object, and also by the new lookup class.
* @return the lookup modes, which limit the kinds of access performed by this lookup object
*/ */
public int lookupModes() { public int lookupModes() {
return allowedModes & ALL_MODES; return allowedModes & ALL_MODES;
...@@ -1352,6 +1358,7 @@ return mh1; ...@@ -1352,6 +1358,7 @@ return mh1;
* The type of the method handle will have a void return type. * The type of the method handle will have a void return type.
* Its last argument will be the array's element type. * Its last argument will be the array's element type.
* The first and second arguments will be the array type and int. * The first and second arguments will be the array type and int.
* @param arrayClass the class of an array
* @return a method handle which can store values into the array type * @return a method handle which can store values into the array type
* @throws NullPointerException if the argument is null * @throws NullPointerException if the argument is null
* @throws IllegalArgumentException if arrayClass is not an array type * @throws IllegalArgumentException if arrayClass is not an array type
...@@ -1580,12 +1587,12 @@ import static java.lang.invoke.MethodType.*; ...@@ -1580,12 +1587,12 @@ import static java.lang.invoke.MethodType.*;
... ...
MethodType intfn1 = methodType(int.class, int.class); MethodType intfn1 = methodType(int.class, int.class);
MethodType intfn2 = methodType(int.class, int.class, int.class); MethodType intfn2 = methodType(int.class, int.class, int.class);
MethodHandle sub = ... {int x, int y => x-y} ...; MethodHandle sub = ... (int x, int y) -> (x-y) ...;
assert(sub.type().equals(intfn2)); assert(sub.type().equals(intfn2));
MethodHandle sub1 = permuteArguments(sub, intfn2, 0, 1); MethodHandle sub1 = permuteArguments(sub, intfn2, 0, 1);
MethodHandle rsub = permuteArguments(sub, intfn2, 1, 0); MethodHandle rsub = permuteArguments(sub, intfn2, 1, 0);
assert((int)rsub.invokeExact(1, 100) == 99); assert((int)rsub.invokeExact(1, 100) == 99);
MethodHandle add = ... {int x, int y => x+y} ...; MethodHandle add = ... (int x, int y) -> (x+y) ...;
assert(add.type().equals(intfn2)); assert(add.type().equals(intfn2));
MethodHandle twice = permuteArguments(add, intfn1, 0, 0); MethodHandle twice = permuteArguments(add, intfn1, 0, 0);
assert(twice.type().equals(intfn1)); assert(twice.type().equals(intfn1));
...@@ -2261,6 +2268,8 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); ...@@ -2261,6 +2268,8 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
* The method type will nominally specify a return of {@code returnType}. * The method type will nominally specify a return of {@code returnType}.
* The return type may be anything convenient: It doesn't matter to the * The return type may be anything convenient: It doesn't matter to the
* method handle's behavior, since it will never return normally. * method handle's behavior, since it will never return normally.
* @param returnType the return type of the desired method handle
* @param exType the parameter type of the desired method handle
* @return method handle which can throw the given exceptions * @return method handle which can throw the given exceptions
* @throws NullPointerException if either argument is null * @throws NullPointerException if either argument is null
*/ */
......
...@@ -194,6 +194,8 @@ class MethodType implements java.io.Serializable { ...@@ -194,6 +194,8 @@ class MethodType implements java.io.Serializable {
/** /**
* Finds or creates a method type with the given components. * Finds or creates a method type with the given components.
* Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}. * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
* @param rtype the return type
* @param ptypes the parameter types
* @return a method type with the given components * @return a method type with the given components
* @throws NullPointerException if {@code rtype} or {@code ptypes} or any element of {@code ptypes} is null * @throws NullPointerException if {@code rtype} or {@code ptypes} or any element of {@code ptypes} is null
* @throws IllegalArgumentException if any element of {@code ptypes} is {@code void.class} * @throws IllegalArgumentException if any element of {@code ptypes} is {@code void.class}
...@@ -214,6 +216,9 @@ class MethodType implements java.io.Serializable { ...@@ -214,6 +216,9 @@ class MethodType implements java.io.Serializable {
* Finds or creates a method type with the given components. * Finds or creates a method type with the given components.
* Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}. * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
* The leading parameter type is prepended to the remaining array. * The leading parameter type is prepended to the remaining array.
* @param rtype the return type
* @param ptype0 the first parameter type
* @param ptypes the remaining parameter types
* @return a method type with the given components * @return a method type with the given components
* @throws NullPointerException if {@code rtype} or {@code ptype0} or {@code ptypes} or any element of {@code ptypes} is null * @throws NullPointerException if {@code rtype} or {@code ptype0} or {@code ptypes} or any element of {@code ptypes} is null
* @throws IllegalArgumentException if {@code ptype0} or {@code ptypes} or any element of {@code ptypes} is {@code void.class} * @throws IllegalArgumentException if {@code ptype0} or {@code ptypes} or any element of {@code ptypes} is {@code void.class}
...@@ -230,6 +235,7 @@ class MethodType implements java.io.Serializable { ...@@ -230,6 +235,7 @@ class MethodType implements java.io.Serializable {
* Finds or creates a method type with the given components. * Finds or creates a method type with the given components.
* Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}. * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
* The resulting method has no parameter types. * The resulting method has no parameter types.
* @param rtype the return type
* @return a method type with the given return value * @return a method type with the given return value
* @throws NullPointerException if {@code rtype} is null * @throws NullPointerException if {@code rtype} is null
*/ */
...@@ -242,6 +248,8 @@ class MethodType implements java.io.Serializable { ...@@ -242,6 +248,8 @@ class MethodType implements java.io.Serializable {
* Finds or creates a method type with the given components. * Finds or creates a method type with the given components.
* Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}. * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
* The resulting method has the single given parameter type. * The resulting method has the single given parameter type.
* @param rtype the return type
* @param ptype0 the parameter type
* @return a method type with the given return value and parameter type * @return a method type with the given return value and parameter type
* @throws NullPointerException if {@code rtype} or {@code ptype0} is null * @throws NullPointerException if {@code rtype} or {@code ptype0} is null
* @throws IllegalArgumentException if {@code ptype0} is {@code void.class} * @throws IllegalArgumentException if {@code ptype0} is {@code void.class}
...@@ -256,6 +264,9 @@ class MethodType implements java.io.Serializable { ...@@ -256,6 +264,9 @@ class MethodType implements java.io.Serializable {
* Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}. * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
* The resulting method has the same parameter types as {@code ptypes}, * The resulting method has the same parameter types as {@code ptypes},
* and the specified return type. * and the specified return type.
* @param rtype the return type
* @param ptypes the method type which supplies the parameter types
* @return a method type with the given components
* @throws NullPointerException if {@code rtype} or {@code ptypes} is null * @throws NullPointerException if {@code rtype} or {@code ptypes} is null
*/ */
public static public static
...@@ -938,7 +949,8 @@ s.writeObject(this.parameterArray()); ...@@ -938,7 +949,8 @@ s.writeObject(this.parameterArray());
* provided to the factory method {@link #methodType(Class,Class[]) methodType}. * provided to the factory method {@link #methodType(Class,Class[]) methodType}.
* For example, null values, or {@code void} parameter types, * For example, null values, or {@code void} parameter types,
* will lead to exceptions during deserialization. * will lead to exceptions during deserialization.
* @param the stream to write the object to * @param s the stream to write the object to
* @throws java.io.IOException if there is a problem writing the object
*/ */
private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
s.defaultWriteObject(); // requires serialPersistentFields to be an empty array s.defaultWriteObject(); // requires serialPersistentFields to be an empty array
...@@ -953,7 +965,9 @@ s.writeObject(this.parameterArray()); ...@@ -953,7 +965,9 @@ s.writeObject(this.parameterArray());
* It provides the parameters to the factory method called by * It provides the parameters to the factory method called by
* {@link #readResolve readResolve}. * {@link #readResolve readResolve}.
* After that call it is discarded. * After that call it is discarded.
* @param the stream to read the object from * @param s the stream to read the object from
* @throws java.io.IOException if there is a problem reading the object
* @throws ClassNotFoundException if one of the component classes cannot be resolved
* @see #MethodType() * @see #MethodType()
* @see #readResolve * @see #readResolve
* @see #writeObject * @see #writeObject
......
...@@ -195,7 +195,7 @@ public class MutableCallSite extends CallSite { ...@@ -195,7 +195,7 @@ public class MutableCallSite extends CallSite {
* processed before the method returns abnormally. * processed before the method returns abnormally.
* Which elements these are (if any) is implementation-dependent. * Which elements these are (if any) is implementation-dependent.
* *
* <h3>Java Memory Model details</h3> * <h1>Java Memory Model details</h1>
* In terms of the Java Memory Model, this operation performs a synchronization * In terms of the Java Memory Model, this operation performs a synchronization
* action which is comparable in effect to the writing of a volatile variable * action which is comparable in effect to the writing of a volatile variable
* by the current thread, and an eventual volatile read by every other thread * by the current thread, and an eventual volatile read by every other thread
......
/* /*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -97,66 +97,113 @@ public final class SerializedLambda implements Serializable { ...@@ -97,66 +97,113 @@ public final class SerializedLambda implements Serializable {
this.capturedArgs = Objects.requireNonNull(capturedArgs).clone(); this.capturedArgs = Objects.requireNonNull(capturedArgs).clone();
} }
/** Get the name of the class that captured this lambda */ /**
* Get the name of the class that captured this lambda.
* @return the name of the class that captured this lambda
*/
public String getCapturingClass() { public String getCapturingClass() {
return capturingClass.getName().replace('.', '/'); return capturingClass.getName().replace('.', '/');
} }
/** Get the name of the functional interface class to which this lambda has been converted */ /**
* Get the name of the functional interface class to which this
* lambda has been converted
* @return the name of the functional interface this lambda has
* been converted to
*/
public String getFunctionalInterfaceClass() { public String getFunctionalInterfaceClass() {
return functionalInterfaceClass; return functionalInterfaceClass;
} }
/** Get the name of the primary method for the functional interface to which this lambda has been converted */ /**
* Get the name of the primary method for the functional interface
* to which this lambda has been converted.
* @return the name of the primary methods of the functional interface
*/
public String getFunctionalInterfaceMethodName() { public String getFunctionalInterfaceMethodName() {
return functionalInterfaceMethodName; return functionalInterfaceMethodName;
} }
/** Get the signature of the primary method for the functional interface to which this lambda has been converted */ /**
* Get the signature of the primary method for the functional
* interface to which this lambda has been converted.
* @return the signature of the primary method of the functional
* interface
*/
public String getFunctionalInterfaceMethodSignature() { public String getFunctionalInterfaceMethodSignature() {
return functionalInterfaceMethodSignature; return functionalInterfaceMethodSignature;
} }
/** Get the method handle kind (see {@link MethodHandleInfo}) of the primary method for the functional interface /**
* to which this lambda has been converted */ * Get the method handle kind (see {@link MethodHandleInfo}) of
* the primary method for the functional interface to which this
* lambda has been converted
* @return the method handle kind of the primary method of
* functional interface
*/
public int getFunctionalInterfaceMethodKind() { public int getFunctionalInterfaceMethodKind() {
return functionalInterfaceMethodKind; return functionalInterfaceMethodKind;
} }
/** Get the name of the class containing the implementation method */ /**
* Get the name of the class containing the implementation
* method.
* @return the name of the class containing the implementation
* method
*/
public String getImplClass() { public String getImplClass() {
return implClass; return implClass;
} }
/** Get the name of the implementation method */ /**
* Get the name of the implementation method.
* @return the name of the implementation method
*/
public String getImplMethodName() { public String getImplMethodName() {
return implMethodName; return implMethodName;
} }
/** Get the signature of the implementation method */ /**
* Get the signature of the implementation method.
* @return the signature of the implementation method
*/
public String getImplMethodSignature() { public String getImplMethodSignature() {
return implMethodSignature; return implMethodSignature;
} }
/** Get the method handle kind (see {@link MethodHandleInfo}) of the implementation method */ /**
* Get the method handle kind (see {@link MethodHandleInfo}) of
* the implementation method.
* @return the method handle kind of the implementation method
*/
public int getImplMethodKind() { public int getImplMethodKind() {
return implMethodKind; return implMethodKind;
} }
/** /**
* Get the signature of the primary functional interface method after type variables are substituted with * Get the signature of the primary functional interface method
* their instantiation from the capture site * after type variables are substituted with their instantiation
* from the capture site.
* @return the signature of the primary functional interface method
* after type variable processing
*/ */
public final String getInstantiatedMethodType() { public final String getInstantiatedMethodType() {
return instantiatedMethodType; return instantiatedMethodType;
} }
/** Get the count of dynamic arguments to the lambda capture site */ /**
* Get the count of dynamic arguments to the lambda capture site.
* @return the count of dynamic arguments to the lambda capture site
*/
public int getCapturedArgCount() { public int getCapturedArgCount() {
return capturedArgs.length; return capturedArgs.length;
} }
/** Get a dynamic argument to the lambda capture site */ /**
* Get a dynamic argument to the lambda capture site.
* @param i the argument to capture
* @return a dynamic argument to the lambda capture site
*/
public Object getCapturedArg(int i) { public Object getCapturedArg(int i) {
return capturedArgs[i]; return capturedArgs[i];
} }
......
...@@ -43,13 +43,13 @@ ...@@ -43,13 +43,13 @@
* </li> * </li>
* </ul> * </ul>
* *
* <h2><a name="jvm_mods"></a>Summary of relevant Java Virtual Machine changes</h2> * <h1><a name="jvm_mods"></a>Summary of relevant Java Virtual Machine changes</h1>
* The following low-level information summarizes relevant parts of the * The following low-level information summarizes relevant parts of the
* Java Virtual Machine specification. For full details, please see the * Java Virtual Machine specification. For full details, please see the
* current version of that specification. * current version of that specification.
* *
* Each occurrence of an {@code invokedynamic} instruction is called a <em>dynamic call site</em>. * Each occurrence of an {@code invokedynamic} instruction is called a <em>dynamic call site</em>.
* <h3><a name="indyinsn"></a>{@code invokedynamic} instructions</h3> * <h2><a name="indyinsn"></a>{@code invokedynamic} instructions</h2>
* A dynamic call site is originally in an unlinked state. In this state, there is * A dynamic call site is originally in an unlinked state. In this state, there is
* no target method for the call site to invoke. * no target method for the call site to invoke.
* <p> * <p>
...@@ -97,7 +97,7 @@ ...@@ -97,7 +97,7 @@
* If this happens, the same error will the thrown for all subsequent * If this happens, the same error will the thrown for all subsequent
* attempts to execute the dynamic call site. * attempts to execute the dynamic call site.
* *
* <h3>timing of linkage</h3> * <h2>timing of linkage</h2>
* A dynamic call site is linked just before its first execution. * A dynamic call site is linked just before its first execution.
* The bootstrap method call implementing the linkage occurs within * The bootstrap method call implementing the linkage occurs within
* a thread that is attempting a first execution. * a thread that is attempting a first execution.
...@@ -131,7 +131,7 @@ ...@@ -131,7 +131,7 @@
* just before its first invocation. * just before its first invocation.
* There is no way to undo the effect of a completed bootstrap method call. * There is no way to undo the effect of a completed bootstrap method call.
* *
* <h3>types of bootstrap methods</h3> * <h2>types of bootstrap methods</h2>
* As long as each bootstrap method can be correctly invoked * As long as each bootstrap method can be correctly invoked
* by {@code MethodHandle.invoke}, its detailed type is arbitrary. * by {@code MethodHandle.invoke}, its detailed type is arbitrary.
* For example, the first argument could be {@code Object} * For example, the first argument could be {@code Object}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册