私有成员是在类级别还是在对象级别进行访问。如果它在对象级别,则以下代码不应编译
class PrivateMember {
private int i;
public PrivateMember() {
i = 2;
}
public void printI() {
System.out.println("i is: "+i);
}
public void messWithI(PrivateMember t) {
t.i *= 2;
}
public static void main (String args[]) {
PrivateMember sub = new PrivateMember();
PrivateMember obj = new PrivateMember();
obj.printI();
sub.messWithI(obj);
obj.printI();
}
}
请说明在sub的messWithI()方法中访问obj的成员i是否有效
答案 0 :(得分:7)
正如DevSolar所说,它处于(顶级)级别。
来自section 6.6 of the Java Language Specification:
否则,如果会员或 那么构造函数被声明为private 当且仅当它被访问时才允许访问 发生在顶部的身体内 包含该等级的等级(第7.6节) 成员的声明或 构造
请注意,没有迹象表明它仅限于特定对象的成员。
从Java 7开始,the compiler no longer allows access to private members of type variables。因此,如果该方法具有类似public <T extends PrivateMember> void messWithI(T t)
的签名,则访问t.i
将是编译器错误。但是,这不会改变您的特定情况。
答案 1 :(得分:4)
请注意,您甚至不需要源级别访问来破坏私有字段。通过使用java.lang.reflect.AccessibleObject.setAccessibe()
,所有代码都可以访问所有其他代码的所有私有成员,除非您指定了不允许它的安全策略。
private
本身并不是一个安全功能!这只是对其他开发人员的一个强烈暗示,即某些内容是内部实现细节,代码中的其他部分不应该依赖于此。
答案 2 :(得分:3)
都不是。私有访问的范围限定在封闭的顶级类中,因此您可以访问同一顶级类中不同类的私有成员:
class PrivateAccess {
static class InnerOne {
private int value;
}
static class InnerTwo {
int getOne ( InnerOne other ) {
return other.value;
}
}
}
类访问的通常含义意味着您可以访问相同类型的其他实例的私有。在Java中,私有访问是在词法上而不是按类型确定的。
答案 3 :(得分:2)
班级。这个想法是类的代码(但没有别的)知道如何处理该类的对象。
如果您无论如何都可以访问类源代码,那么“隐藏”您的任何内容几乎没有意义。
答案 4 :(得分:1)
正如其他人所说,私有,默认访问(“包私有”),受保护,也许在JDK 7模块中是基于类的(嵌套类继承有非常奇怪的规则,我可以'记得)。但为什么呢?
主要是作为二进制(或更多)运算符的方法。为了有效实现,他们通常需要或更容易编写,而无需使用或修改公共API。浏览equals
的实现 - 在良好的代码中,您可以找到对this
进行少量方法调用的字段的直接访问。 (现在的性能方面与现代JVM内联常见调用大多无关,但代码质量问题仍然存在。)
答案 5 :(得分:0)
为了添加DevSolar的答案,我希望messWithI被声明为静态:
public static void messWithI(PrivateMember t) {
t.i *= 2;
} 我甚至很难读到你在没有“静态”暗示的情况下尝试做的事情......而且它也更容易回答你原来的问题 - 这就是私人成员的范围不仅限于有问题的实例。
答案 6 :(得分:0)
同一页说,在6.6.8小节中,您还可以找到以下声明:
私有类成员或构造函数只能在包含成员或构造函数声明的顶级类的主体内访问。它不是由子类继承的。
我们在此评估其访问权限的私有类成员是 i 。
public void messWithI()是一个存在于顶级类主体中的方法,其中 i 已被声明,正是 PrivateMember
你的构造符合上面的陈述,这就是它运行没有问题的原因。
Thas是另一种说法与Jon和Devsolar相同的方式。
类成员的访问修饰符与编写代码的位置(在哪个包中以及在哪个类中)相关,而不管授予访问权限的成员类型:类成员还是实例成员。
逻辑上,如果您没有该类的实例,则不能使用类的实例成员,但这是与成员生命周期相关的另一个问题。