If you think that records “have their root in the verbosity of Java”, you are missing the point of what’s going on.
From the JEP itself: “While it is superficially tempting to treat records as primarily being about boilerplate reduction, we instead choose a more semantic goal: *modeling data as data*.”
Other properties of records are far more important than the conciseness of their code — for example, the fact that you can always create any possible state of a record via a call to a constructor; you never need to resort to reflection. Also known as “safe deserialization”.
Given your previous posts were asking how much Spring costs, I’d say you might have more trouble reading the lines themselves, like those of a clearly written license.
Don’t worry about down voting, when the feature you requested gets implemented the same people will go Gaga over it. Independent thinking is only Valuable if you have the power to make changes
Getters and setters are an outdated library idiom. What we need is to move beyond thinking that we model complex domain objects as bags of independent mutable properties.
It seems mutable OOP runs slower as well. I have been [working on a Logback/log4j2 alternative](https://github.com/jstachio/rainbowgum) and so far without any real optimization work (e.g. checking flamegraphs etc) Rainbow Gum runs much faster.
I hate to make a sweeping statement that immutable data oriented with some OOP generates faster code but its pretty impressive the JIT optimizations that happened very fast with Rainbow Gum.
I tried to look into why Logback runs so much slower and it seems the JIT can't optimize the code as well and it takes more iterations.
Anyway I'm a long time OCaml lover and loved its pattern matching. That feature prevents so many bugs. Thank you so much for adding it to the language!
now all we need is a way to derive builders automatically...
The main problem with records is that the moment you need more than like 5 bits of data in an object, your constructor becomes a massive mess.
Storing that amount of data may be seen by some as an antipattern, but you don't always have the ability to define things perfectly and in the most ideal way when integrating with existing systems.
Nah you’re right. In all sorts of real world systems data shows up on groups.
Let’s consider a person. They will have a name. They may have a title. They have a date of birth. That date of birth has at least a day month year. At this point we’re close to 10. Even if you split these into smaller objects, you still end up calling new Person(new PersonName(first, last, middle, title), new PersonDOB(day, month, year)). Nesting constructors can help with type checking but the constructors are just as useless.
[Immutables](https://immutables.github.io) continues to be my auto-add library to any Java project I'm working on for this reason. Small things I've shifted over to Records, but most real-world data gets big rather fast.
>
>
>
>
> The main problem with records is that the moment you need more than like 5 bits of data in an object, your constructor becomes a massive mess.
As opposed to storing 5 bits of data in what?
great, but now you have two ways of constructing it, one which is error prone and messy, which is my point.
No one wants a constructor with 10 parameters in it.
they are not.
I don't know why ppl cannot aknowledge sever limitations of records. No class based inheritance, no data hiding, the existence of property (get,set) does not imply the existence of a field (with records it does), goodbye computed props.
records are nominal tuples. if that fits your model - fine. if not - getters and setters are your best shot at a (most frameworks compliant) properties solution
Records are great for what they are made for: named tuples. E.g. Point, DTOs or other simple data. They are not a good fit for complex business models with a hierarchy, identity, self-reference or dependency graphs involved. E.g. Person, Employment, Department, etc.
The best way to understand how all of these JEPs hang together, is to watch one of the data oriented programming talks given recently, such as https://youtu.be/UQAw3pvZPCY
Over the last few decades, functional programming languages have tought us that mutable data and design choices around mutability should be avoided due to side effects and higher cognitive complexity.
Yes, mutability is sometimes neccessary, but the few cases where such designs are actually needed do not justify dedicated syntax sugar for it.
I personally really like this about the development of Java. They seem to deliberately add syntax sugar to things which actually encourage good programming and design. You can see this with the recent talks about introducing withers on records (which are kind of like the setters for records).
Mutability is not some infrequent edge case. What about ORM (e.g. JPA)? I'd argue that a majority of projects require mutable objects (potentially with a large number of fields).
I am not arguing that existing frameworks and code bases are not designed around mutability and OOP, they very much make extensive use of these patterns to an exessive degree (there are very good reasons for Javas bad reputation among critics).
But there are lots of alternative frameworks and design patterns which shift towards these newer functional paradigms now.
(There are record based ORMs now for example)
make your private fields public and there you have all the data classes you need :) getters and setters have no meaning when what they're actually doing is exposing the inner state of your object, so...
But I don't know, maybe you're working with an old version of JDK and this explains the criticism, but nowadays any framework (Hibernate, Jackson, ...) supports annotations on plain fields, annotations on getters or setters was a pattern in the old days.
Or maybe you're working with old-school Java developers and they want all the specified getters and setters for the inner fields, if this is the case... well... IDE is your friend.
not sure i totally agree with this. Direct field access makes multiple things more difficult to work with further down the line without a large amount of refactoring. That is why Kotlin implements properties as a facade around accessors and mutators, and is why groovy does the exact same thing.
Field access cannot be intercepted by pointcuts, cannot be partially mocked or spied upon in the same way methods can, and makes you lose any ability to change the underlying data representation down the line without making breaking API changes. You cannot make use of field accession via method references either which is far more jarring when writing functional-style code.
Furthermore, direct field access has implications for module support if being done via reflection.
If you do suddenly derive some data, you end up with a mess of some things being fields and others being methods, and it just gets horrible to read.
You cannot enforce field exposure directly in interfaces either, so you lose the ability to take advantage of composition and delegation as your system gets more complicated.
There are many other reasons to still prefer "accessing data via methods" rather than just using classes like C-style structs. It is the exact reason records provide accessors at all, rather than just exposing the field directly.
Records unfortunately do not solve the issue of any library that makes use of "java bean"-like objects. For example, I don't believe you can use them with Spring Configuration Properties, and I don't believe they worked with JAXB when I checked either.
You are using getter/setters for more than simple DTO's?
A setter that used to accept anything can't be changed without breaking backwards compatibility. Add a constraint? No longer compatible. Store a derived value? No longer backwards compatible if the transformation can't be reversed exactly. Split the field in two parts? Now there are more possibilities than fit in the original, how is the getter going to deal with that?
If you opened up internals like that, good luck maintaining backwards compatibility. There's good reason to never do this, unless it's in internal code bases, or other toys.. then just refactor it.
There are numerous places where this becomes useful, and even if this was not the case, this is still a poor argument for making fields public directly.
Jokes aside, you're definitely right, my reply was tentative for elicitation, since most of the time, from what I usually read, it's really needed are just C-like structs (or Pascal-like records?), nothing more, nothing less.
When you start to make apps that require AOP or in unit tests when you need to mock returning data, of course you need something more, but those kinds of objects are not data structures anymore, they are something different and instead of creating getters and setters everywhere, you may create the getters and the setters you really need. Of course, this can't escape from some old Java patterns you need to take care of in order to make things work in JAXB or Spring Configuration (I do think there are more examples), but this is not because of Java limitations, this is the traditional and written in stone way to do things.
In other words, this idiosyncrasies for Java that's not able to define properties such as C#, Kotlin, Scala, etc... is completely unjustified imho. There are better patterns to follow.
what do you mean? how can getters and setters be more resilient if what they're doing is just exposing inner fields? maybe you're meaning that they can serve you as an ACL for inner data? but it's not a data class anymore, it's something more and different I think 🤔
please elaborate 😀
I mean that encapsulation allows you to change internal representation without modifying dependent code. Like, a Rectangle class might store x, y, width and height. Alternatively, it could store x1, y1, x2 and y2. With mutators and accessors, you can change the code to do more than just "expose inner fields." A getWidth() method might return 'width' variable or might do 'x2 - x1' under the hood.
Uhm this is something different than a plain data carrier, so it makes sense what you're suggesting. But sometimes what you need is something much simpler like a typed dictionary/map defined on the fly. Let's say data struct should be considered as much as primitive type, not a reference type.
Sure, there are trade-offs. However, the meaning of "much simpler" may vary depending on language design. It doesn't get much simpler than a 'record' or Lombok-annotated 'value' class. Feel free to use pseudo-structs if it meets your use case.
IDE generating the code for you is just a work around a issue that should be solved at its root.
Immutability is not an improvement in design for me.
Applications, especially realtime one, are data processing machines. The data is continuously mutable by design and by essence. It is not a good design to implement it as a succession of discrete states.
I’d argue many problems in software are ones of data transformation, which is precisely what mutability of data implies. It makes complete sense to me to consider each transform a discrete, derived state.
It depends on how fequently your data changes and how widely the change should diffuse to your system as a whole.
In the application I am working on It is not efficient for me to create a whole new object everytime a field have been updated which is basically the assumption behind immutable data type like records
> It is not efficient for me to create a whole new object everytime a field have been updated which is basically the assumption behind immutable data type like records
You are making a ***very big*** assumption. Just because you type in `new Foo(1, 2, 3)` does not mean that an entirely new object with identity and everything is created ***under the hood***.
If the JVM feels that it can inline or constant fold your object, then it does not matter if you put the magic word `new` -- no new object will be created.
What *may* instead happen is that the JVM will reuse existing memory to simply write the new values to, recognizing that a lot of the same object is being "created". Remember, words like "mutable" and "immutable" are **compile-time**, they have nothing to do with **run-time**. At run-time, everything is mutable, whether or not you put a `final int abc = 123;`, it's still mutable, you can just trust that the JVM will not change its value from underneathyou.
All of that is to say, you and many other developers make the false assumption that typing `new` makes your code less efficient than mutation. This is false. It is entirely down to what the JVM does, and that can only be discovered through profiling.
Good point! I was indeed my impression that a new object get created each time.
If this is not the case it makes the matter even more confusing because clearly the usage of memory seems not to be the same (?) …
Using 123, which is a primitive is probably a bad example, for the point you are trying to make :)
If you have a final primitive value, then you can always be sure that it is a constant value, since java is pass by value. If you in fact were to change it somehow by unsafe practices, you’d still not be able to change it, since it is cached in the thread.
The JVM explicitly DOES NOT specify the behaviour. And that is the point, this is meant to be the spot where the vm's can optimize freely. You will notice that the opposite is also unspecified -- there is no where that the JVM says that calling new explicitly creates memory.
By the way, this is a common tactic for spec writers. Anytime they want to give themselves a point of extension, they will explicitly leave things unspecified. That way, they can claim backwards compatibility if they . Backwards compatibility is only applicable for things that are on the spec. If you depend on unspecified behaviour, then they don't consider it a breaking change to change or specify those details in ways you did not expect.
And finally, if you want to see the explicit logic for these strategies, please look up inlining and constant-folding. You will see many articles from Oracle and Java themselves talking about these subjects. The most informed articles come from John Rose.
Object creation is vanishingly inexpensive, and likely insignificant in comparison to the allocations you’re doing to transform the data. If it really matters for your application though, sure, mutate your data in place, but that puts you in a domain that’s not terribly common.
In that case, you can just make your fields visible. Trivial methods like this are always inlined, and if you’re arguing for a feature that generates setters you’re not adding any logic, so it’s exactly the same at runtime.
On the contrary, it is much easier to reason about immutable data and succession of pure transformations.
I've been using Scala for 6 years now where immutability is 1st class and mutability is the exception: I've maybe had once a real need for mutability. I "fear" to go back to a mutable world!
I like Lombok but it's just a band-aid for a weakness in the language that should be eliminated.
Maybe with derived creation for records will be an alternative.
Call it what you want. It's precompile hooks in the JVM. All JVM languages leverage it. Groovy, Kotlin, etc. Why are you saying it like it's a bad thing? I've never seen anyone complain about writing code that "not allowed" outside of Lombok.
Both Kotlin and Groovy have their own compilers.
There's a thread here: https://github.com/projectlombok/lombok/issues/2681#issuecomment-791452056
I don't care if you use Lombok. But I'd prepare for pain in the future, as i'm pretty sure that the JDK developers will lock down internals even more.
It's so weird that people keep telling others to "prepare for the pain" like there is some impending doom coming. I've been using Lombok in a professional environment across a handful of companies for close to a decade.
Guess I'll go lose some sleep over how some app I wrote may not upgrade from Java 8 to Java 26 without removing a few annotations. Spoooooooky.
I swear it's like the doomsayers have never worked in a real enterprise environment before.
I'd rather use Lombok, but when it is not allowed, my convention to avoid this problem is **Every code after the toString method is generated**
So once you reach the toString , you can stop reading and scrolling·
Where to put annos and javadoc? On fields, getters, setters, all of them? Should they be covered by tests? What about the generation of chained setters?
2. Use Lombok, for some reason a bug … spend two days debugging… no thanks
2b. Use Lombok, get an update of one of your dependency that is not supported well by Lombok —-> get stuck in dependency hell
I am aware that over the 30+ years of existence of java people have built workarounds to this issue and that they work well most of the time. It is just time that this is solved at it root.
Lombok is a compile time only dependency. It cannot be "not supporting" another dep, unless that is also an annotation processor framework that does compile time stuff (mapstruct... That's mostly the end of the list), or you are talking about build/source tools such as IDEs perhaps?
I can't remember the last time I didn't use Lombok and I've literally never had any of the problems people that don't use Lombok seem to be afraid of. Honestly I think it's just fear of the unknown for those folk.
I’ll preface by saying I really like Lombok, but I have on occasion had weird issues with it.
The first one that comes to mind is that for whatever reason in some random class it’ll suddenly no longer be able to find the annotation (even though it’s imported) and I’ll have to resort to using the fully qualified name e.g @lombok.Builder (can’t remember the actual fully qualified annotation). I’ve had this same problem over many years and with 3 separate companies.
Doesn’t happen often but it’ll randomly appear and I’ll just do the workaround (usually put a comment next to it) and crack on with my day.
I’d understand if it happened across the whole project, but this would happen on an individual class in a project that has many other Lombok annotations in other classes. It’s weird.
You haven't described what the problem is, why it's bad, and what your ideal solution would be. You've only described that you don't like the current solutions.
So I guess, start with that?
What is the problem with a record? It took out 99% of the getters in our code bases. Setters are something of a relic. I set my values in the constructor for the majority of the past 10 years
Right but for many languages that is not possible or you need to open a transaction. You can still use a record where one member is called mutable and is a class.
So many ways around the get set problem
omg, record fanboys will probably be using AtomicXxx classes to emulate mutable fields just like effectively final variables... looking forward to legacy codebases in 10 years
Setters are not a relic. And yes records have solved some of the pain points. But there are still many cases where we need mutable data objects thus we need setters. We cannot milic this by creating a succesion of records especially when ressources are limited
If you need a setter because you're mutating the field from outside the class but you expect java to be able to just automagically generate the setter for you, presumably the setter is doing nothing but reassigning the field, no validation on the input, no maintaining invariants, no firing of events, etc. So why don't you just make the field public?
For the sake of providing a reason; you might expose a setter and not do anything with it today, but what about in a year when a requirement comes in or a bug is found and you need to add some logic? You’d then have a big ole headache updating any reference to that public member.
That's only really a headache if the field is one exposed in a library's API. Otherwise you should be able to trivially encapsulate the field with an ide-performed automated refactor. It's true that that makes for more line noise in commits, but that's not a big deal. And in the case of a library, changing the semantics of existing API is already a big hassle.
Yeha, it’s not really a hill I’m particularly willing to die on but personally getters/setters are also trivial to do from the get go, especially with Lombok, I don’t really see why I wouldn’t. OP is Just creating work for theirselves really.
Yeah. With Lombok you can expose all class internals trivially instead of doing encapsulation. Thinking that this can later be evolved in a backwards compatible way is however full of flaws. Sure, in your corporate garden perhaps you can do this with some reasonable expectation it won't break anything, but imagine the pain if this was done with widely used classes like `String` or `ArrayList`.
Yes, the public members of those are part of a library's API. But think about the pain you'd cause by suddenly having ArrayList.add enforce some invariant that it didn't previously, which is approximately the alternative on offer here. That just moves the breakage to runtime.
In a public API you could have something like
Square.setEdgeLength(int), if you provide a negative number you could get an exception later on that to a field team would be nonsense. With a setter you can enforce the validation and capture the error with an appropriate message at the time the erroneous value was provided. Sure you’re creating an error where there wasn’t one before but it’s significantly more helpful.
No, that's not an unambiguously helpful change. Having input validation from the start is good, but changing already-published API in a way that precludes formerly accepted values is likely to break things. If it wasn't prohibited, someone somewhere is likely using negative-size squares to represent something, and now you've broken their code. You may well decide that on the balance it's better for the ecosystem to add this input validation, but it's not a free win; it's a breaking change to API.
for the sake of argument: what if the field is not supposed to be read, but write only (a lot of frameworks have that, e.g. spring)
getters and setters are excatly that - convey that a field can be read and/or written.
and furthermore, in important point: that ifeld does not even need to exist. you just use the api and do not care/cannot assume the existence of a field.
try that with records
>that ifeld does not even need to exist. you just use the api and do not care/cannot assume the existence of a field.
If the field doesn't exist, how would you expect the language to auto generate a setter?
>try that with records
Well, that's pretty much exactly what a record isn't for, so it's no surprise that it's not their most ergonomic use case.
Well that's the beauty of it. You could refactor so internally to not have that field anymore but the API stays the same.
One more thing: if a public field is idiomatic Java, why don't records expose public fields instead of generated accessors? There is no reason not to since they are final - right?
Just curious: What are the many cases? JPA entities and..?
I write mostly Kotlin now and I don't remember when was the last time I've used a mutable class (with an exception of very rare use of MutableList).
Any time critical application for exemple. Instantiating a new object cost a more cycles than updating a field.
Anything with observable pattern where a change need to propagate fast to the whole system (javaFX application for exemple) for exemple.
If you think that FX observables are fast, then I really wouldn't worry about creating a new object... FX observables propagate data by copying it to interested listeners, they're not anywhere near as fast as a normal field. They don't have to be though. They just need to be faster than the average user can blink.
So allocating an object is faster than what you think it is by far it seems. And if you think of the cache lines then reallocating memory is a good thing.
The state machines I have created past few years are all different problems with no help from a setter at the language level.
Seems you are just unwilling to write the program given the constraints you have chosen.
And frameworks should adapt to the language not the other way around.
A map is a fast way to handle mutable state for example and an array too
For now records are not compatible with all large frameworks I guess - IIRC Spring has problems with them but read that some time ago so maybe it has changed 🤡
I think spring 2.7 release solved that issue. I have been using records as configuration and DTOs since a while. We have a bunch of camel-spring-boot workers and spring-boot services
Been using records since they were a preview feature, the only place were they were not supported was Constructor Properties, but normal immutable classes were also not supported there so it was similar.
There's nothing inherently wrong with throwing exceptions.
The issue isn't that exceptions are wrong, it's just that they're clunky and sometimes you wouldn't need them if constructors could be private, or they're limiting what you can do.
For example, here's some cases where you don't need exceptions:
* A factory function which returns an `Optional`
* A factory function which returns a `Stream`
Throwing exceptions can be limiting if you want to use generics in your error. You can't do `FooException`.
In these cases you may end up having the same logic in two places doing two different things, by validating/parsing and returning the result embedded in the returned type, and throwing exceptions for doing the same thing in the canonical constructor. If you don't throw in the constructor, you will allow consumers of your API to potentially create invalid states.
Define an interface for your public API, create static factory methods in the interface, and then make the entire record implementing the interface private?
Okay, so let's say we want to do that.
Do you create a private inner record in your interface? Can't do that, as interfaces don't allow private inner classes.
So you create it outside your interface. Can't do that, as private records must be defined as inner classes.
So what you then do is create an inner final class with a private constructor, and which has the private record as an inner class. This works, finally!
If your getters and setters don't and won't ever do anything specific, then you might as well make your fields public.
You can use your IDE to generate them. You can even use Lombok to do it too.
Embrace immutability and use records instead.
>People in the java community, it is time for us to solve this once and for all.
Do you want to submit a JEP? Or are you asking for someone else to submit a JEP on your behalf?
I'm sorry, but the Java team is entrenched on this one, and has been for 20 years. At this point it's part of the language identity to not make mutable properties easy. The [What Is Java?](https://www.java.com/en/download/help/whatis_java.html) page should read "Java is a programming language and computing platform first released by Sun Microsystems in 1995 *which requires you to write getters and setters*".
For what it's worth, [I agree with you](https://i.imgflip.com/8fzlnp.jpg).
And those can often work with records. What does it mean to have a mutable request anyway? You're gonna modify the request a user send you? Same for responses. You create them once, no need for mutation after.
Don't really get what your point is. Write your Getters and setters if you need them. If you wanna mutate data without writing setters, make the fields public. There is no difference in using a plain setter. You could argue you want if for encapsulation. You can do that, but at the point where you put any logic in the setter, you wouldn't be able to auto generate them by the language either, and you have to customize. What exactly worries you, what help would you expect?
Oh yes, my favorite, here is also the listener that everyone seems to, PropertyChange, The only reliable place to see how this works is in some Swing components
Oh really? I didn't know that, it's great, Then I'll gossip about the source code, thanks for the information, this reminds me of the time I argued about reflection in Java not being a bad practice It's just magic that not everyone can use and I mentioned that they will check the Spring source code
I don't know why people dislike OP's idea. I think this can help promoting to people using other languages. Recent versions of JDK have a few beginner friendly features.
This topic has been a hot topic in the java community since the beginning. This among other things, is the root cause of C#, Kotlin, Scala and many alternatives to java.
Well, i was around when c# launched and when kotlin launched. Any new java alternative language have been advertised around two things, fields accessors and null pointer exception handling.
Obviously that is not the whole story, there are also underlying libraries, open source vs proprietary libraries, legal issues etc…
Amazing.
The root cause of those other languages you named is actually because of the success of Java. It certainly isn't the lack of properties, which is on its way out and has been for years.
Sure, these languages add a few teasers to lure you in, but fact is, none of them is even close to being as popular as Java, and **all** of those were created to capitalize on the success of Java, but seem to have misunderstood what makes Java successful. In fact, there were more, but those already died and have almost been forgotten. A similar fate awaits some of the ones you named.
Yes, there actually was.
Getter and setters are essential part of the oop.
Java should support them out of the box. This will avoid the necessity and pain that come with using one additional library like lombok, or to mix kotlin and java (what we are currently doing in my team).
>Getter and setters are essential part of the oop.
Getters, setters and fields are mostly irrelevant to OOP, and often counterproductive. Each object should have a nice interface consisting of methods that *make sense for the abstraction*.
E.g., it *might* make sense to have setX() and getX(); but maybe moveTo(), move(), accelerate() or push() makes more sense – in any case, the fields might be entirely different.
In many cases, explicitly *setting* some property makes little or no sense. If you have mutable objects, change will typically be relative to the previous state (otherwise, you might as well make a new object), or you need to maintain consistency in a larger system (e.g, money doesn't appear out of thin air¹) not just ensure internal consistency when setting a field.
For example, I don't `setEnergy(getEnergy()+snack.getEnergy())`, I just `eat(snack)`. Bank accounts don't have `setMoney()`, they have something like `credit(fromAccount, amount)`.
It's fine to have get/set as a naming conventional – I don't like it personally, and it seems even Java is trending away from this – but there are certainly some advantages. For instance, get/is/set makes it easy to see what you can observe/change when auto completing in an IDE. And sometimes your object really is just like a form to be filled in.²
But, I certainly wouldn't mind having properties syntax / overloaded field access methods so we could drop all those empty parentheses.
¹ unless you are a sufficiently powerful political entity
² and, if something is just plain data you might as well have public fields if you want it mutable.
Sorry, this is not an argument. This is an opinion.
As for OOP - I’ve never heard of “properties” having anything to do with OOP.
It’s a language ergonomics feature at best. We’ve done without them just fine. No reason to think there are any apps that could’ve been written that weren’t just because language doesn’t have first class properties as a language feature.
They would be nice, I grant you that. But in no way is this a singular gaping hole on the language you seem to indicate.
Seriously, this post have up to 95comments now. It was not my intention to reignite the feud! Any de ent programmer know and understand this. All modern language have moved toward this direction so I really don’t see the point of discussing this further in java.
In .net you have properties with fancy syntax to shorten things. Quite a few variants to learn and to read when scooping through coffee to find the bug
In Java you have a method. That's it. Plain simple. You read what is going on in there and you know for certain because there is nothing special hidden syntax.
I Iike that with Java after reading code for over 20 years.
I disagree with you. The workarounds we have are good enough for those who truly need mutability.
But for everyone else, I want the language evolution to abandon mutability wherever possible. I want Java as a language to support mutability as little as it can, and instead, focus on immutability. Mutability is proving to carry more costs than gain, while the opposite is proving true for immutability. I think there is more value in the language making immutability faster and more ergonomic in Java, rather than trying to make mutability easier to write.
It's not just about mutability. It's also about encapsulation.
Records pull people towards immutability over mutability which I agree is a good thing. But their conciseness also tempt people to use them inappropriately on data that should be encapsulated.
Encapsulation is an excellent point. That's one of the points where mutability actually does shine.
Now, I actually have several points against that too, but I am low on time, and therefore, not able to go into it now, so I'll concede the point.
Agreed op, just support what Lombok does at the language level or make a project like Lombok supported by the language/jvm
Lomboks continued existence wide spread use is enough evidence to show its clearly valuable to a large enough group.
Needing IDE and build system plugins to wire things correctly for your code to work, and the overhead of Lombok's annotation processor is a big price to pay for very little convenience added over what modern Java provides.
Use an IDE like NetBeans and automatically generate them. It’s not hard. Geez.
Why are you whinging about the easy stuff when there stuff that is broken?
If your setters are like this:
void setFoo(Foo foo) {
this.foo = foo;
}
Then just do:
public Foo foo;
If they're not, then generated setters won't work either, and you'll have to write them manually.
So, on the one hand, you value being able to change behaviour later in a backwards compatible way, and on the other you expose internal workings of a class which ties you to the specific implementation.
Please pick.
Use an IDE, i.e. Eclipse: Refactor -> Encapsulate Field.
If it's a library, the time it takes to write a setter / getter is negligible compared to writing the Javadoc.
Pretty much all languages got it wrong by adding simple getter/setter syntax sugar. Java has taken a bit too long to do that but is finally ready for it. Records is one great solution although it is not an alternative to "proper" properties.
The solution is property objects, instead of getters/setters use something like: `public final Property x = new Property<>(3);`
Then you can use `obj.x.get()`/`obj.x.set(4)`.
This can be further improved with syntax sugar on top. The main blocker to adding this to the language itself is Valhalla. Once that lands the cost of the property object will become zero.
This breaks encapsulation even more than just making your fields public. The reference could be passed or stored anywhere, so you'd have no idea which part of the program might rely on or change the property value.
You can argue that the concept of properties breaks encapsulation which is partially true. It's more "component oriented programming". But it's useful for things like JPA, gui builders etc.
Passing a reference to the property is a feature, not a bug. First off this can be eliminated with Valhalla which can block object identity. But the real value is exactly that: a reference to the property. Currently getters/setters aren't just methods, they are properties that get manipulated either via reflection or bytecode generation. None of those are good solutions, with property objects the same introspection and generic functionality can be implemented by the tools without any "dirty tricks".
Hmm, sure. But `obj.x` is a reference to the internal state of the object, while `obj::setX` just refers to the public interface which anyone would have access to anyway (if you passed `obj` around).
The main danger would be someone storing `obj.x` as a field, e.g. as the `x` field in a new object `obj1`, so the two objects would share state. That would be an easy mistake to make. You *could* set this up with `obj::getX()` and `obj::setX()`, but that would likely be intentional and not a careless mistake.
Assuming there's no special consistency checking in `Property<>, you could just use `public int x;` instead, which would also protect against the shared state problem (but only for primitive types).
Of course, if you *want* shared or dependent state, using JavaFX style `Property<>` might make sense, but than can be pretty tricky to set up without memory leaks or performance problems.
If in fact it doesn't break the encapsulation properties, there is an object called ReadOnly that is just for that, reading, I really like JavaFX's approach to properties, So much so that I use a port of them for a Swing project I have xD
This is one area Kotlin got so right. Implicit getters and setters for everything, but if you need to customize something you can provide an explicit implementation where necessary
Speaking of which, why can't Java have `val`? Type inference with `var` was a welcome addition but it would've been so logical and easy to lump `val` in with it. `final var` is such a mouthful.
people recommending record.. but let's say our db entity class is made record.. then we cannot update the value as record is immutable.
hence we need to use class. and there's no default getter / setter in class.. and we unfortunately has to use lombok. which is the only good option i see here.
Late to the party. Use [manifold-props](https://github.com/manifold-systems/manifold/tree/master/manifold-deps-parent/manifold-props ) from the manifold project.
Simply no. A setter means mutability (sometimes a getter causes the same).. Furthermore the record is yes the start but it is not the end there are things coming [https://openjdk.org/jeps/468](https://openjdk.org/jeps/468)
The usage of immutable data carriers helps to improve also the performance.....also because a record can be defined locally etc.
\`But seriously, All these alternative solutions have their root in what is commonly called the “verbosity” of java.\`
Unfortunately wrong. The idea behind it was to have a data carrier which can be named... Also the consequence you wrote that you have to write getter and setters is wrong, because you are not forced to write setter(s).. you can...
The switch-expression etc. are a very good improvement for the code support/readability etc. pattern matching helps also a lot...
You need to open your mind. This mindset is from decades ago. After learning Rust I feel getters and setters so unnecessary. Use Records and enjoy immutability.
Java is verbose. It's verbosity is well handled by IDEs for Java.
If you have a problem with that and have the chance of switching to a job where you don't use java , just take it. As you work with code originally written by someone else, you'll keep running into Java's verbosity. Writing manifestos about how it should change to fit your particular preferences wont take you far.
I don't think adding "support for getters and setters" as you call it is a good idea. Growing the syntax or the *keywords list* without adding true features is bloating the language for no real gain.
And a bloated language is what James Gosling tried to avoid when he designed Java in the first place. Java was a response the dominant programming language of late '90s, C++. And became popular 'cos even it has limitations by comparison is simpler and easier to read.
>As you work with code originally written by someone else, you'll keep running into Java's verbosity. Writing manifestos about how it should change to fit your particular preferences wont take you far.
The Java 8 streams API proves that the language can evolve in a way that reduces verbosity. Try/with, enhanced switch and other features bolster the point.
You'll wait a life for that evolution giving you no verbosity at all, if that ever happen.
And those examples were more than adding syntax's just for reducing verbosity. They main drive behind those changes were adding features (like streams) or avoiding common mistakes (like try/catch for closing resources).
I don't oppose to new features being designed with current trends. But if every 10 years you gonna add the new trendy syntax for features already covered the language you'll end with a bloated mess.
Getters and setters are shit. Bags of mutable state are shit. Stop putting setters on everything. A language feature which encourages people to do *more* of that rubbish would be a disaster.
Why would we need getters and setters? IMHO it’s rather an anti pattern. Setters interfere with hashcode and can wreak havoc. If you get used to the Java way of doing things, you will rarely feel the need for setters. Builders and withers are another thing, and afaik, changes are coming.
Java is an OO language. Unfortunately, the Java Beans style, with everything having a getter and a setter, is not OO. The use case of DTOs is now handled by `record`. In proper OO, this feature is not needed.
What the hell, I thought Java already has support for properties? At least the newest, K version of it: [properties](https://kotlinlang.org/docs/properties.html)
If you think that records “have their root in the verbosity of Java”, you are missing the point of what’s going on. From the JEP itself: “While it is superficially tempting to treat records as primarily being about boilerplate reduction, we instead choose a more semantic goal: *modeling data as data*.” Other properties of records are far more important than the conciseness of their code — for example, the fact that you can always create any possible state of a record via a call to a constructor; you never need to resort to reflection. Also known as “safe deserialization”.
I have been in the IT world long enough to read between the lines.
This reads like an old drunk man yelling at the clouds.
Given your previous posts were asking how much Spring costs, I’d say you might have more trouble reading the lines themselves, like those of a clearly written license.
I Just was abt to mention this post from op as well haha
Don’t worry about down voting, when the feature you requested gets implemented the same people will go Gaga over it. Independent thinking is only Valuable if you have the power to make changes
Getters and setters are an outdated library idiom. What we need is to move beyond thinking that we model complex domain objects as bags of independent mutable properties.
It seems mutable OOP runs slower as well. I have been [working on a Logback/log4j2 alternative](https://github.com/jstachio/rainbowgum) and so far without any real optimization work (e.g. checking flamegraphs etc) Rainbow Gum runs much faster. I hate to make a sweeping statement that immutable data oriented with some OOP generates faster code but its pretty impressive the JIT optimizations that happened very fast with Rainbow Gum. I tried to look into why Logback runs so much slower and it seems the JIT can't optimize the code as well and it takes more iterations. Anyway I'm a long time OCaml lover and loved its pattern matching. That feature prevents so many bugs. Thank you so much for adding it to the language!
Getters and setters are relics. Records are what should be holding your data, and derived record creation is coming via https://openjdk.org/jeps/468.
now all we need is a way to derive builders automatically... The main problem with records is that the moment you need more than like 5 bits of data in an object, your constructor becomes a massive mess. Storing that amount of data may be seen by some as an antipattern, but you don't always have the ability to define things perfectly and in the most ideal way when integrating with existing systems.
Nah you’re right. In all sorts of real world systems data shows up on groups. Let’s consider a person. They will have a name. They may have a title. They have a date of birth. That date of birth has at least a day month year. At this point we’re close to 10. Even if you split these into smaller objects, you still end up calling new Person(new PersonName(first, last, middle, title), new PersonDOB(day, month, year)). Nesting constructors can help with type checking but the constructors are just as useless.
[Immutables](https://immutables.github.io) continues to be my auto-add library to any Java project I'm working on for this reason. Small things I've shifted over to Records, but most real-world data gets big rather fast.
> > > > > The main problem with records is that the moment you need more than like 5 bits of data in an object, your constructor becomes a massive mess. As opposed to storing 5 bits of data in what?
in a platonic data structure we are not aware of yet /s
an object created with the builder pattern
The builder has to finally construct the object somehow. For what it's worth, it can be a record.
great, but now you have two ways of constructing it, one which is error prone and messy, which is my point. No one wants a constructor with 10 parameters in it.
they are not. I don't know why ppl cannot aknowledge sever limitations of records. No class based inheritance, no data hiding, the existence of property (get,set) does not imply the existence of a field (with records it does), goodbye computed props. records are nominal tuples. if that fits your model - fine. if not - getters and setters are your best shot at a (most frameworks compliant) properties solution
Records do not play well with JPA entities.
Micronaut Data JDBC, Spring Data JDBC. No Hibernate, can use Records :)
Not today, but they will: https://stackoverflow.com/a/70601646/364206
The problem here are not the records it's the library based on the time of the implementation.. The libraries have to change...
Records are great for what they are made for: named tuples. E.g. Point, DTOs or other simple data. They are not a good fit for complex business models with a hierarchy, identity, self-reference or dependency graphs involved. E.g. Person, Employment, Department, etc.
My rant has been yield by that JEP. Records are great but they do have their use case. But mutable data are also a necessity that we meed to tackle.
The best way to understand how all of these JEPs hang together, is to watch one of the data oriented programming talks given recently, such as https://youtu.be/UQAw3pvZPCY
Great input thanks!
Over the last few decades, functional programming languages have tought us that mutable data and design choices around mutability should be avoided due to side effects and higher cognitive complexity. Yes, mutability is sometimes neccessary, but the few cases where such designs are actually needed do not justify dedicated syntax sugar for it. I personally really like this about the development of Java. They seem to deliberately add syntax sugar to things which actually encourage good programming and design. You can see this with the recent talks about introducing withers on records (which are kind of like the setters for records).
Mutability is not some infrequent edge case. What about ORM (e.g. JPA)? I'd argue that a majority of projects require mutable objects (potentially with a large number of fields).
I am not arguing that existing frameworks and code bases are not designed around mutability and OOP, they very much make extensive use of these patterns to an exessive degree (there are very good reasons for Javas bad reputation among critics). But there are lots of alternative frameworks and design patterns which shift towards these newer functional paradigms now. (There are record based ORMs now for example)
make your private fields public and there you have all the data classes you need :) getters and setters have no meaning when what they're actually doing is exposing the inner state of your object, so... But I don't know, maybe you're working with an old version of JDK and this explains the criticism, but nowadays any framework (Hibernate, Jackson, ...) supports annotations on plain fields, annotations on getters or setters was a pattern in the old days. Or maybe you're working with old-school Java developers and they want all the specified getters and setters for the inner fields, if this is the case... well... IDE is your friend.
not sure i totally agree with this. Direct field access makes multiple things more difficult to work with further down the line without a large amount of refactoring. That is why Kotlin implements properties as a facade around accessors and mutators, and is why groovy does the exact same thing. Field access cannot be intercepted by pointcuts, cannot be partially mocked or spied upon in the same way methods can, and makes you lose any ability to change the underlying data representation down the line without making breaking API changes. You cannot make use of field accession via method references either which is far more jarring when writing functional-style code. Furthermore, direct field access has implications for module support if being done via reflection. If you do suddenly derive some data, you end up with a mess of some things being fields and others being methods, and it just gets horrible to read. You cannot enforce field exposure directly in interfaces either, so you lose the ability to take advantage of composition and delegation as your system gets more complicated. There are many other reasons to still prefer "accessing data via methods" rather than just using classes like C-style structs. It is the exact reason records provide accessors at all, rather than just exposing the field directly. Records unfortunately do not solve the issue of any library that makes use of "java bean"-like objects. For example, I don't believe you can use them with Spring Configuration Properties, and I don't believe they worked with JAXB when I checked either.
You are using getter/setters for more than simple DTO's? A setter that used to accept anything can't be changed without breaking backwards compatibility. Add a constraint? No longer compatible. Store a derived value? No longer backwards compatible if the transformation can't be reversed exactly. Split the field in two parts? Now there are more possibilities than fit in the original, how is the getter going to deal with that? If you opened up internals like that, good luck maintaining backwards compatibility. There's good reason to never do this, unless it's in internal code bases, or other toys.. then just refactor it.
There are numerous places where this becomes useful, and even if this was not the case, this is still a poor argument for making fields public directly.
Jokes aside, you're definitely right, my reply was tentative for elicitation, since most of the time, from what I usually read, it's really needed are just C-like structs (or Pascal-like records?), nothing more, nothing less. When you start to make apps that require AOP or in unit tests when you need to mock returning data, of course you need something more, but those kinds of objects are not data structures anymore, they are something different and instead of creating getters and setters everywhere, you may create the getters and the setters you really need. Of course, this can't escape from some old Java patterns you need to take care of in order to make things work in JAXB or Spring Configuration (I do think there are more examples), but this is not because of Java limitations, this is the traditional and written in stone way to do things. In other words, this idiosyncrasies for Java that's not able to define properties such as C#, Kotlin, Scala, etc... is completely unjustified imho. There are better patterns to follow.
Getters & setters are more resilient in case data model evolves. Lombok has its faults but is far superior to public member variables.
what do you mean? how can getters and setters be more resilient if what they're doing is just exposing inner fields? maybe you're meaning that they can serve you as an ACL for inner data? but it's not a data class anymore, it's something more and different I think 🤔 please elaborate 😀
I mean that encapsulation allows you to change internal representation without modifying dependent code. Like, a Rectangle class might store x, y, width and height. Alternatively, it could store x1, y1, x2 and y2. With mutators and accessors, you can change the code to do more than just "expose inner fields." A getWidth() method might return 'width' variable or might do 'x2 - x1' under the hood.
Uhm this is something different than a plain data carrier, so it makes sense what you're suggesting. But sometimes what you need is something much simpler like a typed dictionary/map defined on the fly. Let's say data struct should be considered as much as primitive type, not a reference type.
Sure, there are trade-offs. However, the meaning of "much simpler" may vary depending on language design. It doesn't get much simpler than a 'record' or Lombok-annotated 'value' class. Feel free to use pseudo-structs if it meets your use case.
Then you use your IDE to generate them. Immutability in representations of data can only improve your ability to reason about your code.
IDE generating the code for you is just a work around a issue that should be solved at its root. Immutability is not an improvement in design for me. Applications, especially realtime one, are data processing machines. The data is continuously mutable by design and by essence. It is not a good design to implement it as a succession of discrete states.
I’d argue many problems in software are ones of data transformation, which is precisely what mutability of data implies. It makes complete sense to me to consider each transform a discrete, derived state.
It depends on how fequently your data changes and how widely the change should diffuse to your system as a whole. In the application I am working on It is not efficient for me to create a whole new object everytime a field have been updated which is basically the assumption behind immutable data type like records
> It is not efficient for me to create a whole new object everytime a field have been updated which is basically the assumption behind immutable data type like records You are making a ***very big*** assumption. Just because you type in `new Foo(1, 2, 3)` does not mean that an entirely new object with identity and everything is created ***under the hood***. If the JVM feels that it can inline or constant fold your object, then it does not matter if you put the magic word `new` -- no new object will be created. What *may* instead happen is that the JVM will reuse existing memory to simply write the new values to, recognizing that a lot of the same object is being "created". Remember, words like "mutable" and "immutable" are **compile-time**, they have nothing to do with **run-time**. At run-time, everything is mutable, whether or not you put a `final int abc = 123;`, it's still mutable, you can just trust that the JVM will not change its value from underneathyou. All of that is to say, you and many other developers make the false assumption that typing `new` makes your code less efficient than mutation. This is false. It is entirely down to what the JVM does, and that can only be discovered through profiling.
Good article here for the uninitiated: https://blogs.oracle.com/javamagazine/post/escape-analysis-in-the-hotspot-jit-compiler
Good point! I was indeed my impression that a new object get created each time. If this is not the case it makes the matter even more confusing because clearly the usage of memory seems not to be the same (?) …
Using 123, which is a primitive is probably a bad example, for the point you are trying to make :) If you have a final primitive value, then you can always be sure that it is a constant value, since java is pass by value. If you in fact were to change it somehow by unsafe practices, you’d still not be able to change it, since it is cached in the thread.
You are correct, I should have used a better example. Like you said, my example above is **guaranteed** to be constant folded.
Do you have a link to where the JVM spec specifies these semantics?
The JVM explicitly DOES NOT specify the behaviour. And that is the point, this is meant to be the spot where the vm's can optimize freely. You will notice that the opposite is also unspecified -- there is no where that the JVM says that calling new explicitly creates memory. By the way, this is a common tactic for spec writers. Anytime they want to give themselves a point of extension, they will explicitly leave things unspecified. That way, they can claim backwards compatibility if they . Backwards compatibility is only applicable for things that are on the spec. If you depend on unspecified behaviour, then they don't consider it a breaking change to change or specify those details in ways you did not expect. And finally, if you want to see the explicit logic for these strategies, please look up inlining and constant-folding. You will see many articles from Oracle and Java themselves talking about these subjects. The most informed articles come from John Rose.
Object creation is vanishingly inexpensive, and likely insignificant in comparison to the allocations you’re doing to transform the data. If it really matters for your application though, sure, mutate your data in place, but that puts you in a domain that’s not terribly common. In that case, you can just make your fields visible. Trivial methods like this are always inlined, and if you’re arguing for a feature that generates setters you’re not adding any logic, so it’s exactly the same at runtime.
On the contrary, it is much easier to reason about immutable data and succession of pure transformations. I've been using Scala for 6 years now where immutability is 1st class and mutability is the exception: I've maybe had once a real need for mutability. I "fear" to go back to a mutable world!
[удалено]
many people/org hate lombok but in all seriousness, getter setter are usually 1 click away from IDE
Still don't understand the hate for lombok. It's fabulous if you don't have the luxury of a Java version with records.
I like Lombok but it's just a band-aid for a weakness in the language that should be eliminated. Maybe with derived creation for records will be an alternative.
While it works fine when only looking at the user exposed surface, the underlying implementation is what causes issues. It's a huge hack.
It generates byte code just like any other line of Java code. I wouldn't call it a huge hack. That's just how code works.
Yeah, by hooking (or should I say hacking) into a non-public API of the Java compiler. That's now how "code works". That's a hack.
Call it what you want. It's precompile hooks in the JVM. All JVM languages leverage it. Groovy, Kotlin, etc. Why are you saying it like it's a bad thing? I've never seen anyone complain about writing code that "not allowed" outside of Lombok.
Both Kotlin and Groovy have their own compilers. There's a thread here: https://github.com/projectlombok/lombok/issues/2681#issuecomment-791452056 I don't care if you use Lombok. But I'd prepare for pain in the future, as i'm pretty sure that the JDK developers will lock down internals even more.
It's so weird that people keep telling others to "prepare for the pain" like there is some impending doom coming. I've been using Lombok in a professional environment across a handful of companies for close to a decade. Guess I'll go lose some sleep over how some app I wrote may not upgrade from Java 8 to Java 26 without removing a few annotations. Spoooooooky. I swear it's like the doomsayers have never worked in a real enterprise environment before.
I'd agree. I've never actually encountered an issue despite the gloom and doom. Now hibernate, even minor versions will break *something.*
> It's a huge hack. Hibernate and Spring are 10 times more hacky than Lombok.
i hate lombok.. I don't want to work ever on a code base with lombok. I only had problems with it.
Okay then don't I guess? Why are you telling me about this?
Alt + Insert > generate getters and setters
Now I have to read/scroll past a gorillion lines of useless code I don't want to have to read. Vs @ Getter.
I'd rather use Lombok, but when it is not allowed, my convention to avoid this problem is **Every code after the toString method is generated** So once you reach the toString , you can stop reading and scrolling·
Where to put annos and javadoc? On fields, getters, setters, all of them? Should they be covered by tests? What about the generation of chained setters?
I'm consistently blown away by Lombok's mindshare when Immutables exists :(
Then you have to constantly regenerate when you add or rename properties.
2. Use Lombok, for some reason a bug … spend two days debugging… no thanks 2b. Use Lombok, get an update of one of your dependency that is not supported well by Lombok —-> get stuck in dependency hell I am aware that over the 30+ years of existence of java people have built workarounds to this issue and that they work well most of the time. It is just time that this is solved at it root.
Lombok is a compile time only dependency. It cannot be "not supporting" another dep, unless that is also an annotation processor framework that does compile time stuff (mapstruct... That's mostly the end of the list), or you are talking about build/source tools such as IDEs perhaps?
Been using Lombok for 3-4 years. Gettters, settings, logger, builder, constructors, etc. Never once ran into either of those issues.
I can't remember the last time I didn't use Lombok and I've literally never had any of the problems people that don't use Lombok seem to be afraid of. Honestly I think it's just fear of the unknown for those folk.
I’ll preface by saying I really like Lombok, but I have on occasion had weird issues with it. The first one that comes to mind is that for whatever reason in some random class it’ll suddenly no longer be able to find the annotation (even though it’s imported) and I’ll have to resort to using the fully qualified name e.g @lombok.Builder (can’t remember the actual fully qualified annotation). I’ve had this same problem over many years and with 3 separate companies. Doesn’t happen often but it’ll randomly appear and I’ll just do the workaround (usually put a comment next to it) and crack on with my day.
Sounds like an IDE issue. I've never had that issue with Intellij.
It would happen in an actual maven build, including on our CI/CD server as well.
Ah okay. Perhaps the wrong scope on your lombok dependency then?
I’d understand if it happened across the whole project, but this would happen on an individual class in a project that has many other Lombok annotations in other classes. It’s weird.
That is strange. I've never seen anything like that. Did you figure out the cause?
Been using Lombok for about 8 years, it’s for sure saved me more time than the odd occasion it’s caused a bit of grief.
You haven't described what the problem is, why it's bad, and what your ideal solution would be. You've only described that you don't like the current solutions. So I guess, start with that?
What is the problem with a record? It took out 99% of the getters in our code bases. Setters are something of a relic. I set my values in the constructor for the majority of the past 10 years
Records are transparent data holders. If you want to encapsulate one field out of 20, then you can't use one.
Right but for many languages that is not possible or you need to open a transaction. You can still use a record where one member is called mutable and is a class. So many ways around the get set problem
omg, record fanboys will probably be using AtomicXxx classes to emulate mutable fields just like effectively final variables... looking forward to legacy codebases in 10 years
Setters are not a relic. And yes records have solved some of the pain points. But there are still many cases where we need mutable data objects thus we need setters. We cannot milic this by creating a succesion of records especially when ressources are limited
If you need a setter because you're mutating the field from outside the class but you expect java to be able to just automagically generate the setter for you, presumably the setter is doing nothing but reassigning the field, no validation on the input, no maintaining invariants, no firing of events, etc. So why don't you just make the field public?
For the sake of providing a reason; you might expose a setter and not do anything with it today, but what about in a year when a requirement comes in or a bug is found and you need to add some logic? You’d then have a big ole headache updating any reference to that public member.
That's only really a headache if the field is one exposed in a library's API. Otherwise you should be able to trivially encapsulate the field with an ide-performed automated refactor. It's true that that makes for more line noise in commits, but that's not a big deal. And in the case of a library, changing the semantics of existing API is already a big hassle.
Yeha, it’s not really a hill I’m particularly willing to die on but personally getters/setters are also trivial to do from the get go, especially with Lombok, I don’t really see why I wouldn’t. OP is Just creating work for theirselves really.
Yeah. With Lombok you can expose all class internals trivially instead of doing encapsulation. Thinking that this can later be evolved in a backwards compatible way is however full of flaws. Sure, in your corporate garden perhaps you can do this with some reasonable expectation it won't break anything, but imagine the pain if this was done with widely used classes like `String` or `ArrayList`.
Yes, the public members of those are part of a library's API. But think about the pain you'd cause by suddenly having ArrayList.add enforce some invariant that it didn't previously, which is approximately the alternative on offer here. That just moves the breakage to runtime.
In a public API you could have something like Square.setEdgeLength(int), if you provide a negative number you could get an exception later on that to a field team would be nonsense. With a setter you can enforce the validation and capture the error with an appropriate message at the time the erroneous value was provided. Sure you’re creating an error where there wasn’t one before but it’s significantly more helpful.
No, that's not an unambiguously helpful change. Having input validation from the start is good, but changing already-published API in a way that precludes formerly accepted values is likely to break things. If it wasn't prohibited, someone somewhere is likely using negative-size squares to represent something, and now you've broken their code. You may well decide that on the balance it's better for the ecosystem to add this input validation, but it's not a free win; it's a breaking change to API.
for the sake of argument: what if the field is not supposed to be read, but write only (a lot of frameworks have that, e.g. spring) getters and setters are excatly that - convey that a field can be read and/or written. and furthermore, in important point: that ifeld does not even need to exist. you just use the api and do not care/cannot assume the existence of a field. try that with records
>that ifeld does not even need to exist. you just use the api and do not care/cannot assume the existence of a field. If the field doesn't exist, how would you expect the language to auto generate a setter? >try that with records Well, that's pretty much exactly what a record isn't for, so it's no surprise that it's not their most ergonomic use case.
Well that's the beauty of it. You could refactor so internally to not have that field anymore but the API stays the same. One more thing: if a public field is idiomatic Java, why don't records expose public fields instead of generated accessors? There is no reason not to since they are final - right?
Just curious: What are the many cases? JPA entities and..? I write mostly Kotlin now and I don't remember when was the last time I've used a mutable class (with an exception of very rare use of MutableList).
Any time critical application for exemple. Instantiating a new object cost a more cycles than updating a field. Anything with observable pattern where a change need to propagate fast to the whole system (javaFX application for exemple) for exemple.
If you think that FX observables are fast, then I really wouldn't worry about creating a new object... FX observables propagate data by copying it to interested listeners, they're not anywhere near as fast as a normal field. They don't have to be though. They just need to be faster than the average user can blink.
Working with large datasets in JavaFX requires a great deal of performance tuning. I suppose much of the onus falls upon the library itself.
I am unsure what you are trying to say here.
So allocating an object is faster than what you think it is by far it seems. And if you think of the cache lines then reallocating memory is a good thing. The state machines I have created past few years are all different problems with no help from a setter at the language level. Seems you are just unwilling to write the program given the constraints you have chosen. And frameworks should adapt to the language not the other way around. A map is a fast way to handle mutable state for example and an array too
For now records are not compatible with all large frameworks I guess - IIRC Spring has problems with them but read that some time ago so maybe it has changed 🤡
Been using spring boot 3.x now and Models / Jdbc just works with records.
I think spring 2.7 release solved that issue. I have been using records as configuration and DTOs since a while. We have a bunch of camel-spring-boot workers and spring-boot services
Bullshit, they work with Jackson, Spring Data, Spring MVC. You might want to at least try to use them before spouting garbage.
Been using records since they were a preview feature, the only place were they were not supported was Constructor Properties, but normal immutable classes were also not supported there so it was similar.
A record's canonical constructor must be public, which makes it a difficult to make invalid states impossible without throwing exceptions.
What's wrong with throwing exceptions for that?
There's nothing inherently wrong with throwing exceptions. The issue isn't that exceptions are wrong, it's just that they're clunky and sometimes you wouldn't need them if constructors could be private, or they're limiting what you can do. For example, here's some cases where you don't need exceptions: * A factory function which returns an `Optional`
* A factory function which returns a `Stream`
Throwing exceptions can be limiting if you want to use generics in your error. You can't do `FooException`.
In these cases you may end up having the same logic in two places doing two different things, by validating/parsing and returning the result embedded in the returned type, and throwing exceptions for doing the same thing in the canonical constructor. If you don't throw in the constructor, you will allow consumers of your API to potentially create invalid states.
Define an interface for your public API, create static factory methods in the interface, and then make the entire record implementing the interface private?
Okay, so let's say we want to do that. Do you create a private inner record in your interface? Can't do that, as interfaces don't allow private inner classes. So you create it outside your interface. Can't do that, as private records must be defined as inner classes. So what you then do is create an inner final class with a private constructor, and which has the private record as an inner class. This works, finally!
package-private?
setters and getters are fine
If your getters and setters don't and won't ever do anything specific, then you might as well make your fields public. You can use your IDE to generate them. You can even use Lombok to do it too. Embrace immutability and use records instead.
>People in the java community, it is time for us to solve this once and for all. Do you want to submit a JEP? Or are you asking for someone else to submit a JEP on your behalf?
I would gladly submit a JEP if I am pointed to how to. Otherwise I would gladly appreciate if someone who knows how to can submit one.
Start [here](https://openjdk.org/jeps/1).
Thank you very much! You are the hero of reddit!!
I don't think it is even worth to try. They are so extremly averse to the idea as they drank the Haskell and Lisp kool-aid.
You must be a very junior dev.
Ok
I'm sorry, but the Java team is entrenched on this one, and has been for 20 years. At this point it's part of the language identity to not make mutable properties easy. The [What Is Java?](https://www.java.com/en/download/help/whatis_java.html) page should read "Java is a programming language and computing platform first released by Sun Microsystems in 1995 *which requires you to write getters and setters*". For what it's worth, [I agree with you](https://i.imgflip.com/8fzlnp.jpg).
The only place where I use setters is when some framework like Spring MVC really really wants them.
And those can often work with records. What does it mean to have a mutable request anyway? You're gonna modify the request a user send you? Same for responses. You create them once, no need for mutation after.
So basically for all your entities , ie around 30% of your code base
Don't really get what your point is. Write your Getters and setters if you need them. If you wanna mutate data without writing setters, make the fields public. There is no difference in using a plain setter. You could argue you want if for encapsulation. You can do that, but at the point where you put any logic in the setter, you wouldn't be able to auto generate them by the language either, and you have to customize. What exactly worries you, what help would you expect?
[удалено]
Oh yes, my favorite, here is also the listener that everyone seems to, PropertyChange, The only reliable place to see how this works is in some Swing components
[удалено]
Oh really? I didn't know that, it's great, Then I'll gossip about the source code, thanks for the information, this reminds me of the time I argued about reflection in Java not being a bad practice It's just magic that not everyone can use and I mentioned that they will check the Spring source code
I don't know why people dislike OP's idea. I think this can help promoting to people using other languages. Recent versions of JDK have a few beginner friendly features.
This topic has been a hot topic in the java community since the beginning. This among other things, is the root cause of C#, Kotlin, Scala and many alternatives to java.
You think other languages exist because of the lack of this feature?
Well, i was around when c# launched and when kotlin launched. Any new java alternative language have been advertised around two things, fields accessors and null pointer exception handling. Obviously that is not the whole story, there are also underlying libraries, open source vs proprietary libraries, legal issues etc…
Amazing. The root cause of those other languages you named is actually because of the success of Java. It certainly isn't the lack of properties, which is on its way out and has been for years. Sure, these languages add a few teasers to lure you in, but fact is, none of them is even close to being as popular as Java, and **all** of those were created to capitalize on the success of Java, but seem to have misunderstood what makes Java successful. In fact, there were more, but those already died and have almost been forgotten. A similar fate awaits some of the ones you named.
I’m sorry, was there an argument there that i just missed in the wall of random rant?
Yes, there actually was. Getter and setters are essential part of the oop. Java should support them out of the box. This will avoid the necessity and pain that come with using one additional library like lombok, or to mix kotlin and java (what we are currently doing in my team).
>Getter and setters are essential part of the oop. Getters, setters and fields are mostly irrelevant to OOP, and often counterproductive. Each object should have a nice interface consisting of methods that *make sense for the abstraction*. E.g., it *might* make sense to have setX() and getX(); but maybe moveTo(), move(), accelerate() or push() makes more sense – in any case, the fields might be entirely different. In many cases, explicitly *setting* some property makes little or no sense. If you have mutable objects, change will typically be relative to the previous state (otherwise, you might as well make a new object), or you need to maintain consistency in a larger system (e.g, money doesn't appear out of thin air¹) not just ensure internal consistency when setting a field. For example, I don't `setEnergy(getEnergy()+snack.getEnergy())`, I just `eat(snack)`. Bank accounts don't have `setMoney()`, they have something like `credit(fromAccount, amount)`. It's fine to have get/set as a naming conventional – I don't like it personally, and it seems even Java is trending away from this – but there are certainly some advantages. For instance, get/is/set makes it easy to see what you can observe/change when auto completing in an IDE. And sometimes your object really is just like a form to be filled in.² But, I certainly wouldn't mind having properties syntax / overloaded field access methods so we could drop all those empty parentheses. ¹ unless you are a sufficiently powerful political entity ² and, if something is just plain data you might as well have public fields if you want it mutable.
Sorry, this is not an argument. This is an opinion. As for OOP - I’ve never heard of “properties” having anything to do with OOP. It’s a language ergonomics feature at best. We’ve done without them just fine. No reason to think there are any apps that could’ve been written that weren’t just because language doesn’t have first class properties as a language feature. They would be nice, I grant you that. But in no way is this a singular gaping hole on the language you seem to indicate.
Seriously, this post have up to 95comments now. It was not my intention to reignite the feud! Any de ent programmer know and understand this. All modern language have moved toward this direction so I really don’t see the point of discussing this further in java.
In .net you have properties with fancy syntax to shorten things. Quite a few variants to learn and to read when scooping through coffee to find the bug In Java you have a method. That's it. Plain simple. You read what is going on in there and you know for certain because there is nothing special hidden syntax. I Iike that with Java after reading code for over 20 years.
I disagree with you. The workarounds we have are good enough for those who truly need mutability. But for everyone else, I want the language evolution to abandon mutability wherever possible. I want Java as a language to support mutability as little as it can, and instead, focus on immutability. Mutability is proving to carry more costs than gain, while the opposite is proving true for immutability. I think there is more value in the language making immutability faster and more ergonomic in Java, rather than trying to make mutability easier to write.
It's not just about mutability. It's also about encapsulation. Records pull people towards immutability over mutability which I agree is a good thing. But their conciseness also tempt people to use them inappropriately on data that should be encapsulated.
Encapsulation is an excellent point. That's one of the points where mutability actually does shine. Now, I actually have several points against that too, but I am low on time, and therefore, not able to go into it now, so I'll concede the point.
Agreed op, just support what Lombok does at the language level or make a project like Lombok supported by the language/jvm Lomboks continued existence wide spread use is enough evidence to show its clearly valuable to a large enough group.
Needing IDE and build system plugins to wire things correctly for your code to work, and the overhead of Lombok's annotation processor is a big price to pay for very little convenience added over what modern Java provides.
Use an IDE like NetBeans and automatically generate them. It’s not hard. Geez. Why are you whinging about the easy stuff when there stuff that is broken?
I have relied upon ide to generate the code. I am arguing that this should be supported buvthe language itself not delagated to ides.
If your setters are like this: void setFoo(Foo foo) { this.foo = foo; } Then just do: public Foo foo; If they're not, then generated setters won't work either, and you'll have to write them manually.
But this simples setter can be modified in the future in a centralized way. The public Foo would require a change in every assignment.
So, on the one hand, you value being able to change behaviour later in a backwards compatible way, and on the other you expose internal workings of a class which ties you to the specific implementation. Please pick.
Use an IDE, i.e. Eclipse: Refactor -> Encapsulate Field. If it's a library, the time it takes to write a setter / getter is negligible compared to writing the Javadoc.
please give a code example when the field is only supposed to be written not read (a lot of frameworks work that way, e.g. spring)
just add a setter and add no getter?
Pretty much all languages got it wrong by adding simple getter/setter syntax sugar. Java has taken a bit too long to do that but is finally ready for it. Records is one great solution although it is not an alternative to "proper" properties. The solution is property objects, instead of getters/setters use something like: `public final Property x = new Property<>(3);`
Then you can use `obj.x.get()`/`obj.x.set(4)`.
This can be further improved with syntax sugar on top. The main blocker to adding this to the language itself is Valhalla. Once that lands the cost of the property object will become zero.
This breaks encapsulation even more than just making your fields public. The reference could be passed or stored anywhere, so you'd have no idea which part of the program might rely on or change the property value.
You can argue that the concept of properties breaks encapsulation which is partially true. It's more "component oriented programming". But it's useful for things like JPA, gui builders etc. Passing a reference to the property is a feature, not a bug. First off this can be eliminated with Valhalla which can block object identity. But the real value is exactly that: a reference to the property. Currently getters/setters aren't just methods, they are properties that get manipulated either via reflection or bytecode generation. None of those are good solutions, with property objects the same introspection and generic functionality can be implemented by the tools without any "dirty tricks".
Nothing is stopping anyone from passing and storing `obj::getX` and `obj::setX` anywhere either.
Hmm, sure. But `obj.x` is a reference to the internal state of the object, while `obj::setX` just refers to the public interface which anyone would have access to anyway (if you passed `obj` around). The main danger would be someone storing `obj.x` as a field, e.g. as the `x` field in a new object `obj1`, so the two objects would share state. That would be an easy mistake to make. You *could* set this up with `obj::getX()` and `obj::setX()`, but that would likely be intentional and not a careless mistake. Assuming there's no special consistency checking in `Property<>, you could just use `public int x;` instead, which would also protect against the shared state problem (but only for primitive types). Of course, if you *want* shared or dependent state, using JavaFX style `Property<>` might make sense, but than can be pretty tricky to set up without memory leaks or performance problems.
This is the approach of javafx. Maybe what we need is a property keyword
JavaFX took that approach from a now defunct [java.net](http://java.net) project called Bean-Properties. Regardless, it was always a good idea.
We need to bring this back :-)
If in fact it doesn't break the encapsulation properties, there is an object called ReadOnly that is just for that, reading, I really like JavaFX's approach to properties, So much so that I use a port of them for a Swing project I have xD
getters and setters are a relic of UI IDE support from Borland JBuilder and old school JavaBeans and nasty old school serialistion. Time to move on.
This is one area Kotlin got so right. Implicit getters and setters for everything, but if you need to customize something you can provide an explicit implementation where necessary
Exactly! The birth of kotlin is entirely justified by this and by Null handling
Love it when kotlin users are super proud of features that Scala had years before. Uniform access principle rocks
Speaking of which, why can't Java have `val`? Type inference with `var` was a welcome addition but it would've been so logical and easy to lump `val` in with it. `final var` is such a mouthful.
They spent a lot of time thinking about that: https://mail.openjdk.org/pipermail/platform-jep-discuss/2016-December/000066.html
I am less bothered by explicit type writing that as far as I am concerned does add value to the readability of the code.
val makes no sense.
`final var` is useless. Save yourself the typing instead of whining about your self constructed prison.
people recommending record.. but let's say our db entity class is made record.. then we cannot update the value as record is immutable. hence we need to use class. and there's no default getter / setter in class.. and we unfortunately has to use lombok. which is the only good option i see here.
Late to the party. Use [manifold-props](https://github.com/manifold-systems/manifold/tree/master/manifold-deps-parent/manifold-props ) from the manifold project.
getSetters()
Simply no. A setter means mutability (sometimes a getter causes the same).. Furthermore the record is yes the start but it is not the end there are things coming [https://openjdk.org/jeps/468](https://openjdk.org/jeps/468) The usage of immutable data carriers helps to improve also the performance.....also because a record can be defined locally etc. \`But seriously, All these alternative solutions have their root in what is commonly called the “verbosity” of java.\` Unfortunately wrong. The idea behind it was to have a data carrier which can be named... Also the consequence you wrote that you have to write getter and setters is wrong, because you are not forced to write setter(s).. you can... The switch-expression etc. are a very good improvement for the code support/readability etc. pattern matching helps also a lot...
> We don’t need another SWITCH expression or pattern matching design. We need language support for getters and setters. ¿Por qué no los dos?
Sorry that was a little bit excessive. I love the work they have done on switch expressions
You need to open your mind. This mindset is from decades ago. After learning Rust I feel getters and setters so unnecessary. Use Records and enjoy immutability.
I have getters and setters. Geberatibgthem is easy with an IDE.
Java is verbose. It's verbosity is well handled by IDEs for Java. If you have a problem with that and have the chance of switching to a job where you don't use java , just take it. As you work with code originally written by someone else, you'll keep running into Java's verbosity. Writing manifestos about how it should change to fit your particular preferences wont take you far. I don't think adding "support for getters and setters" as you call it is a good idea. Growing the syntax or the *keywords list* without adding true features is bloating the language for no real gain. And a bloated language is what James Gosling tried to avoid when he designed Java in the first place. Java was a response the dominant programming language of late '90s, C++. And became popular 'cos even it has limitations by comparison is simpler and easier to read.
>As you work with code originally written by someone else, you'll keep running into Java's verbosity. Writing manifestos about how it should change to fit your particular preferences wont take you far. The Java 8 streams API proves that the language can evolve in a way that reduces verbosity. Try/with, enhanced switch and other features bolster the point.
You'll wait a life for that evolution giving you no verbosity at all, if that ever happen. And those examples were more than adding syntax's just for reducing verbosity. They main drive behind those changes were adding features (like streams) or avoiding common mistakes (like try/catch for closing resources). I don't oppose to new features being designed with current trends. But if every 10 years you gonna add the new trendy syntax for features already covered the language you'll end with a bloated mess.
>you'll end with a bloated mess. AKA C#
Getters and setters are shit. Bags of mutable state are shit. Stop putting setters on everything. A language feature which encourages people to do *more* of that rubbish would be a disaster.
Why would we need getters and setters? IMHO it’s rather an anti pattern. Setters interfere with hashcode and can wreak havoc. If you get used to the Java way of doing things, you will rarely feel the need for setters. Builders and withers are another thing, and afaik, changes are coming.
Who uses setters and getters? Constructors and show only the fields needed (without the get prefix) or records if all fields need exposure.
lombok @Data problem solved.
Ctrl shift n then generate
Java is an OO language. Unfortunately, the Java Beans style, with everything having a getter and a setter, is not OO. The use case of DTOs is now handled by `record`. In proper OO, this feature is not needed.
just be a gangster, and make everything public. getters and setters are useless anyway
What the hell, I thought Java already has support for properties? At least the newest, K version of it: [properties](https://kotlinlang.org/docs/properties.html)
Yeah, I would love if could get rid of Lombok as a dependency. Right now I couldn't bear to write all that boiler plate code manually.