当前位置: 首页 > 知识库问答 >
问题:

Java17反射:分配lambda对象的"this"引用

施利
2023-03-14

此代码在 java 11 中运行良好。

package test;

import org.junit.Assert;
import org.junit.Test;

import java.lang.reflect.Field;
import java.util.function.Consumer;

public class LambdaArg1ReflectionTest {
    @Test
    public void test() throws IllegalAccessException {
        // Create a lambda with reference to parent class (this)
        Consumer<String> lambda = s -> this.parseInt(s, 7);

        // Get the value from the lambdas "this" reference
        Field lambda_arg1_field = lambda.getClass().getDeclaredFields()[0];
        lambda_arg1_field.setAccessible(true);
        Object lambda_arg1_value = lambda_arg1_field.get(lambda);
        // Assert that the value is as we expected
        Assert.assertEquals(this, lambda_arg1_value);

        // Attempt to assign the same value
        lambda_arg1_field.set(lambda, lambda_arg1_value);
    }

    private int parseInt(String s, int i) {
        return Integer.parseInt(s + i);
    }
}

但是,在java 17中,它抛出了一个异常:

    java.lang.IllegalAccessException: Can not set final test.LambdaArg1ReflectionTest field test.LambdaArg1ReflectionTest$$Lambda$40/0x0000000800c191a8.arg$1 to test.LambdaArg1ReflectionTest

    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:76)
    at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:80)
    at java.base/jdk.internal.reflect.UnsafeQualifiedObjectFieldAccessorImpl.set(UnsafeQualifiedObjectFieldAccessorImpl.java:79)
    at java.base/java.lang.reflect.Field.set(Field.java:799)
    at test.LambdaArg1ReflectionTest.test(LambdaArg1ReflectionTest.java:23)
  • 为什么
  • 它不应该在java17中工作吗
  • 有没有办法解决这个问题

显然这是一个例子。真正的代码试图做的是用间谍对象替换lambdas this引用,调用lambda,然后捕获给this.parseInt的参数。最终,它所做的是序列化lambda的第一个方法调用。

共有1个答案

公西毅
2023-03-14

简短回答:不,你不能这样做

解释:我不测试在以前的java版本上是否可以工作,但在j17中,我不能:您使用的lambda基本上是接近innerClass的东西,并且您正在尝试编辑在其中声明的类以及通过使用jvm中的类模式完成的引用。顺便说一下,消息非常明确,引用是最终的,因此不允许设置。

一个解决办法可能是把λ变成双消费者

BiConsumer<LambdaArg1ReflectionTest,String> lambda = (o,s) -> o.parseInt(s, 7);

这样你可以指定应用你的函数的对象,包括一个存根。

 类似资料:
  • 问题内容: 我从javascript对象内部进行了一些Ajax调用。 在onreadystatechange函数内部,它不再引用主对象,因此我无法访问this.foo。我如何在XMLHttpRequest事件中保留对主对象的引用? 问题答案: 最简单的方法通常是将的值存储在局部变量中: 我也怀疑您的标识符确实是构造函数(您正在分配属性)。 如果是这种情况,请不要忘记添加正确的属性(因为您正在替换整

  • 问题内容: 给定班级价值: 我正在尝试使用创建该类的新实例: 从主要: 这不起作用,Eclipse的输出: 如果是这样,怎么可以用我创建了一个新的价值目标,在那里我调用的? 谢谢 问题答案: 您需要为此找到确切的构造函数。只能用于调用null构造函数。所以写

  • 本文向大家介绍JavaScript对象反射用法实例,包括了JavaScript对象反射用法实例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了JavaScript对象反射用法。分享给大家供大家参考。具体如下: 这里讲述JavaScript对象反射用法,涉及反射DOM对象和自定义对象 希望本文所述对大家的javascript程序设计有所帮助。

  • 本文向大家介绍php面向对象之反射功能与用法分析,包括了php面向对象之反射功能与用法分析的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了php面向对象之反射功能与用法。分享给大家供大家参考,具体如下: 个人对反射定义的理解: 首先得说说什么叫反射。对于一个新手来说,反射这个概念常常给人一种似懂非懂的 感觉,不知道该如何下手操作。 反射是指:指在PHP运行状态中,扩展分析PHP程序,导出或

  • 问题内容: 如何使用反射创建内部类对象?内部和外部类均具有不带参数的默认构造函数 问题答案: “如果构造函数的声明类是非静态上下文中的内部类,则构造函数的第一个参数必须是封闭的实例;请参见 Java™语言规范的 15.9.3节。” 这意味着您永远不能使用; 构造内部类。相反,您必须使用带有单个实例的构造函数。这是一些示例代码,演示其用法: (请注意,在标准Java术语中, 内部类 始终是非静态的。