Java protected fields vs public getters - java

What is better practise and why: accessing base class variables through a protected field or a public getter on the private field.
(The getter will be public regardless)

If there's going to be a public getter anyway, why would you want to expose the field itself more widely than absolutely necessary? That means it's immediately writable by subclasses (unless it's final to start with).
Personally I like all my fields to be private: it provides a cleaner separation between API and implementation. I regard the relationship between a superclass and a subclass as similar to that of a caller and callee - changes to the underlying implementation shouldn't break subclasses any more than they should break callers. The name of a field is an implementation detail which shouldn't impact other classes.
Admittedly my view is occasionally seen as somewhat extreme...

You should always program against the public API of a class, that is, use the public methods.
The reason is simple. Someday in the future, you or someone else might want to change the implementation. This should always be possible. If you rely on instance variable, you limit yourself.
Also, when accessing the variable, you can not control if that variable is read-only nor can you add checks when this variable is changed.
If you use setters/getters, you can allways add validation, checking etc later on. You can also only provide a getter to make a variable read only.

Direct field access is not preferred. Use public or protected setters and getters.
The getter need not be public - if you wan to hide the data from "outsiders", but give the data to subclasses, use protected

Some of Sun's recommendations on controlling access to fields are here. Note that making a field protected exposes it to the package as well, not only to subclasses. Generally, as stated at the link above, fields should be private unless there is a very good reason not to do so.

Effective Java 2nd Edition says
Item 13: Minimize the accessibility of classes and members
The rule of thumb is simple: make each class or member as inaccessible as
possible. In other words, use the lowest possible access level consistent with the
proper functioning of the software that you are writing.
So if you are not sure why you need a protected class member (ie you don't need the field to be accessible to subclasses or classes in the same package), then declare it private. If you wish to set it from outside the class, then make a public setter.
However, if your member is final, then making it protected might be ok in some cases (ie it doesn't reveal sensitive information).
One potential security issue I would like to mention is that if you have an array declared protected final (even public final), the array reference is final (cannot be modified), but the objects held in the array are not final (an intruder could change the array contents).
If you know c++, you probably know that
const int * someMember
is different from
int * const someMember
The latter is like the final array in java.
The fix for the aforementioned security hole is to return a deep copy of the array or return it as a read only list.

Generally, you should use Sun's recommendations. There is one big exception: if you're programming for Android.
The reason is performance. With every virtual method invocation, there is overhead involved in using the lookup table to route the method to its object. This overhead is not involved when accessing a local variable.
Here are some links that explain this in a little more depth:
http://developer.android.com/training/articles/perf-tips.html#GettersSetters
http://blog.leocad.io/why-you-shouldnt-use-getters-and-setters-on-android/
It's important to know what you're trying to accomplish:
The field's value should be accessible to client code, using a public interface.
The field is meant to be used by subclasses.
In plain ol' Java, getters and setters accomplish both tasks. But Android is different. If you're doing #1, then you should use public getters and setters. If you're doing #2, then you should use protected fields. If you're doing both, use both.

I would like to present you with some arguments protecting "protected" fields in Java:
"You may favor accessing base class members using protected fields over public accessors in situation where you need to avoid value validation".
However if this is not the case, then private fields with public accessors should be used, to compliment hermetization.
The principle of getters and setters is to provide validation to the values inputted and outputted to the class member. However, in OOP languages, we operate on objects not classes. Base class and specialized class represent a single object, that is why it is perfectly fine to access specific class members over protected field.
Consider the following abstract example with a car:
- you have a base class Car and the derived class Porshe.
- Car class may have field like engine, which value is not set in Cars constructor (maybe the type of engine is known only after object initialization)
- You create a Porshe class object that contains some logic used to calculate engine type using some external data.
In this example, it is expected that engine field has a public getter, so car users know what engine the car has. However, there is no public setter as we expect car drivers not to temper with the engine! That is why, it is perfectly fine to make engine a protected field, so the Porshe class can set its value at some time in future.
Yes, some people will probably say "then use protected setter!".
And I will repeat: in OOP languages we work with objects not classes.
Single responsibility principle - yes, but as object not as class.
If you say: "at some point if we use protected fields over 3 or 5 inheritance levels, it may be troublesome to understand what happens to the field if each class performs some operation with it". And then I answer: That is another antipattern - your object is probably too big at this point and voids Single Responsibility principle.

Accessing protected fields from a subclass is one of the ways that inheritance violates encapsulation. Using the public API is better for this reason.

Related

Encapsulation - why do we need it when setters are already public? [duplicate]

This question already has answers here:
Why are getter and setter method important in java? [duplicate]
(6 answers)
Closed 7 years ago.
Encapsulation is hiding the data. I would like to hear some really interesting answers here.
What is the point behind keeping variables as private when we already declare public setter methods for variables?
I understand the usage of encapsulation but when we are making the setters as public what is the point behind keeping the variables as private, we can directly use public access modifiers.
Is it because we do not want others to know the exact way we are storing data or managing data on the back-end?
Is it because we do not want others to know the exact way we are
storing data or managing data on the back-end?
Yes, that's the point. It is related to the concepts of abstraction and information hiding too.
You provide a public setter that when invoked by the class client will have the effect that you have documented. It is none of the client's business how this effect is actually achieved. Are you modifying one of the class attributes? Ok, let the client know that, but not the fact that you are actually modifying a variable. In the future, you could want to modify your class so that instead of a simple backup variable it uses something completely different (a dictionary of attributes? An external service? Whatever!) and the client will not break.
So your setter is an abstraction that you provide to the client for "modify this class attribute". At the same time you are hiding the fact that you are using an internal variable because the client doesn't need to know that fact.
(Note: here I'm using the word "attribute" as a generic concept, not related to any concrete programming language)
I fully agree with Konamiman's answer, but I'd like to add one thing:
There are cases where you really don't want that abstraction. And that's fine.
A simple example I like to use here is a class for a 3-dimensional float vector:
class Vector3f {
public:
float x;
float y;
float z;
};
Could you make those fields private and provide setters instead? Sure, you could. But here you might argue that the class is really just supposed to provide a tuple of floats and you don't want any additional functionality. Thus adding setters would only complicate the class and you'd rather leave the fields public.
Now, you can easily construct scenarios where that might bite you later on. For instance, you might one day get a requirement that Vector3fs are not allowed to store NaNs and should throw an exception if anyone tries to do so. But such a hypothetical future problem should not be enough to justify introducing additional abstractions.
It's your call as a programmer to decide which abstractions make sense for the problem at hand and which ones would only get in your way of getting the job done. Unnecessary abstractions are over-engineering and will hurt your productivity just as much as not abstracting enough.
Bottom line: Don't blindly use setters everywhere just because someone claimed that's good practice. Instead, think about the problem at hand and consider the tradeoffs.
Because by encapsulation we provide single point of access. Suppose you define a variable and its setter as follows
String username;
public void setUsername(String username){
this.username = username;
}
Later you like to add some validation before setting username property. If you are setting the username at 10 places by directly accessing the property then you don't have single point of access and you need to make this change at 10 places. But if you have one setter method then by making a change at one place you can easily achieve the result.
Think about this : I'm representing a real life object, a Lion through a class. I'd do something like this.
class Lion {
public int legs;
}
Now my class is needed by some other developer to create an object and set its legs field. He'd do something like this
Lion jungleKing = new Lion();
jungleKing.legs = 15;
Now the question is, Java won't restrict him to setting any number more than 4 as the number of legs for that object. It's not an error, and it'll run just fine. But it's a logical blunder, and the compiler won't help you there. This way a Lion may have any number of legs.
But if we write the code this way
class Lion {
private int legs;
public void setLegs(int legs){
if(legs > 4){
this.legs = 4;
}
else this.legs = legs;
}
}
Now you won't have any Lion with more than 4 legs because the policy of updating the fields of the class has been defined by the class itself and there's no way anyone not knowing the policy is going to update the legs field because the only way to update the legs field is through the setLegs() method and that method knows the policy of the class.
Although Konamiman's answer is spot on, I'd like to add that, in the particular case of public setters versus directly exposing public fields you are asking, there is another very important distinction to keep in mind apart from information hiding and decoupling implementation from the public surface, or API, of a class; validation.
In a public field scenario, there is no way to validate the field's value when it's modified. In case of a public setter (be it a Foo {get; set;} property or a SetFoo(Foo value)) method you have the possibility to add validation code and launch required side-effects and this way ensure that your class is always in a valid or predictable state.
What if you do want to a range check before assignment? That's one of the cases I use setters and getters
More or less simple and realistic example I encountered in practice is an Options class, which has a lot of setters and getters. At some point you might want to add new option which depends on others or has side effects. Or even replace group of options with Enum. In this case setA function will not just modify a field, but will hide some additional configuration logic. Similarly getA will not just return value of a, but something like config == cStuffSupportingA.
Wikipedia has a good overview of [mutator methods(https://en.wikipedia.org/wiki/Mutator_method), which is what setter methods are and how they work in different languages.
The short version: if you want to introduce validation or other logic that gets executed on object modification it is nice to have a setter to put that logic in. Also you may want to hide how you store things. So, those are reasons for having getters/setters. Similarly, for getters, you might have logic that provides default values or values that are dependent on e.g. configuration for things like Locale, character encoding, etc. There are lots of valid reasons to want to have logic other than getting or setting the instance variable.
Obviously, if you have getters and setteres, you don't want people bypassing them by manipulating the object state directly, which is why you should keep instance variables private.
Other things to consider include whether you actually want your objects to be mutable at all (if not, make fields final), whether you want to make modifying the object state threadsafe with e.g. locks, synchronized, etc.
Setting fields as private documents a powerful fact: these private fields are only directly used within the current class. This helps maintainers by not having to track down field usage. They can reason better on the code by looking at the class and determining that the effects on and from these fields with the class' environment go through public and protected method calls. It limits the exposure surface on the class.
In turn, defining a "setter" for a private field is not about giving it publicity again. It is about declaring another powerful fact: an object belonging to this class has a property that can be modified from the outside. (The terms object and property are used in the sense of a bounded part of the whole and an observable fact about this part, not in the OOP sense)
Why then declare a "setter" on a field when making the field public would suffice? Because declaring a field not only binds a name to a property of the objects of the class, but also commits to use memory storage for this property.
Therefore, if you declare a "private field with a setter", you declare three things:
You declare that the name you gave to the field/setter cluster represents a property of the object which is of interest when the object is seen as a black box.
You declare that the value of this property is modifiable by the environment of the object.
You declare that in this particular concrete class, the property of the object is realized by committing some memory storage to it.
I advocate that you never make your fields private with getters and setters indiscriminately. Fields are for describing storage. Methods are for interactions with the environment. (And the particular case of "getters" and "setters" are for describing properties of interest)

When is using public fields acceptable?

I have a main class that has a thread pool, which is used by quite a few other classes for performing actions on a database. I currently have a getter method to get the pool which works fine but seems a bit clumsy.
Are there any circumstances where it is acceptable to use a public field instead of getter/setter methods?
Are there any circumstances where it is acceptable to use a public field instead of getter/setter methods?
The main reason that public fields are bad are that they expose the implementation to the outside world. That leads to unwanted coupling; i.e. classes that are overly dependent on the implementation details of other classes. That tends to make code harder to understand and harder to change. And if the field is not final, you need to search the entire code-base to be sure that nothing is "interfering" with the field. (OK, IDE's make this easier ... but contrast a public field with a private field that has no setter.)
A secondary reason is that you cannot override a field. Once you have exposed a field in a superclass, there is nothing you can do in a subclass can do to modify or restrict its meaning. (By contrast, getters and setters can be overridden ...)
The only situation where it is acceptable (from a stylistic perspective) to have "public" fields is when the class which declares the fields is a private nested or inner class. The consequence is that all dependencies on the field are restricted to the source file that contains the declaration ... which negates the problems above.
UPDATE - I forgot public static final ... but we tend not to think of those as fields at all. Anyway, it is normal practice to access public static final fields directly. The idea of a constant is to deliberately expose the name, type and value ... and the override issue doesn't apply because of the nature of static fields.
I currently have a getter method to get the pool which works fine but seems a bit clumsy.
"Clumsy" is a matter of opinion / taste. Personally, I don't think that obj.getInstance() is clumsy compared with obj.instance. It is just the Java way1.
The flipside is that if you didn't have a getInstance() method, all of the classes that used the pool would have to have hard-coded references to the instance field. If (for some reasons) you needed to change something about the way the pool was accessed (e.g. add a security check, add a counter, make pool creation lazy, make sure that access is properly synchronized), then you have to change each and every place where you have coded reference to the field. But with a getter, you just have one place to change.
1 - Obviously, other languages do this differently. But you are not writing those languages. Java is what it is.
There are many reasons for using getter & setter instead of a public field. One I've found in SO is
Because 2 weeks (months, years) from now when you realize that your
setter needs to do more than just set the value, you'll also realize
that the property has been used directly in 238 other classes :-)
You can also have a look at this post, which also quotes that i've give above and provides a few other examples. Read and then you can decide whether to use a public field in your case.
Keeping your class fields private and using getter/setter methods provides a layer of abstraction and makes it easier to maintain in the long run. See this: What's the deal with Java's public fields?

confusion on Get and set methods in java

I am learning get and set methods, I was just wondering if these can only be public, and do they need to be written for every instance variable in a class?
No.
Many internal variables should never be edited, such as states of computations.
If a field is private and has no getter/setter, it is that way for a reason and is acceptable as long as you don't need to access it outside the class.
If it is public, there's no point, and if protected, it's per-package or subclasses not necessarily in the same package.
Without a modifier, it's package-private.
If you want to make a field private and the getter/setter controlled you can use access levels as well.
On that note, if you want, you can perform validation inside a setter to ensure only acceptable values are set. Then, you can either silently reject, return false if the setter is a boolean, or throw an exception in severe circumstances.
I am assuming you are talking about encapsulation.
The whole point of these methods is for them to be public so that they can pass the value of your variable somewhere else in the application.
For achieving this with many variables, you may consider using 'listeners' (Observer Pattern Theory) which are basically custom interfaces that work with a custom class that contains many of these get and set methods.
More on encapsulation:
http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming)
More on Observer Pattern Theory
http://www.youtube.com/watch?v=UEtyGP994X0
You need to have public getters and setters for your object to function as a JavaBean.
If you don't have a JavaBean requirement for your objects, then you don't need/have to provide public getters ( and especially setters ) in your classes.
Get and set methods in Java are just normal methods. They don't have to be public, but they wouldn't be very useful if they weren't public.
They don't need to be written for every instance variable in a class. If there are instance variables whose values depend on other values, then it may not make sense for them to have setters, e.g. a totalPrice instance variable that depends on a quantity instance variable.
If you want instance variables that shouldn't change, i.e they are immutable, then don't provide any set methods at all.
These methods provide your interface to the caller. They provide the operations on your object that you allow, so that the caller can't set your values to an invalid state, e.g. a count of -1 or a latitude of 91 degrees. This is "encapsulation", or hiding your object's implementation from your caller.
There is no java rule for making getters and setters public but these are made public for a reason.The point of getters and setters is that only they are meant to be used to access the private varialble, which they are getting or setting. This way you provide encapsulation and it will be much easier to refactor or modify your code later.Using getter and setter functions allow for constraints and encapsulation. Lets say x is the radius. shape.x = -10 would not make much sense. Also, if someone tries to set an illegal value, you can print an error, set a default value, or do nothing. It is good practice to make member variables private so they cannot be modified directly by programs using them.
A good article on the usage of getters and setters:
http://java.dzone.com/articles/getter-setter-use-or-not-use-0
Basically Yes, and No.
Yes, Get and Set methods (also called "getters" and "setters" or accessor methods) should almost always be public (although they can be otherwise -- there's a difference between can and should). The point of getters and setters is usually so other classes can access the encapsulated instance variables.
Exeptions:
You might make an accessor method to be protected if you only want child
classes or other classes in the same package to have access to those
methods.
You might use a private (or protected) setter if you want to
use special logic to set a variable (like concatenating it)
and you don't want other classes to be able to set the
variable.
No, they shouldn't always have accessors. Sometimes a variable should only have a getter (for instance, if that variable is final), and sometimes a variable shouldn't be accessed at all, and therefore you would not give it any accessor methods.
Get and set methods were designed originally for JavaBeans, classes stylized so IDEs and application programs can detect what properties the classes have and what event listeners they support. Through a limited version of reflection called introspection, tools can analyze the classes, and even if the programmer did not want to use is/get/set methods he could write BeanInfo classes that tell what methods be used instead.
Look at the Javadoc for java.beans.Introspector. and java.beans.BeanInfo. This provides ways to document additional information, including methods exposed to other tools and metadata about properties. For example, a TemperatureGauge class could expose the minimum and maximum temperature so a Swing program can set the limits of a slider without the programmer looking the information up.
Still, one should not expose more than one has to expose. You may need to limit access to getters and setters. You may need them for database tools, but you may not want ordinary programming to touch properties. This leads to ideas like OSGI or proxies where methods are limited to specific packages.
For example, one common tactic is to have getters only, to mark variables final, and build objects in the constructor. For example,
public final class Complex {
private final double re;
private final double im;
public Complex(double re, double I'm) {
this.re = re;
this.im = im;
}
public double getReal() {
return re;
}
// more getters, arithmetic, etc.
}
Note that I named the method slightly differently than the variable; that's okay.
On the other hand, there is a style of programming where one eschews getters and writes methods that tell the object what to do. Consider a Name class with givenName and surname instance variables. Then, add this method:
public void writeFormally(Appendable app) {
app.append(surname)
.append(", ")
.append(givenName);
}
You see this sometimes in Model-View-Presenter systems, like GWT and its HasText interface.
Unless you are writing code that deals with dependency injection systems or that use reflection to have your objects communicate with database, don't worry about the specifics of getters and setters. Just do what comes naturally and limit your objects' exposures. Also, every time you are tempted to write:
x.getA().getB().getC().setZ(42);
Rewrite the code to get rid of the chain of gets and sets. Look up the Law of Demeter in The Pragmatic Programmer.
Use protected if you want only child classes to access the field. However, if you want other classes to access the field, public is the way to go. Your decision should be based on the scope of access.

Why are instance variables in Java always private?

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:
Why are instance variables private? Why not public?
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).
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).
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

the use of private keyword

I am new to programming. I am learning Java now, there is something I am not really sure, that the use of private. Why programmer set the variable as private then write , getter and setter to access it. Why not put everything in public since we use it anyway.
public class BadOO {
public int size;
public int weight;
...
}
public class ExploitBadOO {
public static void main (String [] args) {
BadOO b = new BadOO();
b.size = -5; // Legal but bad!!
}
}
I found some code like this, and i saw the comment legal but bad. I don't understand why, please explain me.
The most important reason is to hide the internal implementation details of your class. If you prevent programmers from relying on those details, you can safely modify the implementation without worrying that you will break existing code that uses the class.
So by declaring the field private you prevent a user from accessing the variable directly. By providing gettters and setters you control exactly how a user may control the variable.
The main reason to not just make the variable public in the first place is that if you did make it public, you would create more headaches later on.
For example, one programmer writes public getters and setters around a private member variable. Three months later, he needs to verify that the variable is never "set" to null. He adds in a check in the "setFoo(...)" method, and all attempts to set the variable will then be checked for "setting it to null". Case closed, and with little effort.
Another programmer realizes that putting in public getters and setters around a private member variable is violating the spirit of encapsulation, he sees the futility of the methods and decides to just make the member variable public. Perhaps this gains a bit of a performance boost, or perhaps the programmer just wants to "write it as it is used". Three months later, he needs to verify that the variable is never "set" to null. He scans every access to the variable, effectively searching through the entire code base, including all code that might be accessing the variable via reflection. This includes all 3rd party libraries which has extended his code, and all newly written modules which used his code after it was written. He then either modifies all calls to guarantee that the variable is never set to null. The case is never closed, because he can't effectively find all accesses to the exposed member, nor does he have access to all 3rd party source code. With imperfect knowledge of newly written modules, the survey is guaranteed to be incomplete. Finally he has no control over the future code which may access the public member, and that code may contain lines which set the member variable to null.
Of course the second programmer could then break all existing code by putting "get" and "set" methods around the variable and making it private, but hey, he could have done that three months earlier and saved himself the explanation of why he needed to break everyone else's code.
Call it what you will, but putting public "get" and "set" methods around a private member variable is defensive programming which has been brought about by many years (i.e. decades) of experience.
Anything public in your class is a contract with the users of the class. As you modify the class, you must maintain the contract. You can add to the contract (new methods, variables, etc.), but you can't remove from it. Idealy you want that contract to be as small as possible. It is useful to make everything private that you can. If you need direct access from package members, make it protected. Only make those things public which are required by your users.
Exposing variables means that you are contracting forever, to have that variable and allow users to modify it. As discussed above, you may find you need to invoke behaviour when a variable is accessed. This can be be done if you only contract for the getter and setter methods.
Many of the early Java classes have contracts which require them to be thread safe. This adds significant overhead in cases where only one thread can access the instance. Newer releases have new classes which duplicate or enhance the functionality but drop the syncronization. Hence StringBuilder was added and in most cases should be used instead of StringBuffer.
Its considered bad mainly because you loose control over who can change the value and what happens when the value changes.
In tiny application written by you for you it won't seem that important but as you start developing for larger and larger applications having control over who changes what and when becomes critical.
Imagine from your example above, you publish library as is, other people use it, then you decide you wanted to calculate another value in your bad class when the size changes ... suddenly the bad00 class has no way of knowing and you can't change it because other people rely on it.
Instead if you had a set method you could extend it to say
void SetSize(int newSize)
{
size = newSize;
DoCalculation;
}
You can extend the functionality without breaking other peoples reliance on you.
I highly recommend the book Effective Java, it contains a lot of useful information about how to write better programs in Java.
Your question is addressed in items 13 and 14 of that book:
Item 13: Minimize the accessibility of classes and members
Item 14: In public classes, use accessor methods, not public fields
You shouldn't allow implementations to alter your records directly. Providing getters and setters means that you have exact control over how variables get assigned or what gets returned, etc. The same thing goes for the code in your constructor. What if the setter does something special when you assign a value to size? This won't happen if you assign it directly.
It's a common pet-peeve of many programmers - Java code with private fields and public accessors and mutators. The effect is as you say, those fields might as well been public.
There are programming languages that voice for the other extreme, too. Look at Python; just about everything is public, to some extent.
These are different coding practices and a common thing programmers deal with every day. But in Java, here's my rule of thumb:
If the field is used purely as an attribute, both readable and writeable by anyone, make it public.
If the field is used internally only, use private. Provide a getter if you want read access, and provide a setter if you want write access.
There is a special case: sometimes, you want to process extra data when an attribute is accessed. In that case, you would provide both getters and setters, but inside these property functions, you would do more than just return - for example, if you want to track the number of times an attribute is read by other programs during an object's life time.
That's just a brief overview on access levels. If you're interested, also read up on protected access.
This is indeed used to hide the internal implementation. This also helps is providing extra bit of logic on your variables. Say you need to make sure that the value passed for a varable should not be 0/null, you can provide this logic in the set method. Also in the same way you can provide some logic while getting the value, say you have a object variable which is not initialised and you are accessing that object, in this case you cand provide the logic to null check for that object and always return an object.
C# programmers use this equally as much, or maybe more frequently than I see in Java. C# calls it properties where in Java it is accessors/mutators
For me it makes sense to have getter and setter methods to encapsulate the classes so that no class can change the instance variables of another class.
Okay. We are talking about Objects here. The real world objects. If they are not private,the user of your class is allowed to change. What if for a Circle class, and for the radius attribute/property of the Circle class, the user sets value as '0'. It doesn't make sense for a Circle to exist with radius as '0'. You can avoid such mistakes if you make your attributes private and give a setter method and in which and throw an Exception/Error (instructing the user ) that it is not allowed to create a Circle with radisu as '0'. Basically, the objects that are created out of your class - are meant to exist as you wished to have them exist. This is one of the ways to achieve it.
As stated earlier, the reason for making a variable private is to hide it from the outside. But if you make a getter AND a setter then you may as well make the variable itself public. If you find yourself later in a position that you made the wrong choice, then you must refactor your code from using the public variable into using the getter/setter which may not be a problem. But it can be a problem if other code, which you do not control, starts depending on your code. Then such a refactoring will break the other code. If you use getters and setters from the start you will reduce that risk in exchange for a little effort. So it depends on your situation.
It depends on who access these public variables. Most likely, only by people inside your company/team. Then it's trivial to refactor them into getters/setters when necessary. I say in this case, it's better to leave the variables public; unless you are forced to follow the java bean convention.
If you are writing a framework or a library intended for the public, then you shouldn't expose variables. It's impossible for you to change them into getters/setters later.
But the 2nd case is more rare than the first; people apply extremely unreasonable assumptions when it come to software engineer, as if they are not writing code, instead they are carving code in stone. And as if the whole world is watching while you code - in reality, nobody will ever read your code except yourself

Categories

Resources