gpt4 book ai didi

java - Lambda 对私有(private)方法的可访问性

转载 作者:搜寻专家 更新时间:2023-11-01 01:32:01 24 4
gpt4 key购买 nike

我对以下情况感到困惑。

考虑两个包含以下类的包 ab:

1) MethodInvoker 只是在给定对象上调用 call():

package b;
import java.util.concurrent.Callable;
public class MethodInvoker {
public static void invoke(Callable r) throws Exception {
r.call();
}
}

2)

package a;
import b.MethodInvoker;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;
public class Test {

private static Void method() {
System.out.println("OK");
return null;
}

public static void main(String[] args) throws Exception {
Method method = Test.class.getDeclaredMethod("method");
method.invoke(null); // ok

// TEST 1
MethodInvoker.invoke(() -> {
return method.invoke(null); // ok (hmm....
});

// TEST 2
MethodInvoker.invoke(new Callable() {
@Override
public Object call() {
return method(); // ok (hm...???
}
});

// TEST 3
MethodInvoker.invoke(new Callable() {
@Override
public Object call() throws Exception {
return method.invoke(null); // throws IllegalAccessException, why???

}
});
}
}

我明确地使 method() private 来测试如何在 Test 类范围之外调用它。我通常对所有 3 个案例感到困惑,因为我发现它们相互矛盾。我通常希望所有这些都应该以相同的方式工作。至少我希望如果 TEST 3 抛出 IllegalAccessException,那么 TEST 2 也应该这样做。但是测试 2 工作正常!

有人可以根据 JLS 给出严格的解释,为什么这些案例中的每一个都能正常工作?

最佳答案

TEST1 和 TEST3 之间的差异归结为 lambda 和匿名类的实现方式之间的差异。

查看这些特殊情况的实际字节码总是很有趣。 https://javap.yawk.at/#jXcoec

TEST1 lambda :

lambda 表达式在其定义的类中被转换为方法。传递对该方法的方法引用。由于 lambda 方法是类的一部分,它可以直接访问类的私有(private)方法。 method.invoke()有效。

TEST3 匿名类:

匿名类被转换为类。 method.invoke() 在那个不应访问私有(private)方法的类中被调用。由于反射,合成方法的工作区不起作用。

测试 2:为了允许嵌套类访问其外部类的私有(private)成员,引入了合成方法。如果您查看字节码,您会看到一个带有签名 static java.lang.Void access$000(); 的方法,它将调用转发给 Void method()

关于java - Lambda 对私有(private)方法的可访问性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42011685/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com