- java.lang.Object
-
- java.lang.invoke.MethodHandles.Lookup
-
- Enclosing class:
- MethodHandles
public static final class MethodHandles.Lookup extends Object
查找对象是用于创建方法句柄的工厂,当创建需要访问检查时。 方法句柄在调用时不执行访问检查,而是在创建时执行访问检查。 因此,当创建方法句柄时,必须强制执行方法句柄访问限制。 这些限制被强制执行的调用类被称为lookup class 。需要创建方法句柄的查找类将调用
MethodHandles.lookup
为自己创建一个工厂。 当创建Lookup
工厂对象时,确定查找类的标识,并将其安全地存储在Lookup
对象中。 查找类(或其Lookup
)可以使用Lookup
对象上的工厂方法来创建访问检查成员的方法句柄。 这包括允许查找类的所有方法,构造函数和字段,甚至是私有的。查找工厂方法
Lookup
对象上的工厂方法对应于方法,构造函数和字段的所有主要用例。 由工厂方法创建的每个方法句柄都是特定字节码行为的功能等价物。 (字节码行为在Java虚拟机规范的5.4.3.5节中描述。)这是这些工厂方法与生成的方法句柄的行为之间的对应关系的总结: lookup method behaviors lookup expression member bytecode behaviorlookup.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*);
lookup.findClass("C")
class C { ... }
C.class;
C
是搜索成员的类或接口,在查找方法中被记录为名为refc
的参数。 方法类型MT
由返回类型T
和参数类型序列A*
。 构造函数还具有一系列参数类型A*
,并被视为返回新创建的类型为C
对象。MT
和字段类型FT
都记录为名称为type
的参数。 形式参数this
代表C
型的自参照; 如果它存在,它始终是方法句柄调用的主要参数。 (在某些protected
成员的情况下,this
可能在类型中被限制到查找类;见下文)。名称arg
代表所有其他方法句柄参数。 在Core Reflection API的代码示例中,如果访问的方法或字段为静态,则名称为thisOrNull
表示空引用,否则为this
。 名称aMethod
,aField
和aConstructor
支架对应于给定的成员反射物体。findClass
操作的字节码行为是一个常量类的负载,好像通过ldc CONSTANT_Class
。 行为被表示,而不是方法句柄,而是直接作为一个Class
常量。在给定成员具有可变权限(即,方法或构造方法)的情况下,返回的方法句柄也将为variable arity 。 在所有其他情况下,返回的方法句柄将是固定的。
讨论:查找方法句柄和底层类成员和字节码行为之间的等价性可以通过以下几种方法分解:
- 如果
C
不能从查找类的加载器中进行符号访问,即使没有等效的Java表达式或字节码常量,查找仍然可以成功。 - 同样,如果
T
或MT
不能从查找类的加载器中进行符号访问,则查找仍然可以成功。 例如,无论请求类型如何,MethodHandle.invokeExact
和MethodHandle.invoke
查找将始终成功。 - 如果安装了一个安全管理器,它可以禁止在各种情况下查找( see below )。 相比之下,
ldc
指令对CONSTANT_MethodHandle
常数不进行安全管理员检查。 - 如果查找方法有一个very large arity ,方法句柄创建可能会失败,因为方法句柄类型具有太多的参数。
访问检查
当创建方法句柄时,访问检查应用于工厂方法Lookup
。 这是与Core Reflection API的关键区别,因为java.lang.reflect.Method.invoke
对每个呼叫者进行每次呼叫的访问检查。所有访问检查从
Lookup
对象开始,它将其记录的查找类与所有请求进行比较,以创建方法句柄。 单个Lookup
对象可用于创建任意数量的访问检查方法句柄,所有这些都针对单个查找类进行检查。一个
Lookup
对象可以与其他可信代码共享,如元对象协议。 共享的Lookup
对象委派了在查找类的私有成员上创建方法句柄的功能。 即使特权代码使用Lookup
对象,访问检查仅限于原始查找类的权限。查找可能会失败,因为查找类不能访问包含的类,或者因为缺少所需的类成员,或者因为查找类不能访问所需的类成员,或者因为查找对象不够信任访问会员 在任何这些情况下,将从尝试查找中抛出
ReflectiveOperationException
。 确切的课程将是以下之一:- NoSuchMethodException - 如果请求但不存在的方法
- NoSuchFieldException - 如果一个字段被请求但不存在
- IllegalAccessException - 如果成员存在,但访问检查失败
通常,可以查找方法方法
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
的查找C.E
为任何其他类中的查找,而不特别提升权限。允许给定查找对象的访问可以根据其集合
lookupModes
限制到查找类通常可访问的成员的子集。 例如,publicLookup
方法生成一个查找对象,该对象只允许访问导出包的公共类中的公共成员。 调用者敏感方法lookup
产生一个查找对象,具有相对于其调用者类的完整功能,以模拟所有支持的字节码行为。 此外,Lookup.in
方法可能产生一个查找对象,其访问模式比原始查找对象少。私人访问 讨论:如果lookup modes包含访问
private
成员的可能性,我们认为查找具有私有访问权限 。 如其他相关方法中所述,只有具有私有访问权限的查询具有以下功能:- 访问查找类的私有字段,方法和构造函数
- 创建方法手柄,调用caller sensitive方法,如
Class.forName
- 创建方法处理哪些
emulate invokespecial
指令 - 避免package access checks查找类可访问的类
- 创建
delegated lookup objects
,它们具有对同一个包成员内的其他类的私有访问
这些权限中的每一个都是这样一个事实的结果:具有私有访问的查找对象可以安全地追溯到一个始发类,其起始类可以可靠地确定其bytecode behaviors和Java语言访问权限并通过方法句柄进行仿真。
安全管理器交互
虽然字节码指令只能引用相关类加载器中的类,但是该API可以搜索任何类中的方法,只要对其Class
对象的引用可用即可。 Core Reflection API也可以使用这种跨装载程序引用,并且不可能使用诸如invokestatic
或getfield
字节码指令。 有一个security manager API允许应用程序检查这样的跨装载程序引用。 这些检查适用于MethodHandles.Lookup
API和Core Reflection API(见Class
)。如果存在安全管理员,则成员和类查找需要额外的检查。 从一到三个电话是安全管理员。 任何这些电话可以通过抛出一个
SecurityException
拒绝访问。 限定smgr
作为安全管理器,lookc
作为查找类的当前查找对象,的refc
作为其中成员正在寻求包含类,和defc
作为其中构件被实际定义的类。 (如果一个类或其他类型的被存取时,refc
个defc
值是类本身。)的值lookc
被定义为不存在 ,如果当前查找对象不具有private access 。 呼叫是按照以下规则进行的:- 步骤1:如果
lookc
不存在,或者如果它的类加载器是不一样的或的类加载器的祖先refc
,然后smgr.checkPackageAccess(refcPkg)
被调用,其中refcPkg
是的包refc
。 - 步骤2a:如果检索的成员不是公开的,并且
lookc
不存在,则RuntimePermission("accessDeclaredMembers")与RuntimePermission("accessDeclaredMembers")
被调用。 - 步骤2b:如果检索到的类有一个
null
类加载器,并且lookc
不存在,则smgr.checkPermission
与RuntimePermission("getClassLoader")
被调用。 - 步骤3:如果所检索的部件是不公开的,而如果
lookc
不存在,并且如果defc
和refc
不同,则smgr.checkPackageAccess(defcPkg)
被调用,其中defcPkg
是的包defc
。
来电者敏感方法
少量的Java方法有一个特殊的属性叫做呼叫者敏感性。 来电者敏感的方法可以根据其直接呼叫者的身份而有所不同。如果请求了一个方法的方法句柄,则应用bytecode behaviors的一般规则,但以特殊方式考虑查找类。 生成的方法句柄就像从查找类中包含的指令调用一样,以便调用者敏感的方法检测查找类。 (相比之下,方法句柄的调用者被忽略。)因此,在调用者敏感方法的情况下,不同的查找类可能会产生不同行为的方法句柄。
在查找对象为
publicLookup()
或其他没有private access的查找对象的情况下 ,查找类被忽略。 在这种情况下,不能创建调用者敏感方法句柄,禁止访问,并且查找失败,并使用IllegalAccessException
。讨论:例如,呼叫者敏感的方法
Class.forName(x)
可以返回不同的类或抛出不同的异常,这取决于调用它的类的类加载器。Class.forName
的公开查询将失败,因为没有合理的方式来确定其字节码行为。如果应用程序缓存方法句柄进行广泛共享,则应使用
publicLookup()
创建它们。 如果有一个Class.forName
的查找,它将失败,并且应用程序必须在这种情况下采取适当的措施。 可能是在引用引导方法的调用期间的后续查找可以包含调用者的特定身份,从而使该方法可访问。功能
MethodHandles.lookup
是调用者敏感的,因此可以有一个用于查找的安全基础。 JSR 292 API中几乎所有其他方法都依赖于查找对象来检查访问请求。
-
-
Field Summary
Fields Modifier and Type Field 描述 static int
MODULE
代表module
访问(默认访问)的单位掩码,这可能有助于lookupModes
的结果。static int
PACKAGE
代表package
访问(默认访问)的单位掩码,这可能有助于lookupModes
的结果。static int
PRIVATE
代表private
访问的单位掩码,可能有助于lookupModes
的结果。static int
PROTECTED
代表protected
访问的单位掩码,这可能有助于lookupModes
的结果。static int
PUBLIC
一个表示public
访问的单位掩码,这可能有助于lookupModes
的结果。static int
UNCONDITIONAL
代表unconditional
访问的单位掩码可能有助于lookupModes
的结果。
-
方法摘要
所有方法 接口方法 具体的方法 Modifier and Type 方法 描述 Class<?>
accessClass(Class<?> targetClass)
确定是否可以从此Lookup
对象定义的查找上下文中访问类。MethodHandle
bind(Object receiver, String name, MethodType type)
为非静态方法生成早期绑定的方法句柄。Class<?>
defineClass(byte[] bytes)
定义一个类到同一个类加载器,并在同一个运行时包和protection domain作为这个查找的lookup class 。MethodHandles.Lookup
dropLookupMode(int modeToDrop)
在同一查找类中创建一个查找,该查找对象查找成员,但查找模式已丢失给定的查找模式。Class<?>
findClass(String targetName)
从这个Lookup
对象定义的查找上下文中按名称查找一个类。MethodHandle
findConstructor(Class<?> refc, MethodType type)
使用指定类型的构造函数生成创建对象并初始化它的方法句柄。MethodHandle
findGetter(Class<?> refc, String name, Class<?> type)
产生方法句柄,给非静态字段的读访问权限。MethodHandle
findSetter(Class<?> refc, String name, Class<?> type)
产生一个给非静态字段写入访问权限的方法句柄。MethodHandle
findSpecial(Class<?> refc, String name, MethodType type, Class<?> specialCaller)
为虚拟方法生成早期绑定的方法句柄。MethodHandle
findStatic(Class<?> refc, String name, MethodType type)
为静态方法生成方法句柄。MethodHandle
findStaticGetter(Class<?> refc, String name, Class<?> type)
产生一个给静态字段读取访问权限的方法句柄。MethodHandle
findStaticSetter(Class<?> refc, String name, Class<?> type)
生成方法句柄,给静态字段写权限。VarHandle
findStaticVarHandle(Class<?> decl, String name, Class<?> type)
产生一个VarHandle,可以访问name
类中声明的类型为type
的静态字段decl
。VarHandle
findVarHandle(Class<?> recv, String name, Class<?> type)
产生一个VarHandle,可以访问name
类中声明的类型为type
的非静态字段recv
。MethodHandle
findVirtual(Class<?> refc, String name, MethodType type)
为虚拟方法生成方法句柄。boolean
hasPrivateAccess()
如果此查找具有PRIVATE
访问权限,则返回true
。MethodHandles.Lookup
in(Class<?> requestedLookupClass)
在指定的新查找类上创建一个查找。Class<?>
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, Class<?> specialCaller)
为反映的方法生成方法句柄。VarHandle
unreflectVarHandle(Field f)
产生一个VarHandle,可以访问f
类中声明的类型为T
的反射字段R
。
-
-
-
字段详细信息
-
PUBLIC
public static final int PUBLIC
代表public
访问的单位掩码,这可能有助于lookupModes
的结果。 该值0x01
恰好与public
modifier bit的值相同。- 另请参见:
- Constant Field Values
-
PRIVATE
public static final int PRIVATE
代表private
访问的单位掩码,可能有助于lookupModes
的结果。 该值0x02
恰好与private
modifier bit的值相同。- 另请参见:
- Constant Field Values
-
PROTECTED
public static final int PROTECTED
代表protected
访问的单位掩码,可能有助于lookupModes
的结果。 该值0x04
恰好与protected
modifier bit的值相同。- 另请参见:
- Constant Field Values
-
PACKAGE
public static final int PACKAGE
代表package
访问(默认访问)的单位掩码,这可能有助于lookupModes
的结果。 该值为0x08
,与任何特定的modifier bit无关 。- 另请参见:
- Constant Field Values
-
MODULE
public static final int MODULE
代表module
访问(默认访问)的单位掩码,这可能有助于lookupModes
的结果。 该值为0x10
,与任何特定的modifier bit无关 。 结合PUBLIC
修饰符位,具有此查找模式的Lookup
可以访问查找类的模块中的所有公共类型以及其他模块导出的包中的公共类型到查找类的模块。- 从以下版本开始:
- 9
- 另请参见:
- Constant Field Values
-
UNCONDITIONAL
public static final int UNCONDITIONAL
代表unconditional
访问的单位掩码可能有助于lookupModes
的结果。 该值为0x20
,与任何特定的modifier bit无关 。 一个Lookup
这种查找模式取得readability 。 结合PUBLIC
修改者位,具有此查找模式的Lookup
可以访问所有公钥类型的所有公共成员,其中类型为exported unconditionally
的包。- 从以下版本开始:
- 9
- 另请参见:
-
MethodHandles.publicLookup()
, Constant Field Values
-
-
方法详细信息
-
lookupClass
public Class<?> lookupClass()
- 结果
- 查找类,代表此查找对象查找成员
-
lookupModes
public int lookupModes()
告诉这个查找对象可以产生哪些访问保护类的成员。 结果是比特的位掩码PUBLIC (0x01) , PRIVATE (0x02) , PROTECTED (0x04) , PACKAGE (0x08) , MODULE (0x10) ,和UNCONDITIONAL (0x20) 。caller's class上新创建的查找对象具有所有可能的位,除了
UNCONDITIONAL
。 查找可用于访问调用者类的所有成员,调用者模块中的所有公共类型以及其他模块导出到调用者模块的包中的所有公共类型。 新查找类created from a previous lookup object上的查找对象可能将某些模式位设置为零。 模式位也可以是directly cleared 。 一旦清除,模式位不能从降级的查找对象恢复。 这样做的目的是通过新的查找对象限制访问,以便它只能访问原始查找对象可以访问的名称,也可以访问新的查找类。- 结果
- 查找模式,限制由该查找对象执行的访问的种类
- 另请参见:
-
in(java.lang.Class<?>)
,dropLookupMode(int)
-
in
public MethodHandles.Lookup in(Class<?> requestedLookupClass)
在指定的新查找类上创建一个查找。 生成的对象将报告指定的类作为自己的lookupClass
。但是,所得到的
Lookup
对象保证没有比原来更多的访问能力。 特别是,访问功能可能会丢失如下:- 如果旧查找类在一个
named
模块中,并且新的查找类位于不同的模块M
,则M
的导出包中的任何成员甚至公共成员也不可访问。 这个例外是当这个查找是publicLookup
,在这种情况下,PUBLIC
访问不会丢失。 - 如果旧的查找类在一个未命名的模块中,并且新的查找类是不同的模块,那么
MODULE
访问将丢失。 - 如果新的查找类与旧的查找类不同,则丢失
UNCONDITIONAL
。 - 如果新的查找类与旧的查找类不同,则保护和默认(包)成员将无法访问。
- 如果新的查找类与旧的查找类不在同一个包成员内,则私有成员将无法访问,受保护的成员将无法通过继承访问。 (受保护的成员可能因为包的共享而可以访问。)
- 如果旧的查找类不能访问新的查找类,那么任何成员,甚至公共成员都不可访问。 (在所有其他情况下,公共成员将继续可访问。)
结果查找的加载类(在
findClass(java.lang.String)
调用期间使用)的功能由查找类'加载器确定,这可能由于此操作而改变。- 参数
-
requestedLookupClass
- 新查找对象所需的查找类 - 结果
- 报告所需查找类的查找对象,如果没有变化则是相同的对象
- 异常
-
NullPointerException
- 如果参数为空
- 如果旧查找类在一个
-
dropLookupMode
public MethodHandles.Lookup dropLookupMode(int modeToDrop)
在同一查找类中创建一个查找,该查找对象查找成员,但查找模式已丢失给定的查找模式。 查找模式下降是一个PUBLIC
,MODULE
,PACKAGE
,PROTECTED
或PRIVATE
。PROTECTED
和UNCONDITIONAL
总是丢弃,因此所得到的查找模式将永远不具有这些访问功能。 当丢弃PACKAGE
,所得到的查找将不具有PACKAGE
或PRIVATE
访问权限。 当拖放MODULE
然后将得到的查找不会有MODULE
,PACKAGE
,或PRIVATE
访问。 如果PUBLIC
被删除,则生成的查找将无法访问。- 参数
-
modeToDrop
- 查找模式下降 - 结果
- 缺少指示模式的查找对象,如果没有变化则是相同的对象
- 异常
-
IllegalArgumentException
-如果modeToDrop
不是一个PUBLIC
,MODULE
,PACKAGE
,PROTECTED
,PRIVATE
或UNCONDITIONAL
- 从以下版本开始:
- 9
- 另请参见:
-
MethodHandles.privateLookupIn(java.lang.Class<?>, java.lang.invoke.MethodHandles.Lookup)
-
defineClass
public Class<?> defineClass(byte[] bytes) throws IllegalAccessException
将类定义到相同的类加载器,并在同一个运行时包中,以及protection domain作为此查找的lookup class 。该查找的lookup modes必须包括
PACKAGE
访问作为默认(包)成员可以访问该类。PACKAGE
查找模式用于验证查找对象是由运行时程序包中的调用者创建的(或从最初由适当的特权代码创建的查找派生到运行时程序包中的目标类)创建的。bytes
参数是与查找类在同一个包中的类名称的有效类文件(由Java虚拟机规范定义)的类字节。此方法不运行类初始化程序。 类初始化程序可以在稍后的时间运行,如“Java语言规范”第12.4节所述。
如果有安全管理员,则首先要求其
checkPermission
方法检查RuntimePermission("defineClass")
。- 参数
-
bytes
- 类字节 - 结果
-
Class
对象 - 异常
-
IllegalArgumentException
- 字节是针对查找类的不同包中的类 -
IllegalAccessException
- 如果此查找没有PACKAGE
访问 -
LinkageError
- 如果类格式错误(ClassFormatError
),无法验证(VerifyError
),已经定义,或者发生另一个链接错误 -
SecurityException
- 如果安全管理员否认 -
NullPointerException
- 如果bytes
是null
- 从以下版本开始:
- 9
- 另请参见:
-
MethodHandles.privateLookupIn(java.lang.Class<?>, java.lang.invoke.MethodHandles.Lookup)
,dropLookupMode(int)
,ClassLoader.defineClass(String,byte[],int,int,ProtectionDomain)
-
toString
public String toString()
显示要从中进行查找的类的名称。 (该名称是由Class.getName
报告的。)如果对该查找允许的访问有限制,则通过在类名称中添加一个后缀(由斜杠和关键字组成)来指示。 该关键字表示最强的访问权限,选择如下:- 如果不允许访问,则后缀为“/ noaccess”。
- 如果只允许对导出包中的类型进行公共访问,则后缀为“/ public”。
- 如果只允许公共访问和无条件访问,则后缀为“/ publicLookup”。
- 如果只允许公共和模块访问,则后缀为“/ module”。
- 如果只允许公共,模块和包访问,则后缀为“/ package”。
- 如果只允许public,module,package和private访问,则后缀为“/ private”。
MethodHandles.lookup
获得的对象。Lookup.in
创建的对象总是有限制访问,并显示一个后缀。(看起来很奇怪,受保护的访问应该比私有访问更强大,独立于包访问,受保护访问是首先丢失的,因为它需要调用者和被调用方之间的直接子类关系。
- 重写:
-
toString
在Object
- 结果
- 对象的字符串表示形式。
- 另请参见:
-
in(java.lang.Class<?>)
-
findStatic
public MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException
为静态方法生成方法句柄。 方法句柄的类型将是该方法的类型。 (由于静态方法不接收接收器,所以在方法句柄类型中没有插入附加的接收器参数,因为将使用findVirtual
或findSpecial
) 。查找对象的方法及其所有参数类型必须可访问。当且仅当方法的变量修饰符位(
0x0080
)被设置时,返回的方法句柄将具有variable arity 。如果调用返回的方法句柄,方法的类将被初始化,如果尚未被初始化。
例:
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
,或者方法的变量arity修饰符位是否设置并且asVarargsCollector
失败 -
SecurityException
- 如果一个安全管理员存在,它是 refuses access -
NullPointerException
- 如果任何参数为空
-
findVirtual
public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException
为虚拟方法生成方法句柄。 方法句柄的类型将是该方法的类型,接收器类型(通常为refc
)为前缀。 查询对象必须可访问该方法及其所有参数类型。当被调用时,句柄会将第一个参数视为接收者,并在接收者的类型上进行调度,以确定要输入的方法实现。 (调度动作与
invokevirtual
或invokeinterface
指令执行的动作相同)如果查找类具有访问该成员的完整权限,则第一个参数将为
refc
。 否则该成员必须是protected
并且第一个参数将被限制在查找类的类型中。返回的方法句柄将会有variable arity,如果且仅当方法的变量arity修饰符位(
0x0080
)被设置。由于由
findVirtual
生成的invokevirtual
指令和方法句柄之间的一般equivalence ,如果类为MethodHandle
,名称字符串为invokeExact
或invoke
,则生成的方法句柄相当于由MethodHandles.exactInvoker
或MethodHandles.invoker
生成的相同的type
参数。如果类是
VarHandle
,并且名称字符串对应于签名多态访问模式方法的名称,则生成的方法句柄等效于由MethodHandles.varHandleInvoker(java.lang.invoke.VarHandle.AccessMode, java.lang.invoke.MethodType)
生成的访问模式对应于名称字符串并具有相同的type
参数的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
,或者方法是private
接口方法,或者方法的变量arity修饰符位置位,并且asVarargsCollector
失败 -
SecurityException
- 如果安全管理员存在,它是 refuses access -
NullPointerException
- 如果任何参数为空
-
findConstructor
public MethodHandle findConstructor(Class<?> 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
- 如果任何参数为空
-
findClass
public Class<?> findClass(String targetName) throws ClassNotFoundException, IllegalAccessException
从这个Lookup
对象定义的查找上下文中按名称查找一个类。 该类的静态初始化程序未运行。这里的查找上下文由lookup class ,其类加载器和lookup modes决定 。 特别地,该方法首先尝试加载所请求的类,然后确定该类是否可被该查找对象访问。
- 参数
-
targetName
- 要查找的类的完全限定名称。 - 结果
- 所请求的类。
- 异常
-
SecurityException
- 如果安全管理器存在,它是 refuses access -
LinkageError
- 如果链接失败 -
ClassNotFoundException
- 如果类不能由查找类'loader加载。 -
IllegalAccessException
- 如果类不可访问,则使用允许的访问模式。 -
SecurityException
- 如果安全管理员存在,它是 refuses access - 从以下版本开始:
- 9
-
accessClass
public Class<?> accessClass(Class<?> targetClass) throws IllegalAccessException
- 参数
-
targetClass
- 要进行访问检查的类 - 结果
- 已经访问检查的类
- 异常
-
IllegalAccessException
- 如果类不能从查找类访问,则使用允许的访问模式。 -
SecurityException
- 如果一个安全管理器存在,它是 refuses access - 从以下版本开始:
- 9
-
findSpecial
public MethodHandle findSpecial(Class<?> refc, String name, MethodType type, Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException
为虚拟方法生成早期绑定的方法句柄。 它会绕过检查重写在接收机,方法as if called从invokespecial
从明确内指令指定specialCaller
。 方法句柄的类型将是该方法的类型,前面加上适当受限的接收器类型。 (接收器类型将为specialCaller
或子类型。)查找对象必须可访问该方法及其所有参数类型。在方法解析之前,如果显式指定的调用者类与lookup类不相同,或者该查找对象没有private access权限,则访问失败。
当且仅当方法的变量arity修饰符位(
0x0080
)被设置时,返回的方法句柄将具有variable arity 。(注:即使在特殊情况下,
invokespecial
指令可以引用它们,这个API也不可见JVM内部方法,名称为"<init>"
,使用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
- 如果访问检查失败,或者方法为static
,或者方法的变量arity修饰符位是否设置并且asVarargsCollector
失败 -
SecurityException
- 如果安全管理员存在,它是 refuses access -
NullPointerException
- 如果任何参数为空
-
findGetter
public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException
产生方法句柄,给非静态字段的读访问权限。 方法句柄的类型将具有字段值类型的返回类型。 方法句柄的单个参数将是包含该字段的实例。 代表查找类立即执行访问检查。- 参数
-
refc
- 访问该方法的类或接口 -
name
- 该字段的名称 -
type
- 字段的类型 - 结果
- 一个可以从字段加载值的方法句柄
- 异常
-
NoSuchFieldException
- 如果该字段不存在 -
IllegalAccessException
- 如果访问检查失败,或者该字段是static
-
SecurityException
- 如果安全管理器存在,它是 refuses access -
NullPointerException
- 如果任何参数为空 - 另请参见:
-
findVarHandle(Class, String, Class)
-
findSetter
public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException
产生一个给非静态字段写入访问权限的方法句柄。 方法句柄的类型将具有void返回类型。 方法句柄将使用两个参数,包含该字段的实例和要存储的值。 第二个参数将是字段的值类型。 代表查找类立即执行访问检查。- 参数
-
refc
- 访问该方法的类或接口 -
name
- 该字段的名称 -
type
- 字段的类型 - 结果
- 一个可以将值存储到字段中的方法句柄
- 异常
-
NoSuchFieldException
- 如果该字段不存在 -
IllegalAccessException
- 如果访问检查失败,或者该字段是static
-
SecurityException
- 如果一个安全管理器存在,它是 refuses access -
NullPointerException
- 如果任何参数为空 - 另请参见:
-
findVarHandle(Class, String, Class)
-
findVarHandle
public VarHandle findVarHandle(Class<?> recv, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException
产生一个VarHandle,可访问name
类中声明的类型为type
的非静态字段recv
。 VarHandle的变量类型是type
,它有一个坐标类型,recv
。代表查找类立即执行访问检查。
在以下情况下,不支持返回的VarHandle的某些访问模式:
- 如果该字段声明为
final
,则不支持写入,原子更新,数字原子更新和逐位原子更新访问模式。 - 如果字段的类型是比其他任何
byte
,short
,char
,int
,long
,float
,或double
然后数字原子更新的接入方式是不受支持的。 - 如果字段的类型是以外的任何其他
boolean
,byte
,short
,char
,int
或long
然后逐位原子更新的接入方式是不受支持的。
如果该字段声明为
volatile
则返回的VarHandle将根据其指定的访问模式覆盖对该字段的访问(有效地忽略volatile
声明)。如果字段类型为
float
或double
则数字和原子更新访问模式使用其逐位表示比较值(分别为Float.floatToRawIntBits(float)
和Double.doubleToRawLongBits(double)
)。- API Note:
-
由数字和原子更新访问模式执行的
float
值或double
值的float
比较不同于原语==
运算符和Float.equals(java.lang.Object)
和Double.equals(java.lang.Object)
方法,特别是关于比较NaN值或比较-0.0
与+0.0
。 当执行比较和设置或与这些值的比较和交换操作时,应注意,因为操作可能会意外失败。 在Java中,许多可能的NaN值被认为是NaN
,尽管Java提供的IEEE 754浮点运算没有区别它们。 如果预期值或见证值为NaN值,并且将其转换(可能以平台特定的方式)为另一个NaN值,因此具有不同的按位表示(参见Float.intBitsToFloat(int)
或Double.longBitsToDouble(long)
了解更多详细信息),则可能会发生操作失败。 值-0.0
和+0.0
具有不同的位表示,但在使用基元==
运算符时被认为是相等的。 如果,例如,数字算法计算的预期值是说可能会出现操作故障-0.0
和先前计算的见证价值被说+0.0
。 - 参数
-
recv
- 类型为R
的接收器类,声明非静态字段 -
name
- 该字段的名称 -
type
- 字段的类型,类型为T
- 结果
- 一个VarHandle可以访问非静态字段。
- 异常
-
NoSuchFieldException
- 如果该字段不存在 -
IllegalAccessException
- 如果访问检查失败,或者该字段是static
-
SecurityException
- 如果一个安全管理员存在,它是 refuses access -
NullPointerException
- 如果任何参数为空 - 从以下版本开始:
- 9
- 如果该字段声明为
-
findStaticGetter
public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException
产生一个给静态字段读取访问权限的方法句柄。 方法句柄的类型将具有字段值类型的返回类型。 方法句柄将不会引用任何参数。 代表查找类立即执行访问检查。如果调用了返回的方法句柄,则该字段的类将被初始化,如果尚未初始化。
- 参数
-
refc
- 访问该方法的类或接口 -
name
- 该字段的名称 -
type
- 字段的类型 - 结果
- 一个可以从字段加载值的方法句柄
- 异常
-
NoSuchFieldException
- 如果该字段不存在 -
IllegalAccessException
- 如果访问检查失败,或者该字段不是static
-
SecurityException
- 如果一个安全管理员存在,它是 refuses access -
NullPointerException
- 如果任何参数为空
-
findStaticSetter
public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException
生成方法句柄,给静态字段写权限。 方法句柄的类型将具有void返回类型。 方法句柄将使用单个参数,字段的值类型,要存储的值。 代表查找类立即执行访问检查。如果调用了返回的方法句柄,则该字段的类将被初始化,如果尚未初始化。
- 参数
-
refc
- 访问该方法的类或接口 -
name
- 该字段的名称 -
type
- 字段的类型 - 结果
- 一个可以将值存储到字段中的方法句柄
- 异常
-
NoSuchFieldException
- 如果该字段不存在 -
IllegalAccessException
- 如果访问检查失败,或者该字段不是static
-
SecurityException
- 如果一个安全管理员存在,它是 refuses access -
NullPointerException
- 如果任何参数为空
-
findStaticVarHandle
public VarHandle findStaticVarHandle(Class<?> decl, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException
产生一个VarHandle,可以访问name
类中声明的类型为type
的静态字段decl
。 VarHandle的变量类型是type
,它没有坐标类型。代表查找类立即执行访问检查。
如果返回的VarHandle操作,则声明类将被初始化,如果尚未初始化。
在以下情况下,不支持返回的VarHandle的某些访问模式:
- 如果该字段声明为
final
,则不支持写入,原子更新,数字原子更新和按位原子更新访问模式。 - 如果字段的类型是比其他任何
byte
,short
,char
,int
,long
,float
,或double
,然后数字原子更新的接入方式是不受支持的。 - 如果字段的类型是以外的任何其他
boolean
,byte
,short
,char
,int
或long
然后逐位原子更新的接入方式是不受支持的。
如果该字段声明为
volatile
则返回的VarHandle将根据其指定的访问模式覆盖该字段的访问(有效地忽略volatile
声明)。如果字段类型为
float
或double
则数字和原子更新访问模式使用其逐位表示比较值(分别见Float.floatToRawIntBits(float)
和Double.doubleToRawLongBits(double)
)。- API Note:
-
按照数字和原子更新访问模式执行的
float
值或double
值的比较比较,不同于原语==
运算符和Float.equals(java.lang.Object)
和Double.equals(java.lang.Object)
方法,特别是关于比较NaN值或比较-0.0
与+0.0
。 当执行比较和设置或与这些值的比较和交换操作时,应注意,因为操作可能会意外失败。 在Java中,许多可能的NaN值被认为是NaN
,尽管Java提供的IEEE 754浮点运算没有区别它们。 如果预期值或见证值为NaN值,并且将其转换(可能以平台特定方式)转换为另一个NaN值,并因此具有不同的逐位表示(参见Float.intBitsToFloat(int)
或Double.longBitsToDouble(long)
了解更多详细信息),则可能会发生操作失败。 值-0.0
和+0.0
具有不同的位表示,但在使用基元==
运算符时被认为是相等的。 如果,例如,数字算法计算的预期值是说可能会出现操作故障-0.0
和先前计算的见证价值被说+0.0
。 - 参数
-
decl
- 声明静态字段的类 -
name
- 该字段的名称 -
type
- 字段的类型,类型为T
- 结果
- 一个VarHandle可以访问静态字段
- 异常
-
NoSuchFieldException
- 如果该字段不存在 -
IllegalAccessException
- 如果访问检查失败,或者该字段不是static
-
SecurityException
- 如果一个安全管理员存在,它是 refuses access -
NullPointerException
- 如果任何参数为空 - 从以下版本开始:
- 9
- 如果该字段声明为
-
bind
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); mh1 = mh1.withVarargs(mh0.isVarargsCollector()); return mh1;
defc
是receiver.getClass()
或receiver.getClass()
的超类型,其中所请求的方法可以被查找类访问。 (不像bind
,bindTo
不保留变量元数。另外,bindTo
可能抛出ClassCastException
中的实例,其中bind
将引发IllegalAccessException
,如在其中所述构件是所述壳体protected
和接收器通过限制findVirtual
到查找类)。- 参数
-
receiver
- 访问该方法的对象 -
name
- 方法的名称 -
type
- 方法的类型,省略了接收方参数 - 结果
- 所需的方法句柄
- 异常
-
NoSuchMethodException
- 如果方法不存在 -
IllegalAccessException
- 如果访问检查失败,或者方法的变量asVarargsCollector
修饰符位置位,并且asVarargsCollector
失败 -
SecurityException
- 如果安全管理器存在,它是 refuses access -
NullPointerException
- 如果任何参数为空 - 另请参见:
-
MethodHandle.bindTo(java.lang.Object)
,findVirtual(java.lang.Class<?>, java.lang.String, java.lang.invoke.MethodType)
-
unreflect
public MethodHandle unreflect(方法 m) throws IllegalAccessException
做一个direct method handle的m ,如果查找类有权限。 如果m是非静态的,则接收者参数被视为初始参数。 如果m是虚拟的,则在每次呼叫时都应该重写。 与Core Reflection API不同,异常不包装。 方法句柄的类型将是方法的类型,接收器类型为前缀(但仅当它是非静态的)时。 如果方法的accessible
标志未设置,则代表查找类立即执行访问检查。 如果m不是公开的,不要与不信任方共享所产生的句柄。当且仅当方法的变量arity修饰符位(
0x0080
)被设置时,返回的方法句柄将具有variable arity 。如果m是静态的,并且如果返回的方法句柄被调用,那么方法的类将被初始化,如果它还没有被初始化。
- 参数
-
m
- 反映的方法 - 结果
- 可以调用反射方法的方法句柄
- 异常
-
IllegalAccessException
- 如果访问检查失败,或者如果方法的变量arity修饰符位被设置并且asVarargsCollector
失败 -
NullPointerException
- 如果参数为空
-
unreflectSpecial
public MethodHandle unreflectSpecial(方法 m, Class<?> specialCaller) throws IllegalAccessException
为反映的方法生成方法句柄。 它会绕过检查重写在接收机,方法as if called从invokespecial
从明确内指令指定specialCaller
。 方法句柄的类型将是该方法的类型,前面加上适当受限的接收器类型。 (接收器类型为specialCaller
或子类型。)如果未设置方法的accessible
标志,则代表查找类立即执行访问检查,就像invokespecial
指令被链接一样。在方法解析之前,如果显式指定的调用者类与lookup类不相同,或者该查找对象没有private access权限,则访问失败。
如果且仅当方法的变量arity修饰符位(
0x0080
)被设置时,返回的方法句柄将具有variable arity 。- 参数
-
m
- 反映的方法 -
specialCaller
- 这个类specialCaller
叫做方法 - 结果
- 可以调用反射方法的方法句柄
- 异常
-
IllegalAccessException
- 如果访问检查失败,或者方法为static
,或者方法的变量arity修饰符位是否设置并且asVarargsCollector
发生故障 -
NullPointerException
- 如果任何参数为空
-
unreflectConstructor
public MethodHandle unreflectConstructor(Constructor<?> c) throws IllegalAccessException
为反射的构造函数生成方法句柄。 方法句柄的类型将是构造函数的类型,返回类型更改为声明类。 方法句柄将执行一个newInstance
操作,在传递给方法句柄的参数上创建构造函数类的新实例。如果未设置构造函数的
accessible
标志,则代表查找类立即执行访问检查。当且仅当构造函数的变量arity修饰符位(
0x0080
)被设置时,返回的方法句柄将具有variable arity 。如果调用返回的方法句柄,那么构造函数的类将被初始化,如果还没有被初始化。
- 参数
-
c
- 反映的构造函数 - 结果
- 可以调用反射的构造函数的方法句柄
- 异常
-
IllegalAccessException
- 如果访问检查失败或方法的变量修改位置1,并且asVarargsCollector
失败 -
NullPointerException
- 如果参数为空
-
unreflectGetter
public MethodHandle unreflectGetter(Field f) throws IllegalAccessException
产生方法句柄,给予反映字段的读访问权限。 方法句柄的类型将具有字段值类型的返回类型。 如果该字段是静态的,方法句柄将不会引用任何参数。 否则,其单个参数将是包含该字段的实例。 如果字段的accessible
标志未设置,则代表查找类立即执行访问检查。如果该字段是静态的,并且如果返回的方法句柄被调用,则该字段的类将被初始化,如果它还没有被初始化。
- 参数
-
f
- 反射场 - 结果
- 一个方法句柄,可以从反射的字段加载值
- 异常
-
IllegalAccessException
- 如果访问检查失败 -
NullPointerException
- 如果参数为空
-
unreflectSetter
public MethodHandle unreflectSetter(Field f) throws IllegalAccessException
产生一个方法句柄,给一个反射的字段写权限。 方法句柄的类型将具有void返回类型。 如果该字段是静态的,那么方法句柄将使用一个参数,即字段的值类型,要存储的值。 否则,两个参数将是包含该字段的实例和要存储的值。 如果字段的accessible
标志未设置,则代表查找类立即执行访问检查。如果该字段是静态的,并且如果返回的方法句柄被调用,则该字段的类将被初始化,如果它还没有被初始化。
- 参数
-
f
- 反映的领域 - 结果
- 一种可以将值存储到反射场中的方法句柄
- 异常
-
IllegalAccessException
- 如果访问检查失败 -
NullPointerException
- 如果参数为null
-
unreflectVarHandle
public VarHandle unreflectVarHandle(Field f) throws IllegalAccessException
产生一个VarHandle,可以访问f
类中声明的类型为T
的反射字段R
。 VarHandle的变量类型是T
。 如果该字段是非静态的,则VarHandle有一个坐标类型,R
。 否则,该字段是静态的,并且VarHandle没有坐标类型。代表查找类立即执行访问检查,而不管字段的
accessible
标志的值。如果该字段是静态的,并且如果返回的VarHandle被操作,则该字段的声明类将被初始化,如果它还没有被初始化。
在以下情况下,不支持返回的VarHandle的某些访问模式:
- 如果该字段声明为
final
,则不支持写入,原子更新,数字原子更新和逐位原子更新访问模式。 - 如果字段的类型是比其他任何
byte
,short
,char
,int
,long
,float
,或double
然后数字原子更新的接入方式是不受支持的。 - 如果字段的类型是以外的任何其他
boolean
,byte
,short
,char
,int
或long
然后逐位原子更新的接入方式是不受支持的。
如果该字段声明为
volatile
则返回的VarHandle将根据其指定的访问模式覆盖该字段的访问(有效地忽略volatile
声明)。如果字段类型为
float
或double
则数字和原子更新访问模式使用其逐位表示比较值(分别见Float.floatToRawIntBits(float)
和Double.doubleToRawLongBits(double)
)。- API Note:
-
由数字和原子更新访问模式执行的
float
值或double
值的按位比较与原语==
运算符和Float.equals(java.lang.Object)
和Double.equals(java.lang.Object)
方法的不同之处 在于 ,特别是关于比较NaN值或比较-0.0
与+0.0
。 当执行比较和设置或与这些值的比较和交换操作时,应注意,因为操作可能会意外失败。 在Java中,有许多可能的NaN值被认为是NaN
,尽管Java提供的IEEE 754浮点运算没有区分它们。 如果预期值或见证值是NaN值,并且它被转换(可能以平台特定的方式)到另一个NaN值,并且因此具有不同的位方式表示(参见Float.intBitsToFloat(int)
或Double.longBitsToDouble(long)
了解更多细节),则可能会发生操作失败。 值-0.0
和+0.0
具有不同的逐位表示,但在使用基元==
运算符时被认为是相等的。 如果,例如,数字算法计算的预期值是说可能会出现操作故障-0.0
和先前计算的见证价值被说+0.0
。 - 参数
-
f
- 反射字段,字段类型为T
,声明类型为R
- 结果
- 一个VarHandle可以访问非静态字段或静态字段
- 异常
-
IllegalAccessException
- 如果访问检查失败 -
NullPointerException
- 如果参数为空 - 从以下版本开始:
- 9
- 如果该字段声明为
-
revealDirect
public MethodHandleInfo revealDirect(MethodHandle target)
破解由此查找对象或类似的对象创建的一个direct method handle 。 执行安全和访问检查以确保该查找对象能够再现目标方法句柄。 这意味着如果目标是一个直接的方法句柄但是由一个不相关的查找对象创建,则破解可能会失败。 如果方法句柄是caller sensitive,并且由不同类的查找对象创建,则可能会发生这种情况。- 参数
-
target
- 一种直接的方法手柄来破解符号参考组件 - 结果
- 一个符号引用,可用于从此查找对象重建此方法句柄
- 异常
-
SecurityException
- 如果一个安全管理器存在,它是 refuses access -
IllegalArgumentException
- 如果目标不是直接方法句柄或访问检查失败 -
NullPointerException
- 如果目标是null
- 从以下版本开始:
- 1.8
- 另请参见:
-
MethodHandleInfo
-
hasPrivateAccess
public boolean hasPrivateAccess()
如果此查找具有PRIVATE
访问权限,则返回true
。- 结果
-
true
如果这个查找有PRIVATE
访问。 - 从以下版本开始:
- 9
-
-