在Java中,private
访问修饰符被认为是安全的,因为它在类之外是不可见的。然后外界也不知道那种方法。
但我认为Java反射可以用来打破这个规则。请考虑以下案例:
public class ProtectedPrivacy{
private String getInfo(){
return "confidential";
}
}
现在从另一个班级我将获得信息:
public class BreakPrivacy{
public static void main(String[] args) throws Exception {
ProtectedPrivacy protectedPrivacy = new ProtectedPrivacy();
Method method = protectedPrivacy.getClass().getDeclaredMethod("getInfo", null);
method.setAccessible(true);
Object result = method.invoke(protectedPrivacy);
System.out.println(result.toString());
}
}
此时我只是认为私有方法安全,因为做上面的事情我们必须知道方法名称。但是如果包含由其他人编写的私有方法的类我们没有那些可见性。
但是我的观点因为下面的代码行而变得无效。
Method method[] = new ProtectedPrivacy().getClass().getDeclaredMethods();
现在这个method[]
包含了上面需要做的所有事情。我的问题是,有没有办法避免使用Java反射这类事情?
我引用Java Documentation的一些观点来澄清我的问题。
选择访问级别的提示:
如果其他程序员使用您的课程,您需要确保错误 从滥用不可能发生。访问级别可以帮助您这样做。使用 对特定内容有意义的最严格的访问级别 会员。除非你有充分的理由不使用私人,否则请使用私人。
答案 0 :(得分:95)
这取决于你所说的“安全”。如果你正在运行一个允许这种事情的安全管理器,那么是的,你可以用反射做各种讨厌的事情。但是在那种环境中,库可能只是被修改以使方法公开。
在这样的环境中,访问控制实际上是“建议性的” - 您实际上相信代码可以很好地发挥作用。如果不信任您正在运行的代码,则应使用限制性更强的安全管理器。
答案 1 :(得分:40)
访问修饰符与安全性无关。实际上,您可以而且应该将访问修饰符视为安全性的反向 - 它不是为了保护您的数据或算法,而是为了保护人们免于了解您的数据和算法的要求。这就是默认修饰符是包的原因 - 如果它们正在处理它们可能已经需要知道的包。
随着对数据和代码方法的了解,知道何时以及如何使用它的响应能力。你没有在你的inIt方法上设置私人信息以防止别人发现它,你这样做是因为(a)他们不会知道你只在foo之后调用它并且只有当bar = 3.1415和(b)因为它对他们没有好处。
访问修饰符可以用一个简单的短语“TMI,伙计,我所以不需要知道”来总结。
答案 2 :(得分:7)
通过说'安全',您正在保护您或其他开发人员,他们使用您的API通过调用您的私有方法来损害对象。但是,如果您或他们真的需要调用此方法,他们可以使用Reflection。
答案 3 :(得分:6)
问题是你是谁试图保存。在我看来,你的代码的这样一个客户端是亏本的。
试图访问上述类private
成员的任何代码(由您或其他人编写)实际上都在挖掘自己的坟墓。 private
成员未参与公开 API,如有更改,恕不另行通知。如果客户端碰巧以上面给出的方式使用其中一个私有成员,那么如果它升级到私有成员被修改的API的较新版本,它将会中断。
答案 4 :(得分:5)
有了设施,就有了责任。你有不能做的事情,& 可以做的事情,但不应该做。
私人修饰符以最受限制的方式提供/使用。在课堂外不应看到的成员应被定义为私人。但是,正如我们所看到的那样,这可以用反思打破但这并不意味着你不应该使用私人 - 或者他们不安全。关于你应该明智地或以建设性的方式使用事物(如反思)。
答案 5 :(得分:5)
假设您信任API的客户端程序员,另一种看待他们使用这些特定功能的“安全”方式。
您公开提供的功能应该为您的代码提供清晰,记录良好,很少变化的界面。您的私有函数可以被视为实现细节,并且可能会随着时间的推移而发生变化,因此直接使用是不安全的。
如果客户程序员竭尽全力绕过这些抽象,那么他们就会宣称他们知道自己在做什么。更重要的是,他们知道它不受支持,可能会停止使用未来版本的代码。
答案 6 :(得分:5)
private
不是为了安全,而是为了保持代码清洁并防止出错。它允许用户模块化代码(以及如何开发代码),而不必担心所有其他模块的细节
一旦您发布了代码,人们就可以弄清楚它是如何工作的。如果您最终希望代码在计算机上运行,则无法“隐藏”逻辑。即使编译成二进制文件也是一种混淆程度。
因此,您无法设置API来执行您不希望其他人能够调用的特殊事物。对于Web API,您可以将要控制的方法放在服务器端。