那如果把接口实现为一个私有内部类,又会怎么样呢?下面展示了这种情况:
public C.f() InnerA$C public C.g() package C.u() protected C.v() private C.w()
这里对反射仍然没有任何东西可以隐藏。那么如果是匿名类呢?
输出结果:
public C.f() AnonymousA$1 public C.g() package C.u() protected C.v() private C.w()
看起来任何方式都没法阻止反射调用那些非公共访问权限的方法。对于字段来说也是这样,即便是 private 字段:
输出结果:
i = 1, I'm totally safe, Am I safe? f.getInt(pf): 1 i = 47, I'm totally safe, Am I safe? f.get(pf): I'm totally safe i = 47, I'm totally safe, Am I safe? f.get(pf): Am I safe? i = 47, I'm totally safe, No, you're not!
但实际上 final 字段在被修改时是安全的。运行时系统会在不抛出异常的情况下接受任何修改的尝试,但是实际上不会发生任何修改。
通常,所有这些违反访问权限的操作并不是什么十恶不赦的。如果有人使用这样的技术去调用标志为 private 或包访问权限的方法(很明显这些访问权限表示这些人不应该调用它们),那么对他们来说,如果你修改了这些方法的某些地方,他们不应该抱怨。
另一方面,总是在类中留下后门,也许会帮助你解决某些特定类型的问题(这些问题往往除此之外,别无它法)。
总之,不可否认,反射给我们带来了很多好处。
程序员往往对编程语言提供的访问控制过于自信,甚至认为 Java 在安全性上比其它提供了(明显)更宽松的访问控制的语言要优越。然而,正如你所看到的,事实并不是这样。



