Reputation: 2259
I was under the impression that private non-static variables could only be accessed by methods called on the object that the variables reside in, but this is not the case. Could someone please explain the reasoning behind why the following compiles and runs?
public class Sandbox {
private String _privateString = "unmodified";
public static void setPrivateString(String str, Sandbox s) {
s._privateString = str;
}
public String toString()
{
return _privateString;
}
public static void main(String[] args) {
Sandbox s = new Sandbox();
setPrivateString("modified", s);
System.out.println(s);
}
}
Output:
modified
EDIT: The same is true in C#.
Upvotes: 19
Views: 23306
Reputation: 547
Your code is compiled because inside setPrivateString(String str, Sandbox s) you are accessing the private variable _privateString by reference variable s.
A non-static member can only access by instance variable from the static API.
Check this code
public class Sandbox {
public static void main(String[] args) {
Sandbox s = new Sandbox();
// testAccess();// If you uncomment this line you will get compile time error
s.testAccess();//can only access in this way
}
private void testAccess() {
System.out.println("can only access by instance variable from static method");
}
}
Upvotes: 0
Reputation: 13682
The rule is simple:
member methods of a class can access and modify private members of the same class regardless of their visibility.
Upvotes: 4
Reputation: 45555
Private member variables of class A can be accessed (i.e. read/written to) by any method of class A (static or non-static), so in your example, since the method changing the string is a method of the same class the member belongs to, it is granted access to the variable.
The reason is because a class is considered a self-contained body of logic (i.e. a specific implementation), so it makes sense that privacy is contained within a class; there is no reason to exclude static methods from that access right, since they are also part of the specific implementation the class provides.
Upvotes: 26
Reputation: 38245
You seem to be confusing visibility
with scope
. The instance variables are in the scope of an instance, so they cannot be accessed in a static method directly, but only with an instance reference qualifier: s._privateString
in your case.
However, this does not mean that instance variables are not visible for a static method inside the same class, as private
means visible inside the class (for any member with any scope).
Upvotes: 4
Reputation: 1656
As mentioned in some other posts, Java's visibility system is class-based, not an object-based one.
Note that this is utilized in the compiler: When you have nested classes and you access a private field of the outer class, a public synthetic static method is generated to allow the access. It is usually named "access$0" etc. You can create a bytecode that violates encaplulation without the Reflection API by using these synthetic methods. You can also access them from the Reflection API without enabling access to private members. Many crazy things can be done...
If there was not such visibility system, compiler probably would need to compile it elsehow.
... Hoewver, the end-programmer usually don't need to know this detail. IDEs don't include synthetic methods in code completion and I hope that compilers (except Jasmin) don't allow you to use it. So if you don't generate bytecode and don't use Reflection API and you ignore these methods in the stacktrace, you probably don't need to know this detail.
Upvotes: 3