开发者

Why are instance variables in Java always private?

开发者 https://www.devze.com 2023-04-09 16:30 出处:网络
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.

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?


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


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.


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.


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


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.


In traditional Object-Oriented design, a class will encapsulate both data (variables) and behavior (methods). Having private data will give you flexibility as to how the behavior is implemented, so for example, an object could store a list of values and have a getAverage() method that computes and returns the mean of these values. Later on, you could optimize and cache the computed average in the class, but the contract (i.e., the methods) would not need to change.

It has become more popular the past few years (for better or worse) to use anemic data models, where a class is nothing but a bunch of fields and corresponding getters and setters. I would argue that in this design you would be better off with public fields, since the getters and setters provide no real encapsulation, but just fool you into thinking you are doing real OO.

UPDATE: The example given in the link in the question is a perfect example of this degenerate encapsulation. I realize the author is trying to provide a simple example, but in doing so, fails to convey any real benefit of encapsulation (at least not in the example code).


  1. Because if you change the structure of the class (removing fields etc.); it will cause bugs. But if you have a getX() method you can calculate the needed value there (if field was removed).

  2. You have the problem then that the class does not know if something is changed and can't guarantee integrity.


Well keeping fields private has many advantages as suggested above. Next best level is to keep them package private using java default access level.

Default level avoid cluttering in your own code and prevents clients of your code from setting invalid values.


For user of class

We, who are using ide like eclipse, netbins..... saw that it suggest us for public method, so if creator of class provide getter and setter for private instance variable you do not have to memorize the name of variable. just write set press ctrl+space you are getting all of setter method created by creator of that class and choose your desired method to set your variable value.

For creator of class

Sometimes you need to specify some logic to set variable value. "suppose you have an integer variable which should store 0

0

精彩评论

暂无评论...
验证码 换一张
取 消