views:

1234

answers:

7

Is the private member access at the class level or at the object level. If it is at the object level, then the following code should not compile

    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();
   }
}

Please clarify if accessing the member i of obj within the messWithI() method of sub is valid

+1  A: 

Class level. The idea is that the code of a class (but nothing else) knows how to handle objects of that class.

If you have access to the class source code anyway, there is little sense in "hiding" anything from you.

DevSolar
+4  A: 

As DevSolar has said, it's at the (top level) class level.

From section 6.6 of the Java Language Specification:

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 or constructor.

Note that there's no indication that it's restricted to members for a particular object.

Jon Skeet
+1  A: 

Note that you don't even need source level access to mess with private fields. By using java.lang.reflect.AccessibleObject.setAccessibe(), all code can access all private members of all other code unless you specify a security policy that disallows it.

private is not by itself a security feature! It is merely a strong hint to other developers that something is an internal implementation detail that other parts on the code should not depend on.

Michael Borgwardt
private (and default access/"package private") are primary security features of Java!! setAccessible has a security check on it.
Tom Hawtin - tackline
The default security policy allows it, so it can hardly be considered a "primary security feature". Most developers' code will run with the default security policy, so they should not put undue faith on private members being inaccessible.
Michael Borgwardt
A: 

Just to add to DevSolar's answer, I would expect messWithI to be declared static as such:

public static void messWithI(PrivateMember t) {
  t.i *= 2;

} I had a hard time even reading what it is that you were trying to do without the 'static' hint... And it also makes it easier to answer your original question -- which is that private members are not limited in scope to just the instance in question.

+3  A: 

Neither. Private access is scoped to the enclosing top-level class, so you can access private members of different class in the same top-level class:

class PrivateAccess {
    static class InnerOne {
        private int value;
    }

    static class InnerTwo {
        int getOne ( InnerOne other ) {
            return other.value;
        }
    }
}

The usual meaning of class access means that you have access to privates of other instances of the same type. In Java, private access is determined lexically, not by type.

Pete Kirkham
Technically it doesn't matter whether you talk about classes or enclosing outer classes. It's just that private is a bit more public than might be expected or wanted.
Tom Hawtin - tackline
A: 

As others have stated, private, default access ("package private"), protected and perhaps in JDK 7 module are class based (there are very strange rules for nested classes inheritance that I can't remember). But why?

Primarily it's down to methods that act as binary (or more) operators. For efficient implementation they often require or are easier to write without having to use or modify the public API. Have a look through at implementations of equals - in good code you'll find direct access of fields with few method calls to this. (The performance aspect of this is now mostly irrelevant with modern JVMs inlining common calls, but the code quality issue is still there.)

Tom Hawtin - tackline
A: 

The same page says, in sub-section 6.6.8, you can also find the following statement:

A private class member or constructor is accessible only within the body of the top level class that encloses the declaration of the member or constructor. It is not inherited by subclasses.

The private class member whose access we evaluate here is i.

public void messWithI() is a method that exists within the body of the top level class where i has been declared, which is, precisely, PrivateMember.

Your construct meets the statement above, and that is why it runs without problems.

Thas is another way to say the same as Jon and Devsolar.

Access modifiers for class members are related to where the code is written, (in which package, and in which class), regardless of what kind of member the access gets granted: a class member or an instance member.

Logically, you cannot use an instance member of a class if you do not have an instance of the class, but that is a different issue, related to the life-cycle of the member.

Rafa Sanchez