public static final class MethodHandles.Lookup extends Object
需要创建方法句柄的查找类将调用MethodHandles.lookup
为自己创建一个工厂。 当创建Lookup
工厂对象时,确定查找类的标识,并安全地存储在Lookup
对象中。 查找类(或其代理)可以使用Lookup
对象上的工厂方法来创建访问检查成员的方法句柄。 这包括允许查找类的所有方法,构造函数和字段,甚至是私有的。
Lookup
对象上的工厂方法Lookup
于方法,构造函数和字段的所有主要用例。
由工厂方法创建的每个方法句柄都是特定字节码行为的功能等同物。
(字节码行为在Java虚拟机规范的5.4.3.5节中描述。)这是这些工厂方法与生成的方法处理的行为之间的对应关系的总结。
lookup expression member bytecode behavior lookup.findGetter(C.class,"f",FT.class)
FT f;
(T) this.f;
lookup.findStaticGetter(C.class,"f",FT.class)
static
FT f;
(T) C.f;
lookup.findSetter(C.class,"f",FT.class)
FT f;
this.f = x;
lookup.findStaticSetter(C.class,"f",FT.class)
static
FT f;
C.f = arg;
lookup.findVirtual(C.class,"m",MT)
T m(A*);
(T) this.m(arg*);
lookup.findStatic(C.class,"m",MT)
static
T m(A*);
(T) C.m(arg*);
lookup.findSpecial(C.class,"m",MT,this.class)
T m(A*);
(T) super.m(arg*);
lookup.findConstructor(C.class,MT)
C(A*);
new C(arg*);
lookup.unreflectGetter(aField)
(static
)?FT f;
(FT) aField.get(thisOrNull);
lookup.unreflectSetter(aField)
(static
)?FT f;
aField.set(thisOrNull, arg);
lookup.unreflect(aMethod)
(static
)?T m(A*);
(T) aMethod.invoke(thisOrNull, arg*);
lookup.unreflectConstructor(aConstructor)
C(A*);
(C) aConstructor.newInstance(arg*);
lookup.unreflect(aMethod)
(static
)?T m(A*);
(T) aMethod.invoke(thisOrNull, arg*);
C
是搜索成员的类或refc
,在查找方法中被记录为名为refc
。
方法类型MT
由返回类型T
和参数类型序列A*
。
构造函数还具有一系列参数类型A*
,并被视为返回新创建的类型为C
对象。
MT
和字段类型FT
都被记录为名为type
。
形式参数this
代表C型的自C
;
如果它存在,它始终是方法句柄调用的主要参数。
(在某些protected
成员的情况下, this
可能被限制在查找类的类型中;见下文)。名称arg
代表所有其他方法句柄参数。
在Core Reflection API的代码示例中,如果访问的方法或字段为静态,则名称thisOrNull
表示空引用, this
this。
名称aMethod
, aField
和aConstructor
代表对应于给定构件反射的对象。
在给定成员具有可变权限(即,方法或构造方法)的情况下,返回的方法句柄也将为variable arity 。 在所有其他情况下,返回的方法句柄将是固定的。
讨论:查找方法句柄和底层类成员和字节码行为之间的等价性可以通过以下几种方法分解:
C
不能从查找类的加载器中进行符号访问,即使没有等效的Java表达式或字节码常量,查找仍然可以成功。 T
或MT
不能从查找类的加载器中进行符号访问,则查找仍然可以成功。 例如,无论请求类型如何, MethodHandle.invokeExact
和MethodHandle.invoke
查找将始终成功。 ldc
指令在CONSTANT_MethodHandle
常量上不受安全管理员检查。 Lookup
的工厂方法。
这是与Core Reflection API的一个主要区别,因为java.lang.reflect.Method.invoke
在每次呼叫时对每个呼叫者执行访问检查。
所有访问检查从Lookup
对象开始,它将其记录的查找类与所有请求进行比较,以创建方法句柄。 单个Lookup
对象可用于创建任意数量的访问检查方法句柄,全部针对单个查找类进行检查。
一个Lookup
对象可以与其他可信代码共享,如元对象协议。 共享的Lookup
对象委托在查找类的私有成员上创建方法句柄的功能。 即使特权代码使用Lookup
对象,访问检查也仅限于原始查找类的权限。
查找可能会失败,因为查找类不能访问包含的类,或者因为缺少所需的类成员,或者因为查找类不能访问所需的类成员,或者因为查找对象不够信任访问会员 在任何这些情况下, ReflectiveOperationException
将从尝试查找中抛出。 确切的课程将是以下之一:
通常,可以查找方法方法M
的方法M
的条件不比查找类可以编译,验证和解析到M
的调用的条件更多的M
。 如果JVM会引发诸如NoSuchMethodError之类的NoSuchMethodError
,方法句柄查找通常会引发相应的检查异常,例如NoSuchMethodException
。 并调用从查询产生的方法处理的效果是exactly equivalent对执行编制,验证和解决呼叫M
。 字段和构造函数也是一样的。
讨论:访问检查仅适用于命名和反映的方法,构造函数和字段。 其他方法句柄创建方法,如MethodHandle.asType
,不需要任何访问检查,并且独立于任何Lookup
对象使用。
如果所需的成员是protected
,通常的JVM规则适用,包括要求查找类必须与所需成员在同一个包中,或必须继承该成员。 (请参阅Java虚拟机规范,第4.9.2,5.4.3.5和6.4节)。另外,如果所需成员是不同包中的非静态字段或方法,则生成的方法句柄只能应用于查找类的对象或其子类之一。 这一要求通过缩窄导致的类型强制this
参数从C
(将必然是查找类的超类)到查找类本身。
JVM对invokespecial
指令提出了类似的要求,接收方参数必须与已解析的方法和当前类匹配。 同样,通过将引导参数的类型缩小到生成的方法句柄来强制执行此要求。 (请参阅Java虚拟机规范,第4.10.1.9节。)
JVM表示作为具有特殊名称的内部方法( "<init>"
和"<clinit>"
)的构造函数和静态初始化程序块。 调用指令的内部语法允许它们引用这些内部方法,就像它们是正常方法一样,但是JVM字节码验证器拒绝它们。 这种内部方法的查找将产生一个NoSuchMethodException
。
在某些情况下,Java编译器可以通过创建包装方法来访问同一顶层声明中另一个类的私有方法来获取嵌套类之间的访问。 例如,一个嵌套类C.D
可以其他相关的类如内访问私有成员C
, C.D.E
,或C.B
,但是Java编译器可能需要生成在这些相关的类包装方法。 在这种情况下, Lookup
的对象C.E
将无法将这些私有成员。 一种用于这一限制的方法是Lookup.in
方法,它可以在变换的查找C.E
成一个上的任何那些其他类的,没有特权的特殊仰角。
根据其设置的lookupModes
,允许给定查找对象的访问可能受限于查找类通常可访问的成员的子集。 例如, publicLookup
方法生成一个查询对象,该对象仅允许访问公共类中的公共成员。 调用者敏感方法lookup
产生一个查找对象,具有相对于其调用者类的完整功能,以模拟所有支持的字节码行为。 此外, Lookup.in
方法可能产生一个查找对象,其访问模式比原始查找对象少。
私人访问的讨论:我们说如果一个查找具有私有访问权,如果它的lookup modes包括访问 private
成员的可能性。 如其他相关方法中所述,只有具有私有访问权限的查询具有以下功能:
Class.forName
emulate invokespecial
说明 delegated lookup objects
,它们具有对同一个包成员内的其他类的私有访问 这些权限中的每一个都是这样一个事实的结果:具有私有访问的查找对象可以被安全地追溯到一个始发类,其中bytecode behaviors和Java语言访问权限可以被方法句柄可靠地确定和模拟。
类
对象的引用即可。
Core Reflection API也可以使用这种跨装载程序引用,并且不可能使用诸如invokestatic
或getfield
字节码getfield
。
有一个security manager API允许应用程序检查这样的跨装载程序引用。
这些检查适用于MethodHandles.Lookup
API和Core Reflection API(如类
所示 )。
如果存在安全管理员,则成员查询需要进行额外的检查。 从一到三个电话是安全管理员。 任何这些电话都可以通过投掷SecurityException
拒绝访问。 将smgr
定义为安全管理器lookc
作为当前查找对象的查找类, refc
作为成员正在寻找的包含类,以及defc
作为成员实际定义的类。 值lookc
被定义为不存在 ,如果当前查找对象不具有private access 。 呼叫是按照以下规则进行的:
lookc
不存在,或者如果它的类加载器是不一样的或的类加载器的祖先refc
,则smgr.checkPackageAccess(refcPkg)
被调用,其中refcPkg
是的包refc
。 lookc
不存在,则调用smgr.checkPermission
与RuntimePermission("accessDeclaredMembers")
。 lookc
不存在,并且如果defc
和refc
不同,则smgr.checkPackageAccess(defcPkg)
被调用,其中defcPkg
是的包defc
。 如果请求呼叫者敏感的方法的方法处理,对于一般的规则bytecode behaviors申请,但他们考虑到查找类的一种特殊的方式。 生成的方法句柄就像从查找类中包含的指令调用一样,以便调用者敏感的方法检测查找类。 (相比之下,方法句柄的调用者被忽略。)因此,在调用者敏感方法的情况下,不同的查找类可能会产生不同行为的方法句柄。
在查找对象为publicLookup()
或其他没有private access的其他查找对象的情况下,查找类被忽略。 在这种情况下,可以创建没有呼叫者-敏感的方法处理,访问是禁止的,并且查找失败并IllegalAccessException
。
讨论:例如,调用者敏感方法Class.forName(x)
可以返回不同的类或抛出异常异常,这取决于调用它的类的类加载器。 Class.forName
的公开查询将失败,因为没有合理的方式来确定其字节码行为。
如果应用程序缓存方法句柄进行广泛共享,则应使用publicLookup()
创建它们。 如果有一个查找Class.forName
,它将失败,并且应用程序必须在这种情况下采取适当的措施。 可能是在引用引导方法的调用期间的后续查找可以包含调用者的特定身份,从而使该方法可访问。
功能MethodHandles.lookup
是调用者敏感的,因此可以有一个用于查找的安全基础。 JSR 292 API中几乎所有其他方法都依赖于查找对象来检查访问请求。
Modifier and Type | Field and Description |
---|---|
static int |
PACKAGE
单位掩码表示
package 访问(默认访问),这可能有助于结果
lookupModes 。
|
static int |
PRIVATE
单位掩码表示
private 访问,这可能有助于结果
lookupModes 。
|
static int |
PROTECTED
单位掩码表示
protected 访问,这可能有助于结果
lookupModes 。
|
static int |
PUBLIC
单位掩码表示
public 访问,这可能有助于结果
lookupModes 。
|
Modifier and Type | Method and Description |
---|---|
MethodHandle |
bind(Object receiver, String name, MethodType type)
为非静态方法生成早期绑定的方法句柄。
|
MethodHandle |
findConstructor(类<?> refc, MethodType type)
使用指定类型的构造函数生成创建对象并初始化它的方法句柄。
|
MethodHandle |
findGetter(类<?> refc, String name, 类<?> type)
产生方法句柄,给非静态字段的读访问权限。
|
MethodHandle |
findSetter(类<?> refc, String name, 类<?> type)
产生一个给非静态字段写入访问权限的方法句柄。
|
MethodHandle |
findSpecial(类<?> refc, String name, MethodType type, 类<?> specialCaller)
为虚拟方法生成早期绑定的方法句柄。
|
MethodHandle |
findStatic(类<?> refc, String name, MethodType type)
为静态方法生成方法句柄。
|
MethodHandle |
findStaticGetter(类<?> refc, String name, 类<?> type)
产生一个给静态字段读取访问权限的方法句柄。
|
MethodHandle |
findStaticSetter(类<?> refc, String name, 类<?> type)
生成方法句柄,给静态字段写权限。
|
MethodHandle |
findVirtual(类<?> refc, String name, MethodType type)
为虚拟方法生成方法句柄。
|
MethodHandles.Lookup |
in(类<?> requestedLookupClass)
在指定的新查找类上创建一个查找。
|
类<?> |
lookupClass()
告诉哪个类执行查找。
|
int |
lookupModes()
告诉这个查找对象可以产生哪些访问保护类的成员。
|
MethodHandleInfo |
revealDirect(MethodHandle target)
破解由此查找对象或类似的对象创建的
direct method handle 。
|
String |
toString()
显示要从中进行查找的类的名称。
|
MethodHandle |
unreflect(方法 m)
做一个
direct method handle到
m ,如果查找类有权限。
|
MethodHandle |
unreflectConstructor(Constructor<?> c)
为反射的构造函数生成方法句柄。
|
MethodHandle |
unreflectGetter(Field f)
产生方法句柄,给予反映字段的读访问权限。
|
MethodHandle |
unreflectSetter(Field f)
产生一个方法句柄,给一个反射的字段写权限。
|
MethodHandle |
unreflectSpecial(方法 m, 类<?> specialCaller)
为反映的方法生成方法句柄。
|
public static final int PUBLIC
public
访问,这可能有助于结果lookupModes
。
0x01
的值恰好与public
modifier bit的值相同。
public static final int PRIVATE
private
访问,这可能有助于结果lookupModes
。
0x02
的值恰好与private
modifier bit的值相同。
public static final int PROTECTED
protected
访问,这可能有助于结果lookupModes
。
值0x04
恰好与protected
modifier bit的值相同。
public static final int PACKAGE
package
访问(默认访问),这可能有助于结果lookupModes
。
该值为0x08
,与任何特定的modifier bit无关 。
public 类<?> lookupClass()
public int lookupModes()
caller's class上新创建的查找对象设置了所有可能的位,因为调用者类可以访问其所有成员。 新的查找类别created from a previous lookup object上的查找对象可能将某些模式位设置为零。 这样做的目的是通过新的查找对象限制访问,以便它只能访问原始查找对象可以访问的名称,也可以访问新的查找类。
public MethodHandles.Lookup in(类<?> requestedLookupClass)
lookupClass
。
然而,所得到的Lookup
对象被保证没有比原来更多的访问能力。 特别是,访问功能可能会丢失如下:
requestedLookupClass
- 新查找对象所需的查找类
NullPointerException
- 如果参数为空
public String toString()
Class.getName
报告的。)如果对该查找允许的访问有限制,则通过在类名称中添加一个后缀(由斜杠和关键字组成)来指示。
该关键字表示最强的访问权限,选择如下:
MethodHandles.lookup
获得的对象是真实的。
由Lookup.in
创建的对象总是具有限制访问权限,并将显示一个后缀。
(看起来很奇怪,受保护的访问应该比私有访问更强大,独立于包访问,受保护的访问是首先丢失的,因为它需要调用者和被调用方之间的直接子类关系。
toString
在
Object
in(java.lang.Class<?>)
public MethodHandle findStatic(类<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException
findVirtual
或findSpecial
所示 )。查找对象的方法及其所有参数类型必须可访问。
返回的方法句柄将有variable arity,当且仅当该方法的变量arity修饰符位( 0x0080
)被设置。
如果调用返回的方法句柄,方法的类将被初始化,如果尚未被初始化。
例:
import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodType.*; ... MethodHandle MH_asList = publicLookup().findStatic(Arrays.class, "asList", methodType(List.class, Object[].class)); assertEquals("[x, y]", MH_asList.invoke("x", "y").toString());
refc
- 访问该方法的类
name
- 方法的名称
type
- 方法的类型
NoSuchMethodException
- 如果方法不存在
IllegalAccessException
- 如果访问检查失败,或者方法不是
static
,或者方法的可变
asVarargsCollector
修饰符位被设置并且
asVarargsCollector
失败
SecurityException
- 如果一个安全管理员存在,它是
refuses access
NullPointerException
- 如果任何参数为空
public MethodHandle findVirtual(类<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException
refc
)为前缀。
查询对象必须可访问该方法及其所有参数类型。
当被调用时,句柄会将第一个参数视为接收者,并在接收者的类型上进行调度,以确定要输入的方法实现。 (调度动作与invokevirtual
或invokeinterface
指令执行的动作相同)
如果查找类具有访问该成员的完整权限,则第一个参数将为refc
。 否则该成员必须是protected
,并且第一个参数将被限制在查找类的类型中。
返回的方法句柄将有variable arity,当且仅当该方法的变量arity修饰符位( 0x0080
)被设置。
因为一般equivalence之间invokevirtual
指令和方法所生产手柄findVirtual
,如果类是MethodHandle
和名称的字符串是invokeExact
或invoke
,所得到的方法手柄等效于一个由产生MethodHandles.exactInvoker
或MethodHandles.invoker
具有相同type
参数。 例:
import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodType.*; ... MethodHandle MH_concat = publicLookup().findVirtual(String.class, "concat", methodType(String.class, String.class)); MethodHandle MH_hashCode = publicLookup().findVirtual(Object.class, "hashCode", methodType(int.class)); MethodHandle MH_hashCode_String = publicLookup().findVirtual(String.class, "hashCode", methodType(int.class)); assertEquals("xy", (String) MH_concat.invokeExact("x", "y")); assertEquals("xy".hashCode(), (int) MH_hashCode.invokeExact((Object)"xy")); assertEquals("xy".hashCode(), (int) MH_hashCode_String.invokeExact("xy")); // interface method: MethodHandle MH_subSequence = publicLookup().findVirtual(CharSequence.class, "subSequence", methodType(CharSequence.class, int.class, int.class)); assertEquals("def", MH_subSequence.invoke("abcdefghi", 3, 6).toString()); // constructor "internal method" must be accessed differently: MethodType MT_newString = methodType(void.class); //()V for new String() try { assertEquals("impossible", lookup() .findVirtual(String.class, "<init>", MT_newString)); } catch (NoSuchMethodException ex) { } // OK MethodHandle MH_newString = publicLookup() .findConstructor(String.class, MT_newString); assertEquals("", (String) MH_newString.invokeExact());
refc
- 访问该方法的类或接口
name
- 方法的名称
type
- 方法的类型,省略了接收方参数
NoSuchMethodException
- 如果方法不存在
IllegalAccessException
- 如果访问检查失败,或者如果方法为
static
或者方法的可变
asVarargsCollector
修饰符位被设置并且
asVarargsCollector
失败
SecurityException
- 如果一个安全管理员存在,它
refuses access
NullPointerException
- 如果任何参数为空
public MethodHandle findConstructor(类<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException
请求的类型必须有一个返回类型void
。 (这与JVM处理构造函数类型描述符一致。)
当且仅当构造函数的变量arity修饰符位( 0x0080
)被设置时,返回的方法句柄将具有variable arity 。
如果调用返回的方法句柄,那么构造函数的类将被初始化,如果还没有被初始化。
例:
import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodType.*; ... MethodHandle MH_newArrayList = publicLookup().findConstructor( ArrayList.class, methodType(void.class, Collection.class)); Collection orig = Arrays.asList("x", "y"); Collection copy = (ArrayList) MH_newArrayList.invokeExact(orig); assert(orig != copy); assertEquals(orig, copy); // a variable-arity constructor: MethodHandle MH_newProcessBuilder = publicLookup().findConstructor( ProcessBuilder.class, methodType(void.class, String[].class)); ProcessBuilder pb = (ProcessBuilder) MH_newProcessBuilder.invoke("x", "y", "z"); assertEquals("[x, y, z]", pb.command().toString());
refc
- 访问该方法的类或接口
type
- 方法的类型,省略了接收者参数,以及一个void返回类型
NoSuchMethodException
- 如果构造函数不存在
IllegalAccessException
- 如果访问检查失败或者方法的变量arity修饰符位被设置并且
asVarargsCollector
失败
SecurityException
- 如果一个安全管理器存在,它
refuses access
NullPointerException
- 如果任何参数为空
public MethodHandle findSpecial(类<?> refc, String name, MethodType type, 类<?> specialCaller) throws NoSuchMethodException, IllegalAccessException
invokespecial
从明确内指令指定specialCaller
。
方法句柄的类型将是该方法的类型,前面加上适当受限的接收器类型。
(接收器类型将为specialCaller
或子类型。)查找对象必须可访问该方法及其所有参数类型。
在方法解析之前,如果显式指定的调用者类与查找类不相同,或者如果此查找对象没有private access权限,则访问失败。
返回的方法句柄将具有variable arity,如果且仅当方法的变量arity修饰符位( 0x0080
)被设置。
(注意:即使invokespecial
指令在特殊情况下可以引用,也可以使用名为"<init>"
JVM内部方法,使用findConstructor
可以安全访问实例初始化方法。)
例:
import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodType.*; ... static class Listie extends ArrayList { public String toString() { return "[wee Listie]"; } static Lookup lookup() { return MethodHandles.lookup(); } } ... // no access to constructor via invokeSpecial: MethodHandle MH_newListie = Listie.lookup() .findConstructor(Listie.class, methodType(void.class)); Listie l = (Listie) MH_newListie.invokeExact(); try { assertEquals("impossible", Listie.lookup().findSpecial( Listie.class, "<init>", methodType(void.class), Listie.class)); } catch (NoSuchMethodException ex) { } // OK // access to super and self methods via invokeSpecial: MethodHandle MH_super = Listie.lookup().findSpecial( ArrayList.class, "toString" , methodType(String.class), Listie.class); MethodHandle MH_this = Listie.lookup().findSpecial( Listie.class, "toString" , methodType(String.class), Listie.class); MethodHandle MH_duper = Listie.lookup().findSpecial( Object.class, "toString" , methodType(String.class), Listie.class); assertEquals("[]", (String) MH_super.invokeExact(l)); assertEquals(""+l, (String) MH_this.invokeExact(l)); assertEquals("[]", (String) MH_duper.invokeExact(l)); // ArrayList method try { assertEquals("inaccessible", Listie.lookup().findSpecial( String.class, "toString", methodType(String.class), Listie.class)); } catch (IllegalAccessException ex) { } // OK Listie subl = new Listie() { public String toString() { return "[subclass]"; } }; assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method
refc
- 访问该方法的类或接口
name
- 方法的名称(不能为“<init>”)
type
- 方法的类型,省略了接收方参数
specialCaller
- 提出的呼叫类执行
invokespecial
NoSuchMethodException
- 如果方法不存在
IllegalAccessException
- 如果访问检查失败,或者方法的变量
asVarargsCollector
修饰符位置位,并且
asVarargsCollector
失败
SecurityException
- 如果一个安全管理员存在,它
refuses access
NullPointerException
- 如果任何参数为空
public MethodHandle findGetter(类<?> refc, String name, 类<?> type) throws NoSuchFieldException, IllegalAccessException
refc
- 访问该方法的类或接口
name
- 该字段的名称
type
- 字段的类型
NoSuchFieldException
- 如果该字段不存在
IllegalAccessException
- 如果访问检查失败,或者该字段是
static
SecurityException
- 如果一个安全管理员存在,它
refuses access
NullPointerException
- 如果任何参数为空
public MethodHandle findSetter(类<?> refc, String name, 类<?> type) throws NoSuchFieldException, IllegalAccessException
refc
- 访问该方法的类或接口
name
- 该字段的名称
type
- 字段的类型
NoSuchFieldException
- 如果该字段不存在
IllegalAccessException
- 如果访问检查失败,或者该字段是
static
SecurityException
- 如果一个安全管理员存在,它
refuses access
NullPointerException
- 如果任何参数为空
public MethodHandle findStaticGetter(类<?> refc, String name, 类<?> type) throws NoSuchFieldException, IllegalAccessException
如果调用了返回的方法句柄,则该字段的类将被初始化,如果尚未初始化。
refc
- 访问该方法的类或接口
name
- 该字段的名称
type
- 字段的类型
NoSuchFieldException
- 如果该字段不存在
IllegalAccessException
- 如果访问检查失败,或者该字段不是
static
SecurityException
- 如果一个安全管理员存在,它
refuses access
NullPointerException
- 如果任何参数为空
public MethodHandle findStaticSetter(类<?> refc, String name, 类<?> type) throws NoSuchFieldException, IllegalAccessException
如果调用了返回的方法句柄,则该字段的类将被初始化,如果尚未初始化。
refc
- 访问该方法的类或接口
name
- 该字段的名称
type
- 字段的类型
NoSuchFieldException
- 如果该字段不存在
IllegalAccessException
- 如果访问检查失败,或者该字段不是
static
SecurityException
- 如果一个安全管理员存在,它
refuses access
NullPointerException
- 如果任何参数为空
public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException
defc
,其中给定名称和类型的方法可以被查找类访问。
查询对象必须可访问该方法及其所有参数类型。
方法句柄的类型将是该方法的类型,而不插入附加的接收器参数。
给定的接收器将被绑定到方法句柄中,以便每次调用方法句柄将在给定的接收器上调用请求的方法。
当且仅当该方法的变量arity修饰符位( 0x0080
)被设置且尾数组参数不是唯一的参数时,返回的方法句柄将具有variable arity 。 (如果尾数组参数是唯一的参数,给定的接收器值将被绑定到它。)
这相当于以下代码:
其中import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodType.*; ... MethodHandle mh0 = lookup().findVirtual(defc, name, type); MethodHandle mh1 = mh0.bindTo(receiver); MethodType mt1 = mh1.type(); if (mh0.isVarargsCollector()) mh1 = mh1.asVarargsCollector(mt1.parameterType(mt1.parameterCount()-1)); return mh1;
defc
是receiver.getClass()
或该类的超类型,其中所请求的方法可以被查找类访问。
(请注意, bindTo
不能保留变量。)
receiver
- 访问该方法的对象
name
- 方法的名称
type
- 方法的类型,省略了接收方参数
NoSuchMethodException
- 如果方法不存在
IllegalAccessException
- 如果访问检查失败或者方法的变量arity修饰符位被设置,并且
asVarargsCollector
失败
SecurityException
- 如果一个安全管理员存在,它
refuses access
NullPointerException
- 如果任何参数为空
MethodHandle.bindTo(java.lang.Object)
,
findVirtual(java.lang.Class<?>, java.lang.String, java.lang.invoke.MethodType)
public MethodHandle unreflect(方法 m) throws IllegalAccessException
accessible
标志,则代表查找类立即执行访问检查。
如果m不是公开的,不要与不信任方共享所产生的句柄。
当且仅当方法的变量arity修饰符位( 0x0080
)被设置时,返回的方法句柄将具有variable arity 。
如果m是静态的,并且如果返回的方法句柄被调用,那么方法的类将被初始化,如果它还没有被初始化。
m
- 反映的方法
IllegalAccessException
- 如果访问检查失败或者方法的变量arity修饰符位被设置并且
asVarargsCollector
失败
NullPointerException
- 如果参数为空
public MethodHandle unreflectSpecial(方法 m, 类<?> specialCaller) throws IllegalAccessException
invokespecial
从明确内指令指定specialCaller
。
方法句柄的类型将是该方法的类型,前面加上适当受限的接收器类型。
(接收器类型将为specialCaller
或子类型。)如果未设置方法的accessible
标志,则代表查找类立即执行访问检查,就像invokespecial
指令被链接一样。
在方法解析之前,如果显式指定的调用者类与lookup类不相同,或者该查找对象没有private access权限,则访问失败。
当且仅当方法的变量修饰符位( 0x0080
)被设置时,返回的方法句柄将具有variable arity 。
m
- 反映的方法
specialCaller
- 这个类名字叫做方法
IllegalAccessException
- 如果访问检查失败或者方法的变量arity修饰符位被设置,并且
asVarargsCollector
失败
NullPointerException
- 如果任何参数为空
public MethodHandle unreflectConstructor(Constructor<?> c) throws IllegalAccessException
newInstance
操作,在传递给方法句柄的参数上创建构造函数类的新实例。
如果未设置构造函数的accessible
标志,则代表查找类立即执行访问检查。
当且仅当构造函数的变量arity修饰符位( 0x0080
)被设置时,返回的方法句柄将具有variable arity 。
如果调用返回的方法句柄,那么构造函数的类将被初始化,如果还没有被初始化。
c
- 反映的构造函数
IllegalAccessException
- 如果访问检查失败或者方法的变量arity修饰符位被设置,并且
asVarargsCollector
失败
NullPointerException
- 如果参数为空
public MethodHandle unreflectGetter(Field f) throws IllegalAccessException
accessible
标志未设置,则代表查找类立即执行访问检查。
如果该字段是静态的,并且如果返回的方法句柄被调用,则该字段的类将被初始化,如果它还没有被初始化。
f
- 反射场
IllegalAccessException
- 如果访问检查失败
NullPointerException
- 如果参数为null
public MethodHandle unreflectSetter(Field f) throws IllegalAccessException
accessible
标志未设置,则代表查找类立即执行访问检查。
如果该字段是静态的,并且如果返回的方法句柄被调用,则该字段的类将被初始化,如果它还没有被初始化。
f
- 反射场
IllegalAccessException
- 如果访问检查失败
NullPointerException
- 如果参数为空
public MethodHandleInfo revealDirect(MethodHandle target)
target
- 一种直接的方法手柄来破解符号参考组件
SecurityException
- 如果一个安全管理器存在,它
refuses access
IllegalArgumentException
- 如果目标不是直接方法句柄或访问检查失败
NullPointerException
- 如果目标是
null
MethodHandleInfo