DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Distribution Design Patterns in Java - Data Transfer Object (DTO) And Remote Facade Design Patterns
  • Protecting Your Domain-Driven Design from Anemia
  • Unraveling Lombok's Code Design Pitfalls: Exploring Encapsulation Issues
  • Architecture and Code Design, Pt. 2: Polyglot Persistence Insights To Use Today and in the Upcoming Years

Trending

  • Docker Model Runner: Streamlining AI Deployment for Developers
  • Contextual AI Integration for Agile Product Teams
  • AI’s Role in Everyday Development
  • Building Resilient Identity Systems: Lessons from Securing Billions of Authentication Requests
  1. DZone
  2. Coding
  3. Languages
  4. Java: Overriding Getters and Setters Design

Java: Overriding Getters and Setters Design

By 
Muhammad Ali Khojaye user avatar
Muhammad Ali Khojaye
·
Sep. 10, 10 · Tutorial
Likes (1)
Comment
Save
Tweet
Share
97.6K Views

Join the DZone community and get the full member experience.

Join For Free

Why do we keep instance variables private? We don’t want other classes to depend on them. Moreover it gives the flexibility to change a variable’s type or implementation on a whim or an impulse. Why, then programmers automatically add or override getters and setters to their objects, exposing their private variables as if they were public?

Accessor methods

Accessors (also known as getters and setters) are methods that let you read and write the value of an instance variable of an object.

public class AccessorExample {
    private String attribute;

    public String getAttribute() {
        return attribute;
    }

    public void setAttribute(String attribute) {
        this.attribute = attribute;
    }
}

Why Accessors?

There are actually many good reasons to consider using accessors rather than directly exposing fields of a class

Getter and Setter make API more stable. For instance, consider a field public in a class which is accessed by other classes. Now, later on, you want to add any extra logic while getting and setting the variable. This will impact the existing client that uses the API. So any changes to this public field will require a change to each class that refers it. On the contrary, with accessor methods, one can easily add some logic like cache some data, lazily initialize it later. Moreover, one can fire a property changed event if the new value is different from the previous value. All this will be seamless to the class that gets the value using accessor method.

Should I have Accessor Methods for all my fields?

Fields can be declared public for package-private or private nested class. Exposing fields in these classes produces less visual clutter compare to accessor-method approach, both in the class definition and in the client code that uses it.

If a class is package-private or is a private nested class, there is nothing inherently wrong with exposing its data fields—assuming they do an adequate job of describing the abstraction provided by the class.

Such code is restricted to the package where the class is declared, while the client code is tied to class internal representation. We can change it without modifying any code outside that package. Moreover, in the case of a private nested class, the scope of the change is further restricted to the enclosing class.

Another example of a design that uses public fields is JavaSpace entry objects. Ken Arnold described the process they went through to decide to make those fields public instead of private with get and set methods here

Now this sometimes makes people uncomfortable because they've been told not to have public fields; that public fields are bad. And often, people interpret those things religiously. But we're not a very religious bunch. Rules have reasons. And the reason for the private data rule doesn't apply in this particular case. It is a rare exception to the rule. I also tell people not to put public fields in their objects, but exceptions exist. This is an exception to the rule, because it is simpler and safer to just say it is a field. We sat back and asked: Why is the rule thus? Does it apply? In this case it doesn't.


Private fields + Public accessors == encapsulation

Consider the example below

public class A {
    public int a;
}

Usually, this is considered bad coding practice as it violates encapsulation. The alternate approach is

public class A {
    private int a;

    public void setA(int a) {
        this.a =a;
    }

    public int getA() {
        return this.a;
    }
}

It is argued that this encapsulates the attribute. Now is this really encapsulation?

The fact is, Getters/setters have nothing to do with encapsulation. Here the data isn't more hidden or encapsulated than it was in a public field. Other objects still have intimate knowledge of the internals of the class. Changes made to the class might ripple out and enforce changes in dependent classes. Getter and setter in this way are generally breaking encapsulation. A truly well-encapsulated class has no setters and preferably no getters either. Rather than asking a class for some data and then compute something with it, the class should be responsible for computing something with its data and then return the result.

Consider an example below,

public class Screens {
    private Map screens = new HashMap();

    public Map getScreens() {
        return screens;
    }

    public void setScreens(Map screens) {
        this.screens = screens;
    }
    // remaining code here
}

If we need to get a particular screen, we do code like below,

Screen s = (Screen)screens.get(screenId);


There are things worth noticing here....

The client needs to get an Object from the Map and casting it to the right type. Moreover, the worst is that any client of the Map has the power to clear it which may not be the case we usually want.

An alternative implementation of the same logic is:

public class Screens {
    private Map screens = new HashMap();

    public Screen getById(String id) {
        return (Screen) screens.get(id);
    }
    // remaining code here
}

Here the Map instance and the interface at the boundary (Map) are hidden. 

Getters and Setters are highly Overused

Creating private fields and then using the IDE to automatically generate getters and setters
for all these fields is almost as bad as using public fields.

One reason for the overuse is that in an IDE it’s just now a matter of few clicks to create these accessors. The completely meaningless getter/setter code is at times longer than the real logic in a class and you will read these functions many times even if you don't want to.

All fields should be kept private, but with setters only when they make sense which makes object Immutable. Adding an unnecessary getter reveals internal structure, which is an opportunity for increased coupling. To avoid this, every time before adding the accessor, we should analyse if we can encapsulate the behaviour instead.

Let’s take another example,

public class Money {
    private double amount;  

    public double getAmount() {
        return amount;
    }

    public void setAmount(double amount) {
        this.amount = amount;
    }

    //client
    Money pocketMoney = new Money();
    pocketMoney.setAmount(15d); 
    double amount = pocketMoney.getAmount();  // we know its double  
    pocketMoney.setAmount(amount + 10d);
}


With the above logic, later on, if we assume that double is not a right type to use and should use BigDecimal instead, then the existing client that uses this class also breaks.

Let’s restructure the above example,

public class Money {
private BigDecimal amount;

public Money(String amount) {
this.amount = new BigDecimal(amount);
}

public void add(Money toAdd) {
amount = amount.add(toAdd.amount);
}

// client
Money balance1 = new Money("10.0");
Money balance2 = new Money("6.0");
balance1.add(balance2);

}

Now instead of asking for a value, the class has a responsibility to increase its own value. With this approach, the change request for any other datatype in future requires no change in the client code. Here not only the data is encapsulated but also the data which is stored, or even the fact that it exists at all.

Conclusions

Use of accessors to restrict direct access to field variable is preferred over the use of public fields, however, making getters and setter for each and every field is overkill. It also depends on the situation though, sometimes you just want a dumb data object. Accessors should be added to a field where they're really required. A class should expose larger behaviour which happens to use its state, rather than a repository of state to be manipulated by other classes.

More Reading

http://c2.com/cgi/wiki?TellDontAsk

http://c2.com/cgi/wiki?AccessorsAreEvil

Effective Java

 

 - See more at http://muhammadkhojaye.blogspot.co.uk/2010/10/getter-setter-to-use-or-not-to-use.html

 

Design Java (programming language) Data (computing) Object (computer science)

Opinions expressed by DZone contributors are their own.

Related

  • Distribution Design Patterns in Java - Data Transfer Object (DTO) And Remote Facade Design Patterns
  • Protecting Your Domain-Driven Design from Anemia
  • Unraveling Lombok's Code Design Pitfalls: Exploring Encapsulation Issues
  • Architecture and Code Design, Pt. 2: Polyglot Persistence Insights To Use Today and in the Upcoming Years

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!