This code runs fine in 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);
}
}
But, in java 17 it throws an exception:
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)
- Why?
- Is it not supposed to work in java 17?
- Is there any way to work around this?
Obviously this is an example. What the real code attempts to do is to replace the lambdas this reference with a spy object, invoke the lambda and then capture the arguments given to this.parseInt. Ultimately what it does is to serialize the first method invocation of a lambda.
Aucun commentaire:
Enregistrer un commentaire