为什么你能在Java和.Net中反映和调用(不是那么)私有方法

Joh*_*ley 4 c# java reflection scope

在Java和C#中,都可以通过反射调用私有方法(如下所示).

  • 为什么允许这样做?
  • 这样做的后果是什么?
  • 它应该在未来的语言版本中被删除吗?
  • 其他语言/平台是否允许这样做?如果我在Java和C#中都有这个类

这是一个例子

public class Foo
{
    private void say() { WriteToConsoleMethod("Hello reflected world"); }
}
Run Code Online (Sandbox Code Playgroud)

哪里WriteToConsole()是特定于语言的,那么我可以运行以下命令来调用私有say()方法:

C#

Foo f = new Foo();
var fooType = f.GetType();
var mi = fooType.GetMethod("say", BindingFlags.NonPublic | BindingFlags.Instance);
mi.Invoke(f, null);
Run Code Online (Sandbox Code Playgroud)

Java的

Foo f = new Foo();
Method method = f.getClass().getDeclaredMethod("say", null);
method.setAccessible(true);
method.invoke(f, null);
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,它并不明显,但也不难.

Jon*_*eet 18

在Java和.NET中,仅当您具有足够的权限时才允许这样做.直接从命令行运行的代码(通常)以"完全信任"模式运行.如果您尝试在限制性更强的环境中执行相同的操作,则会失败.然而,访问控制更多地是关于封装而不是安全性.如果您在完全信任的情况下运行,那么您可能已经有足够的权限启动原生方法来直接探测内存...

  • 为什么允许?有时它可以很方便.它应该小心对待,但它可能是有用的.

  • 有什么后果?你的代码变得脆弱; 你正在以一种它不期望的方式与一种类型进行交互.

  • 它应该在未来的语言版本中被删除吗?它首先是一个平台功能而不是语言功能,但不,我不认为它应该删除.

  • 其他语言/平台是否允许这样做?我不确定......但我不会感到惊讶.

  • "有时它可以很方便" - 我发现我曾经使用反射来测试私有方法.有人可能会认为,在封装时,应该通过提供的接口和公共方法对其进行测试.但有时这些私有方法将一些复杂的逻辑封装在一些有趣的边缘情况下,直接单元测试确实可以改善开发.所以是的,有时可以派上用场! (4认同)