T.K.
T.K.

Reputation: 2259

Java static methods accessing private variables

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

Answers (5)

Learner
Learner

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

Matthew Cox
Matthew Cox

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

davin
davin

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

Costi Ciudatu
Costi Ciudatu

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

v6ak
v6ak

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

Related Questions