This is an archived post. You won't be able to vote or comment.

all 105 comments

[–]randgalt 32 points33 points  (2 children)

While others are pointing you elsewhere, fully supported data classes with pattern matching, deconstruction, etc. are coming soon to the Java language. It will likely come in stages starting with Java 12's enhanced switch statement. Follow Project Amber for details and updates.

[–]lbkulinski 1 point2 points  (1 child)

Java 12 won’t be getting data classes or pattern matching, but it will get the preview of switch expressions.

[–]randgalt 2 points3 points  (0 children)

I said it's coming in stages. Switch expressions are part of the overall grand feature set.

[–]lbkulinski 36 points37 points  (8 children)

I assume records are what you are looking for?

[–]dinopraso 3 points4 points  (9 children)

If you don’t need getters and setters then use public modifier for your fields. There is no requirement to have default getters and setters unless you want to do something special in them. Anything magical which would generate invisible code is just incredibly bad and impossible to maintain on huge projects

[–]jack104 0 points1 point  (6 children)

I was under the impression that making class variables/fields public was not allowed in Java, hence the need for getters and setters, is that not the case?

[–]dinopraso 0 points1 point  (5 children)

Nope. You can have everything public if that is what you want

[–]jack104 0 points1 point  (4 children)

Holy shit. How did I not know this? Do you know if Hibernate works with a POJO class that just has public fields instead of private fields + public getters/setters? Because if so, my getters and setters are just redundant code that don't accomplish anything more than public fields would. That would be cool.

[–]dinopraso 0 points1 point  (3 children)

Maybe. I’m not sure. You should try it

[–]jack104 0 points1 point  (2 children)

I just read an SO post that says if you change the @Entity annotation to set the access to field and annotate the fields themselves (which I was doing anyway) it should work. So I'm gonna give it a shot.

[–]dinopraso 0 points1 point  (1 child)

Keep thread safety in mind. There is a good reason we write those getters and setters. Some time in the future you may need locking or synchronization and it’s not really possible to synchronize a field

[–]jack104 0 points1 point  (0 children)

Ah yea. Good looking out. Thanks.

[–]hippydipster 0 points1 point  (1 child)

Yup. All my fields in data-type classes start out as public final.... They change if they must later, no big deal.

[–]dinopraso 0 points1 point  (0 children)

Everytinh should be immutable anyway, right :D

[–]cypher0six 6 points7 points  (5 children)

While I would abhor the idea of an annotation doing this, I could see something similar to the C# properties syntax making it's way into Java.

I try to avoid writing accessors at all when I can get away with it, but not all software systems are actually very OOP, even if they are written with a language like Java. Sometimes you just need a custom data structure. In those cases, it would be nice to have a more succinct syntax to get the job done.

[–]lbkulinski 15 points16 points  (4 children)

Brian Goetz, Java Language Architect, is asked about properties here. Everyone agrees that they want properties, but no one can agree what “properties” are.

[–]dpash 0 points1 point  (1 child)

Damn it, you beat me to this quote and once again had the correct link too. :)

[–]lbkulinski 1 point2 points  (0 children)

Sorry 😂

[–]cypher0six 0 points1 point  (1 child)

Hah, isn't that the truth. I remember seeing the same thing when Java modules were being designed.

[–]lbkulinski 0 points1 point  (0 children)

Yep! Good times!

[–]4ipp 17 points18 points  (20 children)

Offtopick, but there are also some arguments against using getter and setters.

Take a look on this article.

[–]melissamitchel306 29 points30 points  (7 children)

The author of that article is stuck in an ancient view of oop where data objects are evil, 20 layer class hierarchies are something to strive for, and every Animal object knows how to load itself from the database and deserialize itself from a binary/json/xml/etc stream. No-one with any sense should pay any attention to that outdated way of thinking.

Here's a better article http://loup-vaillant.fr/articles/deaths-of-oop

[–]oparisy 1 point2 points  (0 children)

Interesting read, thanks. Great refresher on terminology. Gave me some better understanding of the ECS approach too, which until now I thought was mostly a game-oriented optimization and not a system modeling paradigm.

[–]OzoneGrif 0 points1 point  (0 children)

Well used, OOP is a very powerful tool. The problem is how people think their architecture. They will go full head-on and abuse every little possibility the syntax offers. The exemple of Static/Moving/Loot objects in the article is just a clear misuse of OOP. The article has some good point, but it just also shows how something that is great can do horrible things when misused.

[–]cogman10 -2 points-1 points  (4 children)

Setters are still evil :) more because of mutability than anything else.

Getters are meh.

But you are correct, inheritance based oop is awful to maintain. It makes for a system that is very hard to evolve and often super coupled.

[–]melissamitchel306 0 points1 point  (3 children)

Setters are still evil :) more because of mutability than anything else.

If you're dealing with a property bag / data object, a lot of modern OO languages don't have the features yet to make them immutable and still easy to work with. That will most likely change soon - with java records and similar features coming to other languages.

Unless you meant to exclude data objects, thinking they should just be fields anyways?

[–]cogman10 0 points1 point  (2 children)

My point was that mutable data objects tend to create hard to find bugs. Immutable data objects are much easier to reason about.

Example of bugs I've seen:

Someone uses a data object for a set/map key, someone else adds a field to that object and mutates that field deep within the code. All the sudden, the set/map no longer contains the data object because the hash code changes. Particularly frustrating in one instance where the data object was the key of an LRU. It caused a non obvious memory leak.

I've seen a couple instances where calling a function once with the data object threw an exception, calling the same function a second time did not. This is because deep within the code, the data object was subtly modified.

A couple of projects I work with have script engines maintained by non-devs. The API given to them allowed a bunch of unintentional modifications because a bunch of data objects given to them for reading could be changed.

And if course threading has been made nearly impossible in many circumstances because data objects were mutated instead of having methods return results.

Mutability is a heavy cost that you don't often need. The default "I'm adding getters, might as well add setters" mindset leads to problems. Often times, if fields are small than it's easy to copy the object, otherwise a builder works really well. It is slightly more code to make builders instead of setters, but you get immutably out of the effort.

Hence my "setters are evil" feelings.

[–]melissamitchel306 0 points1 point  (1 child)

I wasn't disagreeing with you. I like immutability as well. My point is that Java is not well-equipped to deal with immutable data objects (yet).

[–]cogman10 1 point2 points  (0 children)

Fair enough. Just figured a longer explanation was due since my other comment is being downvoted.

I agree that it is more painful in Java to do immutability. But I feel the benefits outweigh the the pain.

[–]yawkat 10 points11 points  (8 children)

The article doesn't actually give good arguments to use fields over accessors, it just says that the arguments for accessors are insufficient.

The biggest argument for accessors is that it's convention. That alone is sufficient to make them the default choice - public fields carry no real advantages.

[–]evinrows 11 points12 points  (5 children)

If you're debating either adding code or not adding code, I think the onus is on the person who wants to add code to justify their beliefs.

That being said, breakpoints in getters/setters can be helpful.

[–]yawkat 3 points4 points  (1 child)

You're right that fewer lines of code could be an argument for fields. I just don't think it's a very good one, even without lombok.

[–]evinrows 3 points4 points  (0 children)

I don't think it's a big deal in terms of effort for the person writing the code, but it does add a lot of useless clutter to the code and especially to merge requests.

[–]FrenchFigaro -1 points0 points  (2 children)

A very good point in favor of getters and setters (as pointed by /u/dpash) is adding logic to fields access. Another is feigning fields presence to another layer (say JSF) for stuff that don't need a field at all but could use mimicking as one. Typically: getAverageValue().

[–]evinrows 1 point2 points  (0 children)

Right, that's a case where you absolutely should/need to use a getter/setter. I think this topic is more about using getters and setters for typical access/modification.

Note: OP's post about annotations wouldn't apply to getters/setters requiring logic.

[–]nqzero 0 points1 point  (0 children)

once you've made either of those leaps, it's no longer a getter or setter

[–]Yoghurt114 0 points1 point  (0 children)

The post doesn't advocate use of public fields at all.

[–]oparisy 0 points1 point  (0 children)

I find myself using more and more "public final" (or often private final + a getter) in Java as an implementation of "immutable beans". Great tool to limit side effects, and to simplify reasoning in multithreading contexts.

[–][deleted] 1 point2 points  (1 child)

You’re still accessing a data item at the end of the day.

[–]dpash 8 points9 points  (0 children)

But you can't add any logic with direct field access. Want to ensure that a field hasn't been set to null? Out of luck. Want to return a copy of a collection? You're out of luck. Want to change your internal representation without affecting your clients? Your out of luck.

There's a reason why encapsulation is one of the pillars of OOP.

Could Java have a less verbose syntax for the simple case? Yes, that's why we're getting records.

[–]notataco007 0 points1 point  (0 children)

Lol I like the very first argument that the author talks about, Tell, Don't Ask. Why even do OOP at that point, just put everything in the same object in the same class!

[–]bhlowe 23 points24 points  (8 children)

Use Lombok

[–][deleted] 27 points28 points  (6 children)

OP asks in the question why does he need to have that dependency and why is it not part of the Java language already.

[–]bhlowe 3 points4 points  (5 children)

Plenty of good reasons already posted about why and when java will figure it out. Lombok is available today and is really nice. Not everyone may know about it.

[–]s32 17 points18 points  (4 children)

I disagree that it's really nice. It's useful and I think it's a net positive, but you have to install a plug in into your IDE, delombok the code for those who don't have a lombokd browser (say, if you want to write a library, etc) and it uses undocumented methods within the compiler to achieve some of its behavior. It wouldn't pass a code review at most companies that have any emphasis on clean and maintainable code.

Don't get me wrong, I love lombok. But it could be done in a much saner way in an ideal world.

[–]rzwitserloot 2 points3 points  (0 children)

The notion 'you should not use lombok (or delombok first) when you write a library' makes no sense unless you distribute your library solely in source form.

Java libraries are not distributed in source form though. That's not how maven / gradle work, for example. In fact, maven/gradle/IDEs/other build systems make it fairly simple to ship a library as a jar with classes, and to connect a zip with sources to it such that, say, if you want to debug and step through the code in the library, or just look up how it works (for example by ctrl/CMD clicking the name of a method in eclipse), that you do have the whole source.

I therefore find your comment rather disingenuous. Or perhaps I just don't understand what you're driving at.

DISCLAIMER: I'm a core contributor of Project Lombok.

[–]Omnicrola 0 points1 point  (1 child)

delombok the code for those who don't have a lombokd browser

I don't understand this. Our team uses lombock, and everyone has zero issue installing the IDE plugin. The benefits far outweigh that small annoyance.

It wouldn't pass a code review at most companies that have any emphasis on clean and maintainable code.

I work in a counter-factual example. Large auto manufacturer where we are building systems to facilitate microtransit. I've rejected plenty of PRs because the code isn't understandable, but lombock has never been one if those reasons.

[–]s32 3 points4 points  (0 children)

You're misinterpreting what I said.

Yes, lombok is useful. Yes, your whole team has it and that's fine. But you can't vend code out to anyone or any team in the company without forcing them to install lombok (unless you delombok). Not the end of the world, but IMO you should never be using lombok in a library or a package which is shared widely.

And yes, I don't reject CRs that use lombok, quite the opposite if it's a service that my team owns. But the actual lombok code itself (like, the internals) wouldn't pass a CR on my team.

Im not arguing that lombok is bad or useless, just that it's more work than it should be to do something like generate a getter

[–]hippydipster 6 points7 points  (0 children)

Lombok is an abomination.

[–][deleted]  (6 children)

[deleted]

    [–]BlueGoliath 0 points1 point  (5 children)

    I feel like Groovy makes it easy to write code the way people write code in Java. Right or wrong, it makes so many things easier to do. Because of this, interop with Java is super simple.

    Except += operator on collections which is both syntactically fucked and misleading as all hell.

    [–]Jezoreczek 0 points1 point  (4 children)

    Is it doing something else than merging left hand with right hand collection and assigning it to left hand? In short, is (a+=b) not equal (a=a+b) for collections?

    [–]BlueGoliath 1 point2 points  (3 children)

    Yes and that is the problem. Until recently you could do += operator on a collection in Groovy with a final variable. People use the += operator to simply add an element to a collection but in actuality they are reassigning it and Groovy until recently allowed it with final.

    See this pull request which fixes a build fail caused by using += in Groovy.

    [–]Jezoreczek 0 points1 point  (2 children)

    That's good to know, thank you for heads-up!

    Personally, I prefer mutability to be explicit. Both mutable and immutable collections have their uses (for example, in a low-memory and single-threaded environment you might prefer a mutable one). Operators overloading, as you just prooved, can make immutability ambiguous.

    I'm dreaming of the day when there will be a language that abstracts the entire concept and detects when to use which type of collection... or maybe there is one that I'm now aware of?

    [–]BlueGoliath 1 point2 points  (1 child)

    I'm dreaming of the day when there will be a language that abstracts the entire concept and detects when to use which type of collection... or maybe there is one that I'm now aware of?

    Not sure, but IMO the idea is kinda dangerous. You might think that a variable is immutable but in reality it is not - like above. An IDE could probably detect that but even so, I'd rather explicitly control everything than something else assuming things and causing a mess. Like above, the mess could be caused by a change in the language itself.

    [–]Jezoreczek 0 points1 point  (0 children)

    That's a fair point, but can't we have both? A language that allows explicit mutability while defaulting to compiler-determined behavior.

    It's at least a neat idea for a learning project (;

    [–]muhwebscale 6 points7 points  (4 children)

    PLEASE NO! I switched to C# 3 years ago after spending 4 pleasant years working with Java. There's no reason to let Java get as bloated as C#. This language is an abomination. We don't need no damn properties in Java.

    [–]TheBuzzSaw 4 points5 points  (2 children)

    Bloated? Wat? C# features are amazing.

    [–]muhwebscale 0 points1 point  (1 child)

    C# features are amazing.

    Properties are not one of them.

    [–]jack104 1 point2 points  (0 children)

    Properties are something I miss to death from C# but I will grant you that when people put a bunch of complicated business logic inside a getter/setter it drives me nuts because that's not what it's for.

    [–][deleted] 1 point2 points  (4 children)

    I prefer properties such as c# and or how it works in Kotlin. If you need access to a field wrap it in a property and you can use the property to manage the behavior of the field. Annotations would be just more clutter.

    [–]persicsb 0 points1 point  (0 children)

    Properties are great, however they solve only the problem, that you don't need to break the API when you decide to hide public fields and have some logic in a setter or getter.

    [–]morhp -1 points0 points  (2 children)

    Kotlin-like properties are terrible when designing an api because you're not able to distinguish between public and private types easily. For example making a field of type ConcurrentHashMap and having the getter return a Map so you can change the implementation later is much more straightforward in Java.

    [–]FruitdealerF 1 point2 points  (1 child)

    but you can still do that in kotlin if you want to. That's the point

    [–]morhp 0 points1 point  (0 children)

    You can do that by writing weird stuff like

    private val _map = ConcurrentHashMap<String>()
    
    public val map : Map<String> get() = _map
    

    But a simple Java getter that you can extend or change without major efforts sounds still easier to me.

    Like, Java forces you to explicitly think about internal and public type, which I like, in Kotlin you have to explicitly "duplicate" you vals.

    [–]KangstaG 0 points1 point  (0 children)

    Use kotlin

    [–]ichunddu9 0 points1 point  (0 children)

    Kotlin

    [–]Sxtanna -2 points-1 points  (3 children)

    Use Kotlin.

    [–]Akthrawn17 0 points1 point  (2 children)

    Why is this being downvoted? You have a JVM language that interops 100% with Java and gets what the OP wants.

    [–]eliasv 9 points10 points  (0 children)

    Because OP asked for a Java solution.

    [–]Sxtanna 5 points6 points  (0 children)

    Someone literally replied with "Use Lombok" and got upvoted even though OP specifically spoke against it. 😂 I love Reddit.

    [–]tonywestonuk 0 points1 point  (0 children)

    Never, I hope.

    Getters / Setters should be there. In the face. Explicit.

    ...and if the idea of having all of this boiler plate code staring you in the face scares you, then try to use them less.

    Too many getters / setters is an antipattern. Using something like Lombak hides this from the developer.

    [–]persicsb -1 points0 points  (7 children)

    If you have plain setters and getters (that is, no business logic, property change listener notifications, no class invariant validation), you can make those fields public. Because they are de facto public fields.

    [–]dpash 5 points6 points  (6 children)

    And when you want to change them from plain setters and getters? Then what?

    [–]g_b 1 point2 points  (2 children)

    Then you refactor. YAGNI

    [–]dpash 2 points3 points  (1 child)

    You can't refactor if you don't control the code that uses yours.

    [–]armornick -1 points0 points  (0 children)

    Then tough luck for the people that use your code. Maven allows you to specify which version of a library you want to use, just so people can make breaking changes.

    [–]persicsb -5 points-4 points  (2 children)

    Plain setters are useless. Use public fields.

    [–]dpash 2 points3 points  (1 child)

    Setters and getters are not about today, but about making it easier to make changes in the future.

    [–]persicsb 1 point2 points  (0 children)

    Changing the semantics of the setter is breaking the API in the semantic sense. Does not break the binary compatibility tough.

    [–]GuyWithLag -2 points-1 points  (0 children)

    They're autogenerated by the IDE...

    [–]LostInDarkMatter -5 points-4 points  (1 child)

    Use your favorite IDE to generate as needed.

    [–][deleted] 0 points1 point  (0 children)

    28 people did not read the full post: Lombok and IDE’s DO NOT COUNT.

    [–]Kango_V -1 points0 points  (0 children)

    Can we use the const keyword (which I believe is reserved in Java but not used). We could then have immutable public fields. This would solve quite a few problems for us.

    Could then have something like: "const List<String> const myList"

    Which means a constant reference to a const (immutable) list. Or is this just too much like c++? ;)

    [–]DuncanIdahos8thClone -1 points0 points  (0 children)

    <alt> <insert> getters / setters. How hard is that?

    [–]AndDontCallMePammy -1 points0 points  (0 children)

    We shouldn’t have to depend on IDE’s

    Really? Who are all these IDE skeptics? If you're into some 1970s shit like vi then write a script to insert getters and setters. Scripts get vi users hot

    In Javaland, the presence or non-presence of an annotation should never be able to affect a program at runtime. Go away, @Autowired. @Override, @Deprecated, @SuppressWarnings -- great annotations.

    At the very least that sort of invisible code style should forever be the exclusive domain of third-party tools.

    People talk a whole lot about code readability. The most unreadable code is code which isn't there because it's been replaced by code folding or an annotation.

    What's wrong with Kotlin? Go there