44

How is the compiler not complaining when I write the following code?

public class MyClass 
{
    private int count;

    public MyClass(int x){
        this.count=x;
    }

    public void testPrivate(MyClass o){
        System.out.println(o.count);
    }   
}

Even though it is an instance of the same class in which testPrivate is written, shouldn't it give a compilation error at System.out.println(o.count)? After all, I am trying to access a private variable directly.
The code even runs fine.

Eran
  • 387,369
  • 54
  • 702
  • 768
Kanwaljeet Singh
  • 1,215
  • 4
  • 15
  • 25
  • 2
    Class MyClass knows the count variable, so no problem – SaintLike Dec 15 '14 at 11:05
  • 18
    It is private to the class, not the instance. Java doesn't try to stop your left hand from hitting your right hand. ;) – Peter Lawrey Dec 15 '14 at 11:06
  • Generate via Eclipse or IDEA hashCode and equals methods , they always look that way – Maksym Dec 15 '14 at 11:14
  • @PeterLawrey yes, but I was under the impression that compiler will smack me on my head if I even try to access private; But it is private to the class, which makes sense. Thank you – Kanwaljeet Singh Dec 15 '14 at 11:23
  • @KanwaljeetSingh surprisingly if you have a private field/method/constructor in a nested class you can still access it in another nested class of the same outer class. – Peter Lawrey Dec 15 '14 at 11:30

5 Answers5

60

A private member is accessible from any method within the class in which it is declared, regardless of whether that method accesses its own (this) instance's private member or some other instance's private member.

This is stated in JLS 6.6.1:

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

This feature of Java allows you to write methods that accept an instance of the class as an argument (for example - clone(Object other), compareTo(Object other)) without relying on the class having non private getters for all the private properties that need to be accessed.

Eran
  • 387,369
  • 54
  • 702
  • 768
  • 1
    TBH, I wasn't consciously aware of that, but it really is listed explicitely as a caveat for private in the Java tome on my desk (Listing 9.6 on page 200 in Krüger, Hansen: "Handbuch der Java-Programmierung", Addison-Wesley, 2012). No mention at first glance in Venners' "Inside the JAVA Virtual Machine", tho. Thanks for the question and the answers. – hiergiltdiestfu Dec 15 '14 at 11:12
  • 1
    Thank you, it makes sense now. I have always used `compareTo` and `equals` with getters. It was weird when I noticed we can access it without getters too. – Kanwaljeet Singh Dec 15 '14 at 11:20
14

Private fields are private to the class as a whole, not just to the object.

Other classes do not know that MyClass has a field called count; however, A MyClass object knows that another MyClass object has the count field.

Simba
  • 1,641
  • 1
  • 11
  • 16
6

Accessors are not security! They are encapsulation, to keep others from having to know about the code.

Consider if someone wrote a Quantum Bogo Sort, but disappeared once he quashed the last bug -- understanding the code causes one to be either deleted from the universe or to go mad.

Despite this minor drawback, if properly encapsulated, this should become your prefered sorting algorithm, as all fields and methods except Sort should be private.

You don't know how it works, and you don't want to know how it works, but it works and that's enough. If on the other hand, everything is public, and you have to understand how it does what it does to use it correctly -- that's just too much bother, I'll stick with quicksort.

Armen Michaeli
  • 8,625
  • 8
  • 58
  • 95
jmoreno
  • 12,752
  • 4
  • 60
  • 91
3

Though it is the instance of the same class in which testPrivate is written, but shouldn't it through a compiler error at System.out.println(o.count);

No. It will never throw a compilation error.

This is much similar to what a simple getter and setter does or a copy constructor does. Remember we can access private members using this.

public MyClass {
  private String propertyOne;
  private String propertyTwo;

  // cannot access otherObject private members directly
  // so we use getters
  // But MyClass private members are accessible using this.
  public MyClass(OtherClass otherObject) {
      this.propertyOne = otherObject.getPropertyOne();
      this.propertyTwo = otherObject.calculatePropertyTwo();
  }

  public void setPropertyOne(String propertyOne) {
      this.propertyOne = propertyOne;
  }

  public String getPropertyOne() {
      return this.propertyOne;
  }
}

Your testPrivate method accepts an instance of MyClass. Since testPrivate is a method inside MyClass, it will have access to private properties.

  public void testPrivate(MyClass o) {
      this.propertyOne = o.propertOne;
  }

Methods defined inside the class will always have access to it's private members, through this. and instance variable.

But if you define testPrivate outside of MyClass then, you won't have access to private members. There you will have to use a method or a setter or a getter.

WarFox
  • 4,933
  • 3
  • 28
  • 32
0

Methods, Variables and Constructors that are declared private can only be accessed within the declared class itself. Check the official documentation

Dinal24
  • 3,162
  • 2
  • 18
  • 32