Why are instance variables in Java always private?

Deepak picture Deepak · Oct 1, 2011 · Viewed 67.7k times · Source

I'm newbie to Java and I'm learning about encapsulation and saw an example where instance variables are declared as private in a class.

http://www.tutorialspoint.com/java/java_encapsulation.htm

I have 2 queries:

  1. Why are instance variables private? Why not public?
  2. What if instance variables are made public and accessed directly? Do we see any constraints?

Can you explain with an example as to what will go wrong in case the instance variables are declared as public in a class in Java?

Answer

Thomas picture Thomas · Oct 1, 2011

Instance variables are made private to force the users of those class to use methods to access them. In most cases there are plain getters and setters but other methods might be used as well.

Using methods would allow you, for instance, to restrict access to read only, i.e. a field might be read but not written, if there's no setter. That would not be possible if the field was public.

Additionally, you might add some checks or conversions for the field access, which would not be possible with plain access to a public field. If a field was public and you'd later like to force all access through some method that performs additional checks etc. You'd have to change all usages of that field. If you make it private, you'd just have to change the access methods later on.

If phone was private:

Consider this case:

class Address {
  private String phone;

  public void setPhone(String phone) {
    this.phone = phone;
  }
}

//access:
Address a = new Address();
a.setPhone("001-555-12345");

If we started with the class like this and later it would be required to perform checks on the phoneNumber (e.g. some minimum length, digits only etc.) you'd just have to change the setter:

class Address {
  private String phone;

  public void setPhone(String phone) {
    if( !isValid( phone) ) { //the checks are performed in the isValid(...) method
     throw new IllegalArgumentException("please set a valid phone number");
    }

    this.phone = phone;
  }
}

//access:
Address a = new Address();
a.setPhone("001-555-12345"); //access is the same

If phone was public:

Someone could set phone like this and you could not do anything about it:

Address a = new Address();
a.phone="001-555-12345";

If you now want to force the validation checks to be performed you'd have to make it private and whoever wrote the above lines would have to change the second line to this:

a.setPhone("001-555-12345");

Thus you couldn't just add the checks without breaking other code (it wouldn't compile anymore).

Additionally, if you access all fields/properties of a class through methods you keep access consistent and the user would not have to worry about whether the property is stored (i.e. is a instance field) or calculated (there are just methods and no instance fields).