I came across the following "strange" feature today - if you have a reference to an object from the class A in the body of the class A you can access the private fields of this object - i.e:
public class Foo{
private int bar;
private Foo foo;
public void f()
{
if(foo.bar == bar) // foo.bar is visible here?!
{
//
}
}
}
Anyone has a good explanation about this?
Access modifiers work at the class level, not at the instance level: all code in the same class can access private members of all instances of the class.
Nothing particularly strange about it.
It is intended to be this way.
Citing the Java Language Specification:
A member (class, interface, field, or method) of a reference (class, interface, or array) type or a constructor of a class type is accessible only if the type is accessible and the member or constructor is declared to permit access:
- ...
- (Otherwise,) if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member.
- ...
Since f() is a member of Foo, it has the privilege to access the private members of Foo. It's not a surprise to me.
It makes sense if you consider the intention of the 'private' modifier to hide implementation details.
Try thinking of it in terms of "this should be private to this class" (which in Java equates to "this should be private to this source file") rather than "this should be private to this instance".
Because private doesn't mean its private from outside the Object but private from other Classes. You are inside of Foo, therefore you can see bar.
That way do private Constructors work in Singletons etc.
Those keywords are class-oriented, not object-oriented. So it just looks and sees "oh huh, an object of class Foo is trying to access a private object on Foo. Well, that's fine".
@Michael
's answer is correct. The behaviour is the same for .NET
for @asenovm
's code.
In addition , It's same for inner classes as well for Java
. Even though you define a variable as private you can access it. I surprised when I encountered at first because it's different for C#
.
public class WrapperClass
{
public static class NotThreadsafe {
private int x = 0;
//....
}
public static void main(String[] args) {
final NotThreadsafe nts=new NotThreadsafe();
int x = nts.x ; // !!! THIS IS ACCESSIBLE AS WELL FOR JAVA BUT NOT.NET
}
}
This is not same for C#
nested classes. If you paste this code to visual studio it doesn't work. Compiler bothers for access levels.