What Is the Point of Setters and Getters in Java

What is the point of getters and setters?

Multiple reasons:

  • If you allow field access like

    shape.x = 90

then you cannot add any logic in future to validate the data.

say if x cannot be less than 100 you cannot do it, however if you had setters like

public void setShapeValue(int shapeValue){
if(shapeValue < 100){
//do something here like throw exception.
}
}
  • You cannot add something like copy on write logic (see CopyOnWriteArrayList)
  • Another reason is for accessing fields outside your class you will have to mark them public, protected or default, and thus you loose control. When data is very much internal to the class breaking Encapsulation and in general OOPS methodology.

Though for constants like

public final String SOMETHING = "SOMETHING";

you will allow field access as they cannot be changed, for instance variable you will place them with getters, setters.

  • Another scenario is when you want your Class to be immutable, if you allow field access then you are breaking the immutability of your class since values can be changed. But if you carefully design your class with getters and no setters you keep the immutability intact.

Though in such cases you have to be careful in getter method to ensure you don't give out reference of objects(in case your class have object as instances).

We can use the private variables in any package using getters and setters.

What is the point of setters and getters in java?

The point of getters and setters, regardless of language, is to hide the underlying variable. This allows you to add verification logic when attempting to set a value - for example, if you had a field for a birth date, you might only want to allow setting that field to some time in the past. This cannot be enforced if the field is publicly accessible and modifyable - you need the getters and setters.

Even if you don't need any verification yet, you might need it in the future. Writing the getters and setters now means the interface is kept consistent, so existing code won't break when you change it.

Why use getters and setters/accessors?

There are actually many good reasons to consider using accessors rather than directly exposing fields of a class - beyond just the argument of encapsulation and making future changes easier.

Here are the some of the reasons I am aware of:

  • Encapsulation of behavior associated with getting or setting the property - this allows additional functionality (like validation) to be added more easily later.
  • Hiding the internal representation of the property while exposing a property using an alternative representation.
  • Insulating your public interface from change - allowing the public interface to remain constant while the implementation changes without affecting existing consumers.
  • Controlling the lifetime and memory management (disposal) semantics of the property - particularly important in non-managed memory environments (like C++ or Objective-C).
  • Providing a debugging interception point for when a property changes at runtime - debugging when and where a property changed to a particular value can be quite difficult without this in some languages.
  • Improved interoperability with libraries that are designed to operate against property getter/setters - Mocking, Serialization, and WPF come to mind.
  • Allowing inheritors to change the semantics of how the property behaves and is exposed by overriding the getter/setter methods.
  • Allowing the getter/setter to be passed around as lambda expressions rather than values.
  • Getters and setters can allow different access levels - for example the get may be public, but the set could be protected.

Why do we actually use getters and setters?

Getters and Setters are abstraction wrappers around your object implementations. You may have a property of an object that is actually (as an example) computed based on the value of other field members, but not stored or persisted within the class, thus a getter creates the illusion that the property itself is native to the class, while its implementation is substantially different. Also, getters without setters allow you to create read-only properties and protect internal members of the class from inadvertent and possibly destructive modification.

It's all about separating the external representation consumed by other applications from the internal implementation plumbing. Those are the basics.

Why are getter and setter method important in java?

The basic "private field with public getter and setter that do nothing but return or set the field" pattern is indeed completely pointless when it comes to encapsulation, except that it gives you a chance to change it later without changing the API.

So don't use that pattern unthinkingly. Carefully consider what operations you actually need.

The real point of getters and setters is that you should only use them where they are appropriate, and that they can do more than just get and set fields.

  • You can have only a getter. Then the property is read only. This should actually be the most common case.
  • You can have only a setter, making the property configurable, but communicating that nothing else should depend on its value
  • A getter can compute a value from several fields rather than return one field.
  • A getter can make a defensive copy
  • A getter can perform an expensive fetch operation lazily and use a field to cache the value
  • A setter can do sanity checks and throw IllegalArgumentException
  • A setter can notify listeners of changes to the value
  • You can have a setter that sets multiple fields together because they belong together conceptually. This doesn't adhere to the JavaBeans specification, so don't do it if you depend on frameworks or tools that expect JavaBeans. Otherwise, it's a useful option.

All of these things are implementation details that are hidden behind the simple "getter and setter" interface. That's what encapsulation is about.

Why setter and getter methods

The practice of automatically, unthinkingly creating getX() and setX() methods for every variable is bad. It's mostly pointless, as you have observed.

But it's the unthinking part that's bad. Methods are infinitely better than exposed variables because, again, as you observed, you can control how the underlying data is accessed. If you think about what you're doing, and apply mutators and accessors as appropriate, they're a wonderful tool:

  • You can restrict clients to only reading, but not writing to a variable.
  • You can restrict the values of an integer to only positive values (for example).
  • You can ensure that one variable is always equal to one-half the value of another (for example).
  • You can ensure that, any time the value of a variable is changed, an event is sent to notify other clients.
  • You can change the data type of an underlying variable, perform conversions in the public methods, and not break any clients.
  • You can convert an object to a remote client for a server-side version of the same object, and again, the client code won't change.
  • You can ensure strict memory ordering across threads by using synchronized accessors.

These are only some of the things you can do with mutators and accessors. By using them, you make your software easy to change and easy to maintain.

Can understand setters and getters in java

You asked for a simple example, so I'll give one. Suppose you're designing a circle class. A circle can be characterized by its diameter:

public class Circle {
private double diameter;

public Circle(double diameter) {
this.diameter = diameter;
}
}

A caller might want to know the diameter of the circle, so you add a getter:

public class Circle {
private double diameter;

public Circle(double diameter) {
this.diameter = diameter;
}

public double getDiameter() {
return this.diameter;
}
}

You might also want to get the area of the circle, so you add a getter for the area:

public double getArea() {
return Math.PI * (this.diameter / 2) * (this.diameter / 2);
}

And then you realize that using the radius rather than the diameter is easier for the internal methods of the circle. But you want to keep all the users of your class as is, to avoid breaking a lot of existing code. So you change the internals of the class without changing the interface:

public class Circle {
private double radius;

public Circle(double diameter) {
this.radius = diameter / 2;
}

public double getArea() {
return Math. PI * radius * radius;
}

public double getDiameter() {
return this.radius * 2;
}
}

And finally, you would like to change the diameter of the circle, so you add a setter:

public void setDiameter(double diameter) {
this.radius = diameter / 2;
}

But wait, a circle with a negative diameter makes no sense, so you make the method safer:

public void setDiameter(double diameter) {
if (diameter <= 0) {
throw new IllegalArgumentException("diameter must be > 0");
}
this.radius = diameter / 2;
}

Had you precomputed the area at construction time, the setDiameter would have had to change the value of the area as well:

public class Circle {
private double radius;
private double area;

public Circle(double diameter) {
this.radius = diameter / 2;
this.area = Math. PI * radius * radius;
}

public double getArea() {
return area;
}

public double getDiameter() {
return this.radius / 2;
}

public void setDiameter(double diameter) {
this.radius = diameter / 2;
// the area must also be changed, else the invariants are broken.
this.area = Math. PI * radius * radius;
}
}

Getters and setters are just methods. But they follow a naming conventions that makes your code easy to grasp, and usable by a number of frameworks which rely on these conventions.

Getter and Setters in Java

The examples you provided are not good fit, at least not in the form and with the names you mentioned.

I'll try with some better examples:

Setters

You might want to use them for validation mostly. As an example setDate(Date d) could check the data is in a certain range, e.g. not more than 20 years into the future etc. (depends on your requirements).

Getters

If those contain more than simple logic they probably represent virtual properties, i.e. properties that don't have an underlying field but are calculated on the fly.

Let's take getAmount() for example: there might not be any field amount or the amount might be stored in cents (or smaller) for some reason (e.g. no precision issues). Thus getAmount() might look like this:

public double getAmount() {
return amountInCents / 100.0;
}

Note that the name getAmount() might be misleading though, so you might be better off using a name like getAmountInUSD() or similar.

General

Using getters and setters in Java is adviceable in most cases since you'd be able to the following (list not complete):

  • add validation logic (to the setters)
  • add transformation logic (setters, getters) for virtual properties
  • define access, i.e. read-only would mean there is no public setter
  • use libraries that are based on the Java Beans specification (which requires the use of setters and getters)
  • decouple the client/caller of the getter/setter, i.e. if at some point you want to add validation having field access done via a setter would not require the client to change (unless validation errors would need to be handled) etc.
  • use setters and getters for debugging purposes, e.g. by putting a breakpoint at the method and have a look at the stack trace to see who called it (mentioned by dsp_user)


Related Topics



Leave a reply



Submit