21

I'm working in a java role after working a couple years in functional programming. Our company was bought by google and I took a java role after the acquisition.

Coming back to java as a polyglot developer, I'm generating getters for immutable objects and I'm seeing it's a total hogwash.

Are there any reasons why the 'getField' convention should be used so prolifically? To me it seems almost horrifying at this point that so many libraries expect public getter methods to work with their functionality when simply making a field public and final would have the same effect as making only a getter on a public mutable field.

Why isn't it more of a common practice to ditch the setters and just expose a final field?

15
  • 5
    Think about what happens when you didiscover that the field "x" that you made public and final actually has to be non-final or, worse, has to be changed so that the correct value has to be calculated when someone asks for it.
    – Blrfl
    Jul 20, 2014 at 23:13
  • 4
    Java getters are archaic - .NET's properties are much better. However, as always, when moving between languages it's important to follow the style guidelines of the language. Most of the time there's a good reason for the guideline (compatibility, readability or refactorability are the three main reasons usually). As others have mentioned, using getX() is a lot more flexible than public final int X;. Not every Java object should be immutable either. You're not functional programming, you're Java programming now.
    – Stephen
    Jul 21, 2014 at 3:49
  • 3
    I think it's a weak argument to say that because everyone does it, it's a good thing. For example, Bloch wrote some very influential works on java such as the concurrency book most often cited and "effective java." In Effective Java he discusses immutability quite a bit offering the guideline: "If a class cannot be made immutable, limit its mutability as much as possible. [...] Make every field final unless there is a compelling reason to make it nonfinal." It is safer in concurrency and easier to reason about. I can't see many reasons to NOT follow that other than "other people do it".
    – JasonG
    Jul 21, 2014 at 3:55
  • 3
    I see that you're trying to edit your question with some points of your own. Respectfully, this is not the place to engage in an extended discussion. If you want to do that, try The Whiteboard. Jul 21, 2014 at 4:35
  • 1
    java.dzone.com/articles/getter-setter-use-or-not-use-0. I'm intrigued though. I almost never use properties (with some exceptions for obvious consts (like pi in a maths library) etc), because of encapsulation, flexibility and working with interfaces/inheritance. On the whole, are attitudes different functional programming land? Jul 21, 2014 at 10:50

12 Answers 12

29

For flexibility -- this has to do with what happens when you change the class later.

If foo.x is a publicly accessible member (even a final one), and you decide that you no longer need that member, code which accessed that method is now broken.

If you have only provided a getter, then you can always provide a compatibility version of that getter which computes the value as needed, and code which worked before still works.

For example, suppose we are writing a Point class, and we decide to go from vector (x,y) to polar (angle, magnitude) representation to internally store the point's position. Code which looks for a member named x is now broken -- but I can always provide a method named getX() which computes the X coordinate of the point and returns it.

10
  • 2
    To cite Martin Fowler's Refactoring: He does not use getters and setters as he can rename the private variable variableName to _variableName and create a getter called variableName.
    – JasonG
    Jul 21, 2014 at 3:32
  • 3
    This is nice in general -- but it makes sense to follow the conventions of the language and project you are working with. In the Java world, the getX() and setX() names are pretty idiomatic, and a lot of tools and frameworks know to look for them -- including in some cases via reflection at runtime.
    – jimwise
    Jul 21, 2014 at 3:35
  • 4
    Won't doing Martin Fowler's trick still require a library's user to recompile?
    – James
    Jul 21, 2014 at 7:30
  • 7
    Aren't braces mandatory when calling functions in Java? So if your code was int x = point.x; you would have to change to int x = point.x();?
    – Falco
    Jul 21, 2014 at 9:28
  • 3
    Good answer, but I think all the answers are missing one more example: the idea of lazy or non-lazy evaluation. You came close when you described the vector vs. polar idea, but even deciding to delay the evaluation of a value from initialization to the first call is an implementation detail that you usually want to keep flexible. Using the final keyword is an implementation detail. The immutability contract is that "no matter how many times you get this value, it won't change". Jul 21, 2014 at 14:46
7

The first problem that comes up in such a design is "what if something isn't final anymore?" You've decided that 'no, you really do need to change that field sometimes' and so when you remove the final, you're left with a public int field; sticking out there for anyone to fiddle with.

The next problem is, you've got to keep using it. Its part of the public API of the class. If you decide later that it doesn't have any meaning in some future version of the refactored class because instead of defining a rectangle as "length of short side, length of long side" with those two fields being public, you've now refactored it so the internal representation is two Points so that you can use it more easily in AWT. But, you've got two fields there that you have to maintain, even though the internal code doesn't use them anymore.

This becomes even more 'fun' when extending the class. Because now everyone that uses the extended class also has those two public final fields that they have to maintain now and is part of their API.

The problem behind these last two examples is that you've exposed some of the implementation of the class to other things. This isn't so bad if the modifiers on the fields are such that they are restricted to only code you have written. A default (package) protection on a fields so that other classes in the package can access it directly? Not so bad. No getters on a private inner class? No problem at all.

Some tools out there use reflection and depend on getters and setters. One that most easily springs to mind is Expression Language used in JSPs that expects a Java Bean compliant object. If you have ${foo.total} it invokes foo.getTotal(). As soon as the code touches JSP, it becomes a bit of a pain to not have getters and setters (related SO) - decorators everywhere.

7
  • 3
    I don't believe it is ever necessary to have mutability - see functional programming for examples. you create a new instance when you need to modify something. As per Bloch's effective java, you should prefer immutability.
    – JasonG
    Jul 21, 2014 at 3:33
  • I updated my answer with a few counter arguments - I'm just looking to have an honest discussion because as a polyglot with strong fp experience I question these conventions heavily coming back to Java . Thank you for your response :)
    – JasonG
    Jul 21, 2014 at 3:35
  • 2
    @JasonG Note the difference between "you should prefer" and "you cannot have anything but". Getters work in both cases of mutability and immutability, public final - only in one. Since getters don't add any overhead whatsoever (I would argue that they make development easier since all readable attributes are nicely set out under get* and all writable under set*), why would you use an inferior version other than that you're more used to it from other languages?
    – Ordous
    Jul 21, 2014 at 10:23
  • @JasonG if you want to discuss it, I'd be happy to take it to chat. However my answer still stands as is. I will point out that Fowler is working in Ruby - a language where accessing a field or calling a method is the same notation. Changing a field to a getter in Java is a breaking change for the API. Java is also not a functional language. To elaborate on Ordous point, Hotspot will inline methods less than some size (-XX:MaxInlineSize=) and getters will fall into this and be the same byte code as field access after optimization.
    – user40980
    Jul 21, 2014 at 10:45
  • @MichaelT I didn't know about maxinlinesize. What happens if I set it to 3 and write foo() { i++; foo(); } will this cause the compiler to infinite loop? Or will it break somewhere?
    – Cruncher
    Jul 21, 2014 at 17:40
6

I'd like to add something people haven't mentioned:

You can override getters and setters and you can specify them in your interfaces. You cannot do this with fields.

5

First: It is reasonable to use Functions instead of fields, because the syntax is different! If you have Code which ist int x = point.x and you decide to change the internal representation of Point to a lazy model which calculates x only when needed, you would have to refactor all legacy code, since a public field access and a method call are fundamentally different: So the code would have to be rewritten to int x = point.x()

So why should we call accessor-Methods to fields getX() instead of just X() ? because it is convention. The argument because everyone does it is perfectly acceptable here. Why do we write Classnames in Camel-Case? Why do we first declare Fields and then Methods in a class? Why do we call the iteration-variable in a simple for-loop i ?

Because it is idiomatic. Almost every Java-Programmer will expect it this way and can easily understand and maintain your code if you follow theses conventions. If you choose a different style and choose different names and code-style you should have a really good reason why this other style is better, because it will make your code less portable and harder to maintain!

1
  • I remember some C-alike language, that support properties with accesor functions, that have syntax different from functions & fields ...
    – umlcat
    Jul 21, 2014 at 20:55
2

It's not always recommended, read for example the Android guidelines:

Avoid internal getters/setters

Virtual method calls are expensive, much more so than instance field lookups. It's reasonable to follow common object-oriented programming practices and have getters and setters in the public interface, but within a class you should always access fields directly.

0
2

The answer is that getters and setters give the library writers the flexibility to change the internal workings of their library without requiring users of that library to recompile every time a change is made. This area is called Binary or Behavioural Compatibility, and is one of the basics of Software Engineering and came about because exposing the internals of a class can quickly become a maintainence nightmare.

THere's unlikely to be any peformance benefit either in directly accessing a field instead of through a getter, unless your HotSpot compiler is sub-standard.

There are certain cases, e.g. small classes, where is can be considered unnecessary.

Renaming a final field and introducing a getter instead is a BC break. It will require the users of you library to recompile which will just piss them off (I've worked in situations where we were not allowed break BC, or there'd be legal ramifications)

As for making everything immutable and making a copy when a change is needed... try sorting an array with that logic. Immutability comes into play with concurrency when threads share data, but there's a lot more to it than just making everything immutable.

Your question is really a moan about why Java isn't Scala, and well the answer to that is that it's because it's Java.

1

I think it's mostly because of legacy reasons.

  • Some of Java's older apis are not immutable (the Date class is a mutable object, there is probably an alternative in java 8 now). Thus an argument for using getters is to potentially return immutable instances of these older objects. This is in contrast with functional programming where everything is considered immutable by default.
  • Making things public and final does not necessarily make them immutable in java. As a simple example if a List was final, the object might not be mutable but the contents within the list are (functional programming would return a new immutable list in this case)
  • Java also has a JavaBeans specification which recommends the use of getters and setters. It supposedly aids in portability (which is probably why frameworks use this for reflection purposes, although some do inspect the fields itself)
3
  • 1
    Yes definitely - you have to use an immutable datatype to truly stop it from being side affected. If you can get it and it's mutable then there is the possibility to change it even if you're not re-assigning it.
    – JasonG
    Jul 21, 2014 at 11:39
  • (Btw I like this answer a lot.)
    – JasonG
    Jul 21, 2014 at 17:14
  • "the object might not be mutable but the contents within the list are" I think you mean that the reference is not mutable. The object very much is. In any case, you could generalize this to: If you have final fields which are mutable, then the class is still mutable.
    – Cruncher
    Jul 21, 2014 at 18:16
1

Sometimes something you get from an object is stored internally as a field, and sometimes it isn't. The example I use with my students is a Date class. It would be madness to represent a date internally as a separate day, month and Year; you just use the number of days passed since some reference day. This ensures consistency, and makes it easy to compare dates and do arithmetic.

Of course, from the perspective of the user of your class, it's a different matter. They want to know about the month and the year and so on. So you compute those on the fly and expose them with getters.

To me, this is the very heart of programming: make things easy for your users and (if needs be) difficult for yourself. This means working from the outside in. Set up the API that your user needs and then worry about how to implement it. And as usual, if you happen to be your own user, it doesn't change a thing. Every piece of code has a user and a developer.

So imagine you're a user, and you want to ask object foo for its bar. In your world, your have to stop to consider how foo is implemented. Is bar an stored explicitly as a field, or is it computed on the fly?

This isn't just about saving the user time, the fact that a user has to think about implementation details shows a seriously leaky abstraction. As others pointed out, this means that you can't just change bar from a field to a value that's computed on the fly. Saying you "have to recompile" doesn't do justice to the impact. You have to track down every piece of code that calls your class and figure out what the impact is. This could be in another company, in another country, and it could be a decade later.

Good coding means worrying about you interfaces, because nothing costs more than changing an interface. Getters are good interface design.

0

I think a serious part of the answer is that Java developers are used to the convention of using getters and setters. If you use a different style, other Java developers will have a somewhat more difficult time reading your code. Considering that the convention doesn't really cost anything in terms of performance or maintainability, I believe that the increased readability is worth it.

1
  • 1
    One way this plays out practically: when I'm working with Java code in an IDE and need to access an object's members, I habitually type in .get or set and then use autocomplete to see what comes up. It would be jarring to be exploring an API and realize this convention didn't hold.
    – Kevin
    Jul 21, 2014 at 18:40
0

I'm a big proponent of immutable domain objects as well, and have seen cases where encapsulating the field with a getter has sure come in handy.

One point to note is that the immutability of an object can be pretty useless if it's only so in a shallow way.

To illustrate the point, consider a class that has a final field (private or not) of type Date. Now the point of immutability is that your object won't change; it could be passed off to other methods, cached, shared around across threads, etc., without fear of anything changing.

But, consider if someone gets a hold of that date field. I'm not saying that Jimmy is malicious or stupid, but he can do some pretty surprising things, and there's no guarantee that he's not going to call date.setTime on that puppy.

So, what do you do? You use encapsulation. You make the field private and exposing it through an accessor (getter), which instead of returning the stored data object, creates a copy with the same value. Oh, and you do the same thing in your constructor (you wouldn't want Jimmy to hold on to the reference he passed in and do more malicious/stupid/surprising things, would you?)

Okay, so now you expose, say, 7 fields directly, and one via an accessor. And Jimmy comes along and wants to use your API, and, well, what the hell is going on? Is this guy giving me the fields directly? Or wrapping them in methods? Some of each? Can't we just be consistent, he wonders?

And in this case, yeah, I have to agree with Jimmy.

1
  • From both a semantic and performance standpoint, it would be cleaner to have methods which wish to have a mutable class object containing information received from a method, pass to that method the object into which it should store the data. If client code says Date myDate = new Date(); someObject.copyDateTo(myDate);, there will be no semantic confusion if myDate is modified. If instead the code had said Date myDate = someObject.getDate();, it would be unclear whether the recipient would own the returned object and could modify it as it saw fit.
    – supercat
    Jul 21, 2014 at 19:35
0

Use of accessors is convenient in the following cases:

  • When, during some hairy debugging, you need to keep track of who is accessing a given field. If there is an accessor method, it is trivial to add the relevant tracking code in that method; otherwise, this is a more complex and protracted game of searching throughout all the code which potentially accesses that field (or it could be done with some instrumentation magic, but that's hardly simple).

  • You might want at some point to save on memory, and replace your "final" field with a piece of code which recomputes the value dynamically, instead of keeping it around. Depending on the relative costs of CPU and RAM, this may be a worthwhile exchange -- and since it is a performance-related issue, it cannot be decided until actual measures have been made, i.e. quite late in the development process. At that point, changing an already existing accessor method is much easier than tracking all callers throughout the code base.

One important point is that Java was meant for big projects involving a lot of people; in such contexts, one cannot assume that recompiling the whole code is practical or even possible. Interfaces are where developer teams meet, and they are very hard to change. Modifying a field access into a method call is an interface change.

On the side of pure performance, Sun pretends that the JIT compiler is smart enough to inline calls to simple method, so that a trivial getter method actually costs nothing at runtime. Or so they say.


Of course, a convention is just a convention. The reasons above should be considered as arguments for using accessors generally, but that's not a dogma. It is more a reminder that the software development cycle is long, often involves a lot more people than initially envisioned, and short-term gains must be balanced against long-term costs. It is OK to use public final fields if that is fine for you; but remember that in any project involving more than one developer, you are not alone, and interface decisions impact everybody.

1
  • "Modifying a field access into a method call is an interface change." -- whats more, all fields defined in an interface are implicitly final static. You can't define a non-static field in an interface (SO). This means also that you can't use an interface to pass around an object that is intended to be accessed via fields. This is also true of C# (note: Eric Lippert answer there) (properties - yes, fields - no).
    – user40980
    Jul 22, 2014 at 15:02
0

I fully agree with the doubts and conclusions of the author of this question.

IMMO in java getters are mainly used because people like "rules of thumb" like "all fields must be private and have a getter" and really don't understand why its the real reason behind this.

Its really annoying when i see a java "bean" with N fields and getter&setters for all the fields, and the people do this because "its object oriented" when in fact this totally breaks encapsulation and creates coupling and more coupling with code like that:

  instance.getFoo().getBar().getFooBar()...

Sometimes you don't need and object, you need a data structure, its perfectly right put all field public and finals.

Sometimes you want an object, if you really want an object why you expose internal state with a getter?. off course you want to ask for something to your object (normally i prefer a tell don't ask approach, but not always is posible) ask you object for that value, but this its not a getter, this its a method that an object expose to give some information to the outside world, and by any means this implies that this object has a property holding this value!.

IMMO the term "getter" its for me one of the most notorious symptom of the big misunderstanding of object orientation in the community.

Not the answer you're looking for? Browse other questions tagged or ask your own question.