Why are instance variables in Java always private?
Solution 1:
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).
Solution 2:
They don't have to be private - but they should be. A field is an implementation detail - so you should keep it private. If you want to allow users to fetch or set its value, you use properties to do so (get and set methods) - this lets you do it safely (e.g. validating input) and also allows you to change the implementation details (e.g. to delegate some of the values to other objects etc) without losing backward compatibility.
Solution 3:
First, it is not true that all instance variables are private. Some of them are protected, which still preserves encapsulation.
The general idea of encapsulation is that a class should not expose its internal state. It should only use it for performing its methods. The reason is that each class has a so-called "state space". That is, a set of possible values for its fields. It can control its state space, but if it exposes it, others might put it in an invalid state.
For example, if you have two boolean fields, and the class can function properly only in 3 cases: [false, false], [false, true], and [true, false]. If you make the fields public, another object can set [true, true], not knowing the internal constraints, and the next method called on the original object will trigger unexpected results.
Solution 4:
Making instance variables public or private is a design tradeoff the designer makes when declaring the classes. By making instance variables public, you expose details of the class implementation, thereby providing higher efficiency and conciseness of expression at the possible expense of hindering future maintenance efforts. By hiding details of the internal implementation of a class, you have the potential to change the implementation of the class in the future without breaking any code that uses that class.
Oracle White Paper
Solution 5:
Like has been pointed out by several answerers already, instance variables don't have to be private
, but they are usually at the very least not made public
, in order to preserve encapsulation.
I saw an example in (I think) Clean Code, which very well illustrates this. If I recall correctly, it was a complex number (as in a+bi
) type; in any case, something very much like that, I don't have the book handy. It exposed methods to get the value of the real and imaginary parts as well as a method to set the value of the instance. The big benefit of this is that it allows the implementation to be completely replaced without breaking any consumers of the code. For example, complex numbers can be stored on one of two forms: as coordinates on the complex plane (a+bi
), or in polar form (φ
and |z|
). Keeping the internal storage format an implementation detail allows you to change back and forth while still exposing the number on both forms, thus letting the user of the class pick whichever is more convenient for the operation they are currently performing.
In other situations, you may have a set of related fields, such as field x
must have certain properties if field y
falls inside a given range. A simplistic example would be where x
must be in the range y
through y+z
, for numerical values and some arbitrary value z
. By exposing accessors and mutators, you can enforce this relationship between the two values; if you expose the instance variables directly, the invariant falls apart immediately, since you cannot guarantee that someone won't set one but not the other, or set them so that the invariant no longer holds.
Of course, considering reflection, it's still possible to access members you aren't supposed to, but if someone is reflecting your class to access private members, they had better realize that what they are doing may very well break things. If they are using the public interface, they might think everything is fine, and then they end up with nasty bugs because they unknowingly did not fully adhere to the implementation details of your particular implementation.