Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 8使用lambda访问私有成员?_Java_Lambda_Java 8 - Fatal编程技术网

Java 8使用lambda访问私有成员?

Java 8使用lambda访问私有成员?,java,lambda,java-8,Java,Lambda,Java 8,给出私有成员访问的答案,同时给出基于lambda的成员访问的答案。然而,通过将两者结合起来,我仍然无法找到通过lambda访问私人成员的方法。错误: Caused by: java.lang.IllegalAccessException: member is private: XXX from ZZZ at java.lang.invoke.MethodHandles$Lookup.revealDirect(MethodHandles.java:1353) at java.lang.invoke

给出私有成员访问的答案,同时给出基于lambda的成员访问的答案。然而,通过将两者结合起来,我仍然无法找到通过lambda访问私人成员的方法。错误:

Caused by: java.lang.IllegalAccessException: member is private: XXX from ZZZ
at java.lang.invoke.MethodHandles$Lookup.revealDirect(MethodHandles.java:1353)
at java.lang.invoke.AbstractValidatingLambdaMetafactory.<init>(AbstractValidatingLambdaMetafactory.java:131)
at java.lang.invoke.InnerClassLambdaMetafactory.<init>(InnerClassLambdaMetafactory.java:155)
at java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:299)
原因:java.lang.IllegalAccessException:成员是私有的:来自ZZZ的XXX
在java.lang.invoke.MethodHandles$Lookup.RevelDirect(MethodHandles.java:1353)中
位于java.lang.invoke.AbstractValidatingLambdaMetafactory。(AbstractValidatingLambdaMetafactory.java:131)
位于java.lang.invoke.InnerClassLambdaMetafactory。(InnerClassLambdaMetafactory.java:155)
位于java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:299)
是调用站点生成器的一部分的点。如何自定义生成器以控制其访问检查


更新:per的示例

关键部分是
查找
对象,该对象被传递到
LambdaMetafactory
,然后在其上调用
revealDirect

从:

执行安全和访问检查以确保此查找对象能够再现目标方法句柄。这意味着,如果目标是直接方法句柄,但由不相关的查找对象创建,则破解可能失败

因此,lambda表达式只能访问包含lambda表达式的类可访问的方法,因为JVM提供的
Lookup
对象将准确反映这些访问权限

这也适用于JavaBean方法,因为按照惯例,这些方法是
public


因此,如果要调用
private
方法,有三个选项:

  • 从具有访问权限的
    private
    方法的声明类中生成lambda实例。当这个类调用时,它将得到一个适当的
    查找
    实例

    类还可以创建具有所需功能的
    查找
    实例,并将其移交给另一个(受信任的)类,该类可以使用它执行此类反射操作。这正是执行
    invokedynamic
    指令时隐式发生的情况。包含
    invokedynamic
    指令的类指向
    LambdaMetaFactory
    中的引导方法,意味着这种信任

    因此,使用所有普通操作,它始终是具有访问权限的类,该类必须启用对另一个类的访问

  • 从Java9开始,使用获取对指定目标类具有私有访问权限的方法句柄。这是根据模块访问规则检查的。对于同一模块内的访问,这应该总是成功的
  • 使用更多的黑魔法来获得适当的
    查找
    实例。您链接的问题提到了非公开的查找。如果您得到这个实例并调用它,您将得到一个具有所需属性的实例。或者,您可以通过
    .in(declaringClass)
    创建受限查找对象,并覆盖其访问修饰符(由报告的修饰符)以启用完全访问。显然,这两种方法都需要对不属于
    公共
    Java API的字段进行访问覆盖

您应该提供引发异常的特定代码。通常,如果您可以自定义lambdas行为的任何方面,我会感到惊讶。lambda语法的语义受JLS中的精确规范的约束。感谢您提供的指针@holger。我们无法控制目标类,因此您的操作选项1不适用。选项2很好,转载于此:您认为有办法避免“黑魔法”吗?或者选项2将是最终答案?