38

I have been taught to always use getters and setters. However, I don't know the pros and cons of these methods, as by implementing them we are exposing the data and also hiding it.

I am a little confused about this. Can anybody give some proper advice on why we use a getter/setter and what the advantages are?

Nike15
  • 544
  • 3
  • 16
School Boy
  • 1,207
  • 2
  • 19
  • 33

6 Answers6

72

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.

earl
  • 40,327
  • 6
  • 58
  • 59
Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
  • 2
    This is a great answer. I feel that the 'always use getter/setters around private fields' dogma has contributed to the Java-is-bloated reputation. Control over access to fields and the ability to react to them being set or get should be part of the language and encapsulated at the class implementation. – Alex Worden Dec 05 '14 at 20:27
19

The idea of getters and setters are to control access to variables in a class. That way, if the value needs to be changed internally to be represented in a different way, you can do so without breaking any code outside the class.

For example, let's say you had a class with a distance variable, and it was measured in inches. A few months pass, you're using this class in a lot of places and you suddenly realize you needed to represent that value in centimeters. If you didn't use a getter and a setter, you would have to track down every use of the class and convert there. If you used a getter and a setter, you can just change those methods and everything that uses the class won't break.

public class Measurement
{

    /**
     * The distance in centimeters.
     */
    private double distance;

    /**
     * Gets the distance in inches.
     * @return A distance value.
     */
    public double getDistance()
    {
        return distance / 2.54;
    }

    /**
     * Sets the distance.
     * @param distance The distance, in inches.
     */
    public void setDistance(double distance)
    {
        this.distance = distance * 2.54;
    }
}
Robert Rouhani
  • 14,512
  • 6
  • 44
  • 59
  • 1
    AHHHHHHH! So that's it! If you have to represent the data in a different way, and you'll using the variables in many other classes, just changing the implementation in the setting method will change the variables in all the other classes. Very good. Then I assume it's good programming to use setter methods for variables that you use very often because you might have to change it later on? How often should we use setter and getters? – Skillet Apr 07 '15 at 20:52
  • that was Nice example! – Devesh Nov 17 '15 at 09:52
  • tracking down or even refactoring every use of the class which uses a public field isn't at all hard especially with modern IDEs. Just make the field private and let the compiler do the hard work for you. As to what might happen after a few months pass, one could argue YAGNI. Just saying.. – Suketu Bhuta Aug 15 '17 at 15:29
7

One good advantage comes into mind is that you can make a field ReadOnly by not implementing a setter for that particular field.

Sandeep Pathak
  • 10,567
  • 8
  • 45
  • 57
3

Here's the downside. Getters/Setters tend to expose the implementation details of your class to the outside world. That's not a good thing. Imagine you are writing an Auto mechanic software package. Thus you will need a Car class, and so you expose getters and setters for the fields

Date lastOilChangeDate;
int lastOilChangeMileage;

in this class. This is because the software wants to send emails when customer cars need oil changes.

But what happens when new cars come out where you determine whether a car needs an oil change differently than 'every 3000 miles or 3 months'? Perhaps these new cars have a sensor in the oil pan that measured dirtyness. Obviously you'd want to use this to determine whether an oil change was needed.

The issue was you were solving the wrong problem with those getter/setters. No one really wants to know when the last oil change was, they want to know if you need another one. They were just implementation details, but you made them part of the interface. What you should have done was added a method

public boolean needsOilChange() 

and then the Car class could implement however it wanted. If the algorithm change the Mechanic class wouldn't have to because all it needed was the needsOilChange method.

MeBigFatGuy
  • 28,272
  • 7
  • 61
  • 66
  • 2
    Getters and setters only expose implementation details if you deliberately write them like that. – Michael Borgwardt Jan 12 '12 at 08:50
  • A car does not determine if it needs an oil change. This is determined by a mechanic performing some analysis or following some guidelines. Your needsOilChange() method belongs on some other object. Any number of applications might find it very useful to know the date and/or mileage of the last oil change and these are properties every car has. Unless of course we're considering Tesla's. Even then, we might want to preserve a history of the oil changes so again, even these details might best be persisted elsewhere... The point here is, it all depends. Dogma is the enemy. – Alex Worden Dec 05 '14 at 20:24
  • your car is too archaic – MeBigFatGuy Jan 01 '15 at 22:08
2

There is nothing wrong with using getters and setters - just be aware that by using them and making them all public you're exposing your variables and, in a way, violating encapsulation. This is what the article you mention is trying to warn of - don't just automatically generate getters and setters for all private instance variables; think about what you want to expose to other classes (and at what level, i.e. private/protected/public) so that you're exposing only as needed.

Amos M. Carpenter
  • 4,848
  • 4
  • 42
  • 72
-3

this is mostly used in Java beans like below.

public Class MyBean{

private int var1;

public void setVar1(int pVar1){

this.var1=pvar1;

}

public int getVar1(){

return var1;`

}

}

benefits are as below

1. with this we can achieve Encapsulation

2. it is called as DTO (Data Transfer Object) design pattern. it is used to transfer data from one layer to another layer in MVC based applications. like u can get user entered data from form (by using getters) and u can use the same data to insert into database(by using setter) and vice verca. latest frameworks (SPring )providing it as inbuilt functionality.

Balaswamy Vaddeman
  • 8,360
  • 3
  • 30
  • 40
  • 1
    I'm sorry, but I don't think this is a good answer (nor is the code well-written or formatted). Point 1 is plain wrong, using getters and setters doesn't help you to achieve encapsulation. Point 2 is correct about Java beans being used as DTOs, but the question was about getter/setter usage, and the fact that beans use these doesn't mean that using DTOs is a benefit of getters/setters. -1 from me, I'm afraid, despite being the accepted answer. – Amos M. Carpenter Jan 12 '12 at 07:37
  • If you use getters and setters for every variable without restrictions, you're not encapsulating anything. – Robert Rouhani Jan 12 '12 at 07:41
  • getters and setters are part of Java beans,Java beans are DTOs,then DTOs are benefit of getters and setters according to transitive law. – Balaswamy Vaddeman Jan 12 '12 at 08:46
  • No, Java beans are not DTOs. The original idea behind JavaBeans was to have components with a lot of logic and functionality that expose configuration options via getters and setters. Swing components are JavaBeans designed like that. – Michael Borgwardt Jan 12 '12 at 08:49
  • original idea may be that Java beans can be used as DTOs and I did it that way – Balaswamy Vaddeman Jan 12 '12 at 08:51
  • @Balaswamy vaddeman: no, that was not the original idea, as I wrote. BTW, DTO is actually an antipattern based on deficits of the EJB 2 architecture and should be avoided nowadays. – Michael Borgwardt Jan 12 '12 at 09:04
  • I do not agree on **antipattern based on the deficits of EJB2** DTO is independent design pattern which is no way related to EJB2 architecture and I agree on DTO is rarely used nowdays because latest frameworks like Spring provide builtin functionality.DTO is still usefull if u r not using any framework. – Balaswamy Vaddeman Jan 12 '12 at 11:50
  • @Balaswamyvaddeman - Your argument: "Getters and setters are part of Java beans, beans are DTOs, therefore DTOs are a benefit of getters and setters, according to transitive law." To point out your fallacy: "Arms and legs are parts of humans, humans are mammals, therefore mammals are a benefit of arms and legs." – Amos M. Carpenter Jan 12 '12 at 16:09