[HN Gopher] Why Java's Records Are Better* Than Lombok's Data an...
___________________________________________________________________
Why Java's Records Are Better* Than Lombok's Data and Kotlin's Data
Classes
Author : gher-shyu3i
Score : 154 points
Date : 2021-05-07 15:30 UTC (7 hours ago)
(HTM) web link (nipafx.dev)
(TXT) w3m dump (nipafx.dev)
| flerchin wrote:
| Project Lombok is my bae, but of course a language included API
| is better than an annotation processor.
| roflc0ptic wrote:
| I love that this website is trying new stuff with design. I also
| think the TOC is terrible and distracting.
| hota_mazi wrote:
| A long winded article that really never justifies its headline.
|
| Kotlin will soon be generating records in its back end, thereby
| gaining all the advantages that it's allegedly not getting today.
| andrewprock wrote:
| I'm never understood why code generation for getters and setters
| is so over-engineered. Heavy technologies for light work is
| almost always more trouble than it's worth.
| commandlinefan wrote:
| Getters are setters are pointless anyway - unless you're
| creating read-only properties by only providing getters,
| reflexively adding a getter and a setter for every property is
| exactly the same as just marking the property public. It's even
| worse in the case of immutable objects (like lists or maps),
| because the getter itself returns a reference to the mutable
| object. Getters and setters mentality came from a horrible
| misunderstanding of object oriented design principles and has
| been standardized into common practice.
| whatshisface wrote:
| In languages without property support, reflexively writing
| getters and setters is the only way to make it possible to go
| back later and add logic to getting and setting without
| changing the callsites. Is this a workaround for the combined
| shackles of mismanaged enterprise environments where changing
| callsites is impossible for some reason, and legacy language
| environments where you have to use Java for some reason? Yes,
| of course. But sometimes you need a workaround.
| slver wrote:
| The real question is why is the convention getFoo()
| setFoo(foo) and not foo() and foo(foo).
| swsieber wrote:
| It makes for easier searching in small code bases with
| stuff like grep instead of needing full language server /
| ide support.
| whatshisface wrote:
| Not all languages have overloading.
| slver wrote:
| I'm referring to Java.
| whatshisface wrote:
| I think the pattern was adopted from languages before
| Java which didn't have overloading.
| commandlinefan wrote:
| > go back later and add logic to getting and setting
|
| Which, realistically, you're virtually never going to do -
| at least not often enough to justify the boilerplate and
| _especially_ in the case of things like "records" which
| were probably auto-generated from a schema (with obligatory
| getters and setters) anyway. If you _did_ , you'd end up
| confusing all of your callers who probably wrote client
| code presuming that what they provided in the setter was
| going to be exactly what they get back in the getter.
| kmonsen wrote:
| Agree, for a lot of code you can be pretty sure it will
| not change. And you should be able to refactor your code
| base, if not there are larger issues.
|
| In general I subscribe to the at first make it as simple
| as possible, when you have two examples of it being too
| simple it is time to refactor.
|
| Of course when creating libraries it is different. In
| that case to protect users on the API surface and try to
| make that stable.
| t-writescode wrote:
| This is true, until you're writing a library that's
| pulled from a repository and used in several projects.
|
| If you can't guarantee you're not going to break someone
| else's code by changing:
|
| foo.x to foo.getX();
|
| then you should stick with properties. Now, for staying
| inside a single package, or a single compiled unit, then
| what you say is reasonable enough. I'd still prefer to
| write the getters and setters, though, especially in
| cases where it's free, like Kotlin.
| commandlinefan wrote:
| It would be better if the default were to not write
| setters _or_ getters for any properties by default, but
| instead to write a logical interface that properly
| encapsulates the properties. Unfortunately, that ship
| sailed a long time ago for Java.
| slver wrote:
| It actually happens a lot for me.
| slver wrote:
| get()/set() is the same as a public property, until you
| change the implementation, while maintaining interface
| compatibility, which is the point.
|
| In C# you'd have a point, they have parametric properties and
| readonly properties. So you'd favor just declaring public
| properties.
|
| But this is why context matters. And OO design principles
| also depend on this context.
| marcosdumay wrote:
| > until you change the implementation, while maintaining
| interface compatibility, which is the point
|
| How many times have you seen that done on the real world?
|
| And how many times have you seen that done, and it not
| creating a lot of bugs because of the behavior change
| without interface changes?
|
| Personally, I've seen the first one more than zero times.
| Not the second. Every single time somebody decided to mess
| with a setter or a getter, it broke the systems that
| depended on it, and things would have been much better if
| they simply changed the interface, so the problems would
| arrive at compile time.
| slver wrote:
| The behavior doesn't change. The implementation does.
| Those are orthogonal.
|
| And yes I see it every day. The collection interfaces in
| Java have countless swappable implementations. Those are
| basically getters and setters on a vector.
|
| I also had to change entity storage to columnar for a
| project. Did that. Never had to change a line of code
| outside the entities.
| RcouF1uZ4gsC wrote:
| Trying to read in Safari iOS but most of the article text seems
| to be missing.
| JackFr wrote:
| Completely unreadable on mobile for me.
| [deleted]
| bvanderveen wrote:
| Same.
| turtletontine wrote:
| Only half the code is rendering for me as well, Firefox iOS
| Reason077 wrote:
| Try using "Reader" mode. Tap the little icon at the left of the
| URL bar.
| random42_ wrote:
| You have to scroll the page reeeeeally slow to let the text
| load where it's supposed to.
| slver wrote:
| So this custom code font not only looks like Apple II, but it
| also works like Apple II. Amazing.
| ilrwbwrkhv wrote:
| That blog is hard to read for some reason.
| eweise wrote:
| Main problem I had with lombok is that it was too flexible,
| causing me to have to read all the annotations on a class. Kotlin
| data classes are implemented a single way so I don't need to grok
| them individually.
| cs-szazz wrote:
| I'm not sure what it's taking about for the "with" feature:
| https://nipafx.dev/java-record-semantics/#with-blocks
|
| In Kotlin data classes, it's already implemented (just called
| copy) https://kotlinlang.org/docs/data-classes.html#copying
| kelnos wrote:
| The annoying thing about Java here is that it doesn't have
| default argument values, and doesn't allow you to name your
| arguments in function calls.
|
| In Scala (I don't know Kotlin, but I assume it's similar) you
| could easily implement a copy() method yourself (and many
| people do if they need a case-class-like thing but can't use a
| case class) that behaves identically to the copy() method
| provided by a case class.
|
| But the semantics of that copy() method require default
| argument values, and the ability to call functions using named
| arguments. Java doesn't have either of those, so instead of
| adding those features (I can understand the former being
| controversial), I guess the plan is to add entirely new syntax
| just for records, which IMO is a huge shame.
|
| But it appears the "with" syntax is far from finalized, so it's
| possible they'll do something better.
| papercrane wrote:
| > I'm not sure what it's taking about for the "with" feature:
| ...
|
| The author is referencing possible future work that can build
| on the current records implementation, and the work Brian Goetz
| is doing with pattern matching and record deconstruction. Goetz
| has put together a draft that shows how these could be
| combined.
|
| https://github.com/openjdk/amber-docs/blob/master/eg-drafts/...
| stickfigure wrote:
| It's also implemented nicely, today, with Lombok:
| @Value @With public class Pair { int left;
| int right; } final Pair rightIs3 =
| somePair.withRight(3);
| giaour wrote:
| "With" doesn't exist in Java, but it was introduced in C# 9.0
| as part of the .NET implementation of records:
|
| https://devblogs.microsoft.com/dotnet/c-9-0-on-the-record/#w...
|
| I think the author is more saying that a "with" operator would
| fit into Java record semantics but might not be compatible with
| Lombok @Data classes or Kotlin data classes (though it looks
| from your link that Kotlin actually does have something very
| similar in the "copy" method).
| bcrosby95 wrote:
| It was included because changing data using records (copying it
| except changing the fields you need to change) is a shitty
| experience, so rather than showing the code you have to write,
| they showed you code you may or may not in the future be able
| to write.
| dlbucci wrote:
| Seems like an odd thing to mention. They are arguing that
| records are better than data classes, but part of their
| argument is "maybe, in the future, at some point, I don't
| know, it will be as easy to do this thing with records as it
| already is with data classes, we'll only need to add new
| syntax and a new keyword to the language".
| krzyk wrote:
| Who is they?
|
| You mean the article author? Yes, it was odd that he
| mentioned that, but besides that not a bad feature to have
| (but a bit wordy for my taste, I hope they'll change that).
| de_keyboard wrote:
| Great to see Records come to Java, although without the "with"
| feature they are pretty half-baked.
|
| I give it 5-10 years before we've tricked everyone into writing
| OCaml / F#!
| abledon wrote:
| IF you're not on Java 14 yet (70% of industry?[1])... this post
| shows two other alternatives for Lombok:
|
| https://medium.com/@vgonzalo/dont-use-lombok-672418daa819
|
| Autovalue & Immutables
|
| [1] https://snyk.io/wp-content/uploads/jvm_2020.pdf pg 5
| zoover2020 wrote:
| Unfortunately AWS Lambda doesn't support 14 yet :/
| jandrese wrote:
| Do you care about memory leaks on a Lambda? I don't think
| they can live long enough to even invoke the GC. I guess if
| you're going through a lot of data you could blow your memory
| budget and have it terminated?
| grishka wrote:
| Curious question -- why do people insist so much on fields being
| private and there being getters and setters, even when all that
| getters do is return the field and all that setters do is set it?
| What kind of problem does this arrangement solve? Why not just
| use public fields?
| jorblumesea wrote:
| getters and setters prevent other objects from modifying
| internal properties in unexpected ways. Having that
| encapsulation and abstraction is important for maintainable
| code.
|
| Also, getters and setters don't always modify individual
| values. Imagine a class where we have:
|
| private val firstName private val lastName
|
| fun returnFullName(): return firstName + lastName
| grishka wrote:
| > modifying internal properties in unexpected ways
|
| Except I'm talking about Java classes that store data. They
| don't do any operations on it, they don't have any internal
| state, they're more like C structs.
|
| > Also, getters and setters don't always modify individual
| values.
|
| Of course. But one doesn't contradict the other.
| brabel wrote:
| I think I can answer that... it's all to do with a grand view
| that the Java original designers had about what objects should
| look like, in what became known as Java Beans. There's a
| spec[1] and everything.
|
| They wanted to be able to write framework code that could
| introspect Java beans and expose them directly in a user
| interface, amongst other things, allowing users to modify them,
| create them, delete them and even compose them to create their
| own applications... they had even imagined there could be
| marketplaces where you could _buy_ Java beans to add to your
| program, or even to modify your other beans to give them extra
| power... getters and setters were part of that - they needed to
| know how to obtain and change the state of an Object, but how
| the Object internally handled such state changes were up to the
| Object itself (what we now call encapsulation)... this was
| similar to how Smalltalk worked and that was an inspiration for
| the Java beans specification... all this never really turned
| out the way they wanted, of course, but have a read of the Java
| beans spec to get a better idea of what they had in mind if you
| don't fully understand it yet.
|
| With time, people forgot completely about Java beans, but for
| whatever reason, getters and setters sticked around to this
| day. Many Java developers today think Java beans are just
| classes with a bunch of getters/setters and never probably
| heard of PropertyChangeListener, VetoableChangeListener and the
| other parts of the Java beans spec (some of it lives on in
| Swing).
|
| If you write Java today and just want to expose some data,
| yeah, just go with public fields if you can't use Java 16
| records yet... if you ever need to change how you internally
| store information, just refactor that to a setter if you really
| must (it will never happen).
|
| [1] https://www.oracle.com/java/technologies/javase/javabeans-
| sp...
| blacktriangle wrote:
| This protects you from changes to the internal representation
| of state in the future. Direct field access totally blows away
| encapsulation.
| grishka wrote:
| So, uh, do a usage search before changing stuff? You'll have
| to, anyway.
| erik_seaberg wrote:
| That works if your class is never used outside your own
| organization, but the API of published code needs to be
| changed more gracefully using semver.
| kaba0 wrote:
| Not necessarily agree with private fields, but that is not
| an option for library writers.
| lowbloodsugar wrote:
| Freedom to change.
| highwind wrote:
| Only argument I heard, not that I agree but, is future proofing
| by abstraction. What if a simple getter evolves into something
| more complex. Then You'd have to refactor all the places where
| it was using the fields.
|
| I personally never had to do this so I'm not sure if this is a
| real benefit.
| dragonwriter wrote:
| Depending on the language, getters and setters may not be
| source and/or binary compatible with fields from the client
| side, so if you might ever need to refactor to a nontrivial
| getter or setter (whether because you are changing
| representation or for other reasons), starting with trivial
| getters/setters instead of fields limits future breakage.
| legerdemain wrote:
| I had the same question -- why accessor methods instead of
| making the fields public, but final. If anything, it seems like
| a layer of indirection.
|
| The only answer that makes any sense is this one from Brian
| Goetz.[1] Namely, that it's a workaround to support mutable
| fields of otherwise immutable objects.
|
| To be honest, allowing you to override the methods on an
| immutable, auto-generated class to inject custom accessor logic
| feels like an immediate retreat from the conceptual goal of
| providing an immutable record implementation in the first
| place.
|
| [1] https://stackoverflow.com/questions/66702223/why-do-java-
| rec...
| skinkestek wrote:
| > why accessor methods instead of making the fields public,
| but final.
|
| The best explanation I have is that it is:
|
| - a convention that seemed like a good idea for many people
| at the time, it even has a name: Javabeans
|
| - it allows for a standard non magic way to add logic to be
| run when reading or updating fields
|
| - in a time where source control tools and Java refactoring
| tools where not as developed as they are today it made sense
| to make getters and setters everywhere since changing from
| public fields to accessor methods after it were already in
| use was probably scary for large teams.
| legerdemain wrote:
| Thanks for your speculation, but I'd rather take Brian
| Goetz's word for it. He is, after all, one of the
| architects of the Java language and the records feature in
| particular.
|
| ...Unless you're Brian Goetz's alt account?
| skinkestek wrote:
| > Unless you're Brian Goetz's alt account?
|
| I have a policy of saying whether if is true or false.
|
| That said you should take his word for why it was
| designed that way and my word as an historical account of
| why I did that in 2005-2015.
| smoldesu wrote:
| This might qualify as low-grade threadjacking, so I apologize if
| this is off topic, but who's actually using Java these days? Most
| devs I know avoid it like the plague, and only use it to maintain
| legacy codebases or get CS qualifications. Are there any real
| advantages to using Java in 2021, besides it's mature
| community/ecosystem/tooling?
| jeroenhd wrote:
| The existence of Spring Boot makes Java a very good choice for
| loads of dev shops. Good balance between features, ease of use,
| performance and security, not difficult to pick up, and very
| well documented.
|
| In my personal opinion, C# is a superior language these days
| now that most of .NET has been ported into dotnet core.
| However, that's only been the case for a few years and before
| that, Java was in a league of its own with its excellent
| library ecosystem and omnipresent JVMs.
|
| Java is a very boring language. Features get added slowly
| compared to other languages, improvements are generally quite
| gradual and new concepts only rarely ever get added to the
| language. This will drive away many hot startups and fresh CS
| graduates because they want to use the latest technologies in
| brave new ways and explore the ecosystem.
|
| For general businesses, boring is good. Boring is predictable,
| understandable and maintainable. Java is not the fastest
| language to write software in, but it's fast enough not to
| warrant teaching your staff a new language for. It's missing
| many features that are standard in other languages, but there's
| third party libraries to make up for that.
|
| In my mind, languages like Rust and Zig are the Teslas of the
| software world, exciting, new, full of flaws that need to be
| ironed out but ready to storm the general market one day soon.
| Go and Kotlin are the shiny new SUVs, impressive and high
| quality, but packed with weird design choices and opinions on
| how to use them. Java and C# are the old van the company has
| owned for 20 years. Nothing impressive, but reliable,
| comfortable, predictable, and with quirks that everyone has
| been learning for years now. Most businesses don't need a
| Cybertruck, they need to get around, and what businesses
| already have is good enough for the next while.
| bob1029 wrote:
| If C# didn't exist, we would certainly be a Java shop. Not only
| because of the ecosystem & tooling, but also because it is a
| language that has historically proven its ability to model
| incredibly complex business domains as well as support mission
| critical workloads without falling over on itself.
| azth wrote:
| How's your experience with C#/.NET been? Does it have an
| analogous offering to Java's JFR[0] for always-on profiling?
|
| [0] https://blogs.oracle.com/javamagazine/java-flight-
| recorder-a...
| bpicolo wrote:
| Seems like EventPipe is the C# equivalent?
| https://docs.microsoft.com/en-
| us/dotnet/core/diagnostics/eve...
| azth wrote:
| It seems somewhat similar, but I don't see mention of
| method traces (similar to a profile view in figure 7 in
| the blog post I listed).
| bpicolo wrote:
| There are tools built on top of it to that effect
| (eventpipe -> dotnet-trace -> tools built on top of
| trace) https://www.hanselman.com/blog/dotnettrace-for-
| net-core-trac...
| bob1029 wrote:
| I am not familiar with the scope of JFR, but there have
| been some very recent movements around profiling in
| C#/.NET:
|
| https://devblogs.microsoft.com/dotnet/introducing-dotnet-
| mon...
|
| https://devblogs.microsoft.com/dotnet/whats-new-in-dotnet-
| mo...
|
| My experience overall with the C# ecosystem has been
| fantastic. We started out on .NET Framework 4.x back in
| 2014-2015, and today are now talking about moving to .NET 6
| and rewriting our native apps to use MAUI as November grows
| closer. A lot of the same code we had back in 2015 is still
| running today with zero modifications.
| switch007 wrote:
| "historically proven its ability to model incredibly complex
| business domains"
|
| You surely can't be talking about its type system?
| bob1029 wrote:
| I certainly prefer the type system of C# over Java, but the
| latest things I've seen come out of the Java camp give me
| confidence that I could port most of the same ideas across
| the way without too much friction if need be.
| switch007 wrote:
| You said historically, by which I assumed you meant older
| Java versions, not later ones.
| autodidacticon wrote:
| It would seem that the world of data engineering is largely
| dominated by Java.
| throwpupper wrote:
| Java? Not so much. JVM? Absolutely. The ecosystem, stability
| and performance is unmatched.
| taftster wrote:
| Try this list out:
|
| https://projects.apache.org/projects.html?language#Java
|
| There's a LOT of real interest in Java in many many industries.
| Saying this like "Most devs I know" just really is more of an
| observation of your local circle.
|
| Big data, Finance, Government
|
| Just to name three really big industries that are dominated by
| Java.
| lowbloodsugar wrote:
| >Are there any real advantages to using Java in 2021, besides
| it's mature community/ecosystem/tooling?
|
| It's fast: C fast in most cases. It can use a lot of cores and
| memory with minimal effort from developers. It has great tuning
| parameters for things like GC. We hit a cliff at about 150GB
| heap, tuned it, and now we're at 300GB. It's "good-enough" type
| safe. Java grows with you.
| barsonme wrote:
| Android development. Kotlin is great, but Java is still a
| perfectly valid choice. In particular, if you don't have
| dedicated Android developers Java can be a good choice because
| most people are at least somewhat familiar with it and won't
| have to learn a new language to be productive. That said, I
| think anybody who understands Java should be able to understand
| Kotlin with minimal effort.
| EvilEy3 wrote:
| > besides it's mature community/ecosystem/tooling?
|
| Not sure if I should be mad or just ignore you.
| skinkestek wrote:
| > Most devs I know avoid it like the plague, and only use it to
| maintain legacy codebases or get CS qualifications.
|
| All the customers I have worked with since I became a
| consultant 4 years ago (and a couple of the best companies I
| worked with in the decade before) used Java or .Net. More
| specifically one of them was dotnet core and the rest are JVM.
|
| And I'm happy with that.
|
| Java and Maven means I can focus on the problem and not on all
| the crazy things people who think they are too clever to use
| Java do.
|
| I mean I have seen a couple of Abstract Factories in Java, but
| I haven't seen anyone avoiding putting passwords in the source
| code by writing things like this:
| rot13(<rot13password>)
|
| That is stuff I have found in Python code by the one consultant
| who was to smart to use Java or .Net.
| dboreham wrote:
| Java has the nice advantage that it works.
| Misdicorl wrote:
| > besides it's mature community/ecosystem/tooling
|
| Thats the answer. And its a _really_ good one.
|
| The only other languages with the same or better breadth and
| depth have their own reasons to avoid them like the plague
| (e.g. C/C++ footguns, difficulty managing large-ish codebases
| without types)
| villasv wrote:
| IKR. The question framing is almost like: is there any other
| reason to use Java except all the most important and good
| reasons?
| smoldesu wrote:
| I meant it more on a language level. It has a great network
| of support, no doubt credited to it's long legacy, but what
| technical advantages would it provide over writing a
| program in a language like C++ or Rust? Is it all creature
| comfort, or does it have some hidden advantage that I can't
| see?
| Misdicorl wrote:
| > besides it's mature community/ecosystem/tooling
|
| How could you not see this as an incredible technical
| advantage in almost any context?
| Misdicorl wrote:
| If you must have a specific language level technical
| advantage over C++/Rust, its the incredible GC algorithms
| available to you while you are (mostly) stuck with simple
| arena collectors in C++/Rust land.
| haolez wrote:
| It's a language that protects your investment. There is a lot
| of effort in backwards compatibility and the language puts a
| lot of constraints in the devs so that the development moves
| slowly, but in a sustainable manner.
|
| This is the best case scenario, of course. But it's an argument
| that I see being used in new Java projects.
| diab0lic wrote:
| A large chunk of the Netflix backend runs on the JVM. Much of
| it written in Java. While I agree that many devs avoid it like
| the plague, and I used to be one of them, once I let go of
| attachments to programming languages I found it quite a
| pleasant experience to develop software using Java.
|
| Basically using Lombok and Vavr give you a very nice
| lightweight functional experience. Bells and whistles tend to
| be a distraction from making software that works and scales.
| I'd way rather focus on the hard problems in computing than how
| to most idiomatically or elegantly express things in a
| language.
| johnthuss wrote:
| One of the best things about Records is that they guide you to
| creating immutable data structures, which Lombok does not. This,
| along with the reduction of boilerplate, greatly reduces the
| cognitive load required to understand a lot of code.
| oftenwrong wrote:
| The guidance is nice, but, unfortunately, Record components can
| still be mutable. It would be great if there was a way to have
| a stronger guarantee of immutability.
| chris_j wrote:
| Lombok has @Value classes, which I use a lot. Is there
| something about them that does not guide you to creating
| immutable data structures?
| watwut wrote:
| Lombok increases the cognitive load required to understand
| and debug the code.
| EvilEy3 wrote:
| @JvmRecord data class ...
|
| I'm sorry, you said something?
| jgrant27 wrote:
| They are still classes, still live on the heap and still need to
| be garbage collected. Compare with value types that live on the
| stack in other languages such as Swift, Go and Julia.
| The_rationalist wrote:
| Value classes, primitive types and specialized generics will be
| on the stack on the next versions. There is also this related
| work https://github.com/microsoft/openjdk-
| proposals/blob/main/sta...
| kasey_junk wrote:
| I've not explored them much, how well does escape analysis work
| with them?
| shagie wrote:
| The heap is an implementation detail.
|
| With escape analysis, the compiler can allocate the data on the
| heap, stack, or even stick it in registers.
|
| https://www.beyondjava.net/escape-analysis-java
|
| https://shipilev.net/jvm/anatomy-quarks/18-scalar-replacemen...
|
| https://www.javaadvent.com/2020/12/seeing-escape-analysis-wo...
| Someone wrote:
| Java compilers are getting more and more advanced, but I
| don't think they will ever become the magical "sufficiently
| advanced compiler" that produces code that's as good as
| humans _could_ (but often won't, because of time constraints)
| write.
|
| I don't think anybody fully disagrees with that. At least, I
| haven't heard people claim _int_ can be removed from the
| language because a good compiler can produce identical code
| for _Integer_ s.
|
| And yes, that can also apply to instances that _do_ escape. A
| sufficiently advanced compiler could in some /many cases
| figure out that an array of _Integer_ can be compiled down to
| an array of _int_. However, it's way easier for a compiler to
| check a programmer's claim "we won't use features of
| _Integer_ on these ints" than to deduce that code won't, so a
| little bit of programmer effort allows for a simpler compiler
| that can produce faster code.
|
| For me, records and (future) value types are examples of such
| "little bits of programmer effort"
| eklavya wrote:
| I could be wrong but I don't think dart has ints, I think
| it only has objects.
| Someone wrote:
| https://api.dart.dev/stable/2.6.0/dart-core/int-
| class.html:
|
| "Classes cannot extend, implement, or mix in int."
|
| https://api.dart.dev/stable/2.6.0/dart-core/num-
| class.html:
|
| "It is a compile-time error for any type other than int
| or double to attempt to extend or implement num."
|
| = it seems that, technically, you're right. _int_ is an
| object in Dart. At the same time, it's a restricted type
| of object.
|
| So restricted that I think it is aan object only in
| name/at compile time.
| anonymoushn wrote:
| Can you have an array of 1 million structs, not pointers to
| structs?
| im3w1l wrote:
| 1 million is not a lot. I'd begin by asking myselves "can I
| afford to chase those pointers?", because maybe you can.
| anonymoushn wrote:
| No, because my competitors who are attempting to fill the
| same orders I am attempting to fill are not chasing
| pointers.
| secondcoming wrote:
| are your competitors using java?
| jandrese wrote:
| You are chasing nanoseconds with a garbage collected
| language?
| jhgb wrote:
| Those nanoseconds tend to add up.
| Bjartr wrote:
| That's a good question to ask when faced with a problem
| that could be solved that way, but a real answer to the
| question would be useful too.
| [deleted]
| shagie wrote:
| The first question is "through static analysis, can you
| guarantee that the structs do not leave the scope?"
|
| The second question to look at is "which JVM are you
| using?"
|
| Different JVMs may implement this differently. This isn't
| something that one can say about _Java_. It is something
| that one _might_ be able to say about HotSpot, Zulu, or
| GraalVM.
| anonymoushn wrote:
| It's a global array of structs, let's say.
| shagie wrote:
| If it's a global, it's very likely allocated on the heap.
|
| The question of "what is the representation of the object
| on the heap?" then open.
|
| However, the "this is global" complicates it.
|
| This isn't a question for _Java_ to answer. You would
| need to dig into the specifics of the particular VM that
| you are using and how it allocates such a structure along
| with what optimizations it has available.
| iainmerrick wrote:
| You're technically correct that this stuff is all
| possible in principle, but the answer in practice right
| now is "no".
| kelnos wrote:
| Sure, but I think that's still important that it's
| possible. And if it doesn't get implemented, the reason
| may be because JVM developers have done the work to
| figure out that in the real world the optimization
| doesn't buy all that much.
|
| Regardless, if you care about performance enough (via
| actual benchmarks) that you know that you really need
| some data to be guaranteed to be stack-allocated structs,
| then you probably shouldn't be using Java (or any GC'd
| language?) in the first place. Records don't change that
| calculus.
| shagie wrote:
| From the link about GraalVM:
|
| > Something that Graal can do that C2 cannot, and a key
| advantage of GraalVM, is partial escape analysis. Instead
| of determining a binary value of whether an object
| escapes the compilation unit or not, this can determine
| on which branches an object escapes it, and move
| allocation of the object to only those branches where it
| escapes.
|
| And from
| https://docs.oracle.com/en/java/javase/11/vm/java-
| hotspot-vi...
|
| > The Java HotSpot Server Compiler implements the flow-
| insensitive escape analysis algorithm described in:
|
| > ...
|
| > After escape analysis, the server compiler eliminates
| the scalar replaceable object allocations and the
| associated locks from generated code. The server compiler
| also eliminates locks for objects that do not globally
| escape. It does not replace a heap allocation with a
| stack allocation for objects that do not globally escape.
|
| ----
|
| So, some JVMs implement, others only do a limited subset
| of the optimizations available with escape analysis.
|
| I would not say that the answer of "is it used in
| practice" is "no."
| dtech wrote:
| GraalVM is excellent in performing escape analysis on
| objects on the call stack, but it does not prevent the
| pointer overhead that a JVM array-of-heap-object-
| references has vs an array-of-structs that e.g. .NET
| supports [2].
|
| _Theoretically_ it could do hat, but that 's just the
| classic "sufficient smart compiler" strawman [1]
|
| [1] https://wiki.c2.com/?SufficientlySmartCompiler
|
| [2] https://stackoverflow.com/questions/29665748/memory-
| allocati...
| shagie wrote:
| My point wasn't so much "can GraalVM do {some
| optimization}" but rather that the Java Language
| Specification doesn't say anything about it and that
| different JVMs have a different set of optimizations.
|
| So "does Java allocate a record in an array directly as
| some structure of values in the array or as a pointer to
| a record object?" isn't one that can be answered by
| looking at Java.
|
| It _is_ an interesting question, and I 'd be curious to
| see someone do a deep dive into the internals of GraalVM
| to show what can be done.
|
| The other part that trickled out in other comments from
| the person posing the question about the array of
| records:
|
| > It's a global array of structs, let's say.
|
| and
|
| > No, because my competitors who are attempting to fill
| the same orders I am attempting to fill are not chasing
| pointers.
|
| ... which, I'd be curious to see how .NET supports an
| array of struts (that are presumably changing over the
| lifetime of the array) that is allocated as a global.
| That sort of use case and the specifics of how it is
| implemented could make escape analysis give up and you'll
| see an array on the heap with pointers to records on the
| heap as they're passed off to different threads (which
| each have their own stack).
| dtech wrote:
| The point is those optimizations are not here now, and
| haven't been there for the last 25 years. Hand-waving
| them away as theoretically possible is dishonest. We're
| 25 years into the most popular programming language's
| lifetime and the most advanced VM available only recently
| learned good escape analysis. It isn't easy.
|
| > which, I'd be curious to see how .NET supports an array
| of struts (that are presumably changing over the lifetime
| of the array) that is allocated as a global.
|
| Very easy. An array-of-structs (which can still be on the
| heap mind you) will just be a continuous block of memory.
| This is totally independent of any locking and
| synchronization.
|
| For example in a class with 2 32-bit fields, and an array
| of objects a b object-ref array will look like: [p_ap_b],
| p being a pointer to [a_0a_1] or [b_0b_1]. A struct-array
| will look like [a_0a_1b_0b_1].
| [deleted]
| loukrazy wrote:
| Isn't the point that Record classes will be able to be upgraded
| to value types easily once Valhalla is done? Or am I missing
| something
| The_rationalist wrote:
| No they won't (or maybe they will be able to be speculatively
| opt-deopt?) Value types above a relatively small size are
| less efficient than references.
| kasperni wrote:
| Yes, just add 'primitive' before record in the declaration.
| valenterry wrote:
| > Actually, records are even better* than tuples. EP 395 says: >
| > Records can be thought of as nominal tuples.
|
| They are certainly not better, that's just a sad click-bait (the
| author even admits that).
|
| Sometimes nominal typing is better and sometimes structural
| typing is better. Forcing people to always use nominal types just
| ends in a lot of generic or long/meaningless names - one can
| already see this in Java.
| slver wrote:
| I've been thinking about structural vs nominal. As you say,
| both have use cases. How would you combine both in one language
| so it's not confusing?
| amitport wrote:
| TypeScript!
| swsieber wrote:
| Restrict structural types to tuples only.
| slver wrote:
| That honestly won't be very useful.
| The_rationalist wrote:
| Nominal ![?] named You can have named tuple members while
| maintaining structural typing, it's not mutually exclusive.
| kelnos wrote:
| My general rule (in Scala) is that if I need a tuple larger
| than two or three elements, I'm better of writing a case class.
| Tuples get unreadable real fast.
|
| I think tuples are an essential language feature (and it's
| ridiculous that Java doesn't have them yet), but I think
| they're often way overused.
| jayd16 wrote:
| Records are good but if you want this in Lombok don't you just
| use @Getter instead of @Data to generate read only methods?
|
| Serialization is handled by Java bean getters and setters just
| fine. I don't really see an advantage.
| simonpantzare wrote:
| I've used @Value along with @Builder(toBuilder=true).
| ctvo wrote:
| Who is arguing otherwise? It's assumed that when a language adds
| a new feature that's historically been provided by libraries,
| it's probably better optimized. CompletableFutures, Streams,
| Date/Time. For many they've replaced libraries filling the gaps.
|
| But not all of us can use JDK 14, and will continue to use Lombok
| if we're writing in Java.
| Rapzid wrote:
| Work on a Grails app; only boots on up to 11 ATM. BUT, the hot
| reload only works with 8... So while the app runs on 11, most
| development occurs on 8 still.
|
| Lombok JustWorks(tm). You forget it's there until you setup a
| new dev environment and forget to setup the annotation
| processor in IntelliJ.
| pkulak wrote:
| So what's the answer to the question? Pattern matching and
| destructuring? But I don't see any reason Kotlin data classes
| can't do that. I know Kotlin pattern matching is pretty lack-
| luster, but I never thought this was the reason.
| abductee_hg wrote:
| sorry -java .. better? what? why would anyone use java for
| anything? let me give an example: from a project a while(some
| years actually) ago i still have a license for a php-ide(zend).
| its in java. no chance in hell to get it working today.
|
| meanwhile, stuff i did 2003 still runs on windows out of the box,
| even in wine/osx. so again: why use java for anything?
| https://twitter.com/abductee_org/status/711966430133026816 (try
| it https://www.pouet.net/prod.php?which=11247 )
|
| oh and there is this:
| https://people.eecs.berkeley.edu/~wkahan/JAVAhurt.pdf so, double-
| again: why use java for anything?
| AtNightWeCode wrote:
| Not sure why immutable data structures have surfaced as something
| important. Typically you never change fields so it is kind of
| only of academic value if a field in a POD, POJO, POCO or
| whatever it is called in the specific language actually may
| change.
| ramblerman wrote:
| > so it is kind of only of academic value if a field in a POD,
| POJO, POCO or whatever it is called in the specific language
| actually may change.
|
| I'm not sure if you've debugged much, or inherited any large
| legacy projects, but knowing it is immutable vs "typically it
| isn't" is a pretty big distinction in that moment.
| AtNightWeCode wrote:
| Good code don't have this issue.
| slver wrote:
| Good code doesn't have concepts like "typically doesn't
| mutate". It's either mutable or immutable.
| AtNightWeCode wrote:
| The standard way to do it is to mutate clones as always
| in Java. Typically by use of libraries that provide this.
| You really need very bad code to have to think about if
| objects are mutable.
| slver wrote:
| Apparently you don't know most immutable structures are
| optimized for modified cloning in ways mutables aren't.
| AtNightWeCode wrote:
| This is Java.
| razzm256 wrote:
| There are many good things enabled by immutability, like
| safer/easier multithreading, value-like semantics for objects.
| It is _definitely_ not only of academic value.
| AtNightWeCode wrote:
| Typically you use values and not objects for these kind of
| things so not that much gained.
| the_af wrote:
| "Typically" this means you can never be sure, which is a
| problem.
| AtNightWeCode wrote:
| Sure of what? If your code is not garbage it takes two
| seconds to see where things change. It should be very places
| in the code.
| slver wrote:
| It takes two seconds in a hello world demo. It takes
| probably more in a millions of lines project.
| AtNightWeCode wrote:
| Fields of an object should typically not change. But yes,
| I had to make a field of a class immutable some time ago.
| There was a bug and I could not read the code to figure
| out were the object was changed. Still, caused by bad
| code. Same object sent around pretty much everywhere.
| slver wrote:
| So even you, the master of great code, wrote bad code. I
| guess immutability is worth something then.
| AtNightWeCode wrote:
| I did not write the original solution...
| the_af wrote:
| Precisely: you did not write the original solution, which
| is where immutability shines. It's a code comprehension
| tool; it gives you guarantees about code _you_ didn 't
| write. That's a huge boon!
| AtNightWeCode wrote:
| There are no guarantees that it is the same object you
| get so it is pointless.
| slver wrote:
| So you reckon we only need immutability if two or more
| people have to work on code. Ok.
| AtNightWeCode wrote:
| You are just too stupid. I hope you are not immutable.
| reom_tobit wrote:
| Keyword being "may".
|
| Guarantees are nice. Especially if objects are going to be
| passed around every which way from Sunday. It allows you to
| better reason about what could happen, and where.
|
| Java has taken a while to get there, but I'm glad that they
| have finally.
| AtNightWeCode wrote:
| Well, if you pass around objects and change their state
| records will not help. People who does this are already using
| immutable frameworks in Java to clone and change some field
| and then pass it along.
| reom_tobit wrote:
| Sure, things have been bolted on top of Java to allow this
| to happen. People have made use of them.
|
| Java now has built in support for these things, so no
| longer will developers rely on third-party solutions.
|
| This is great for the Java world, and for any languages
| that are being built on top of the JVM by extension.
|
| I would politely disagree with your characterisation of it
| being just academic, as an engineer I find it incredibly
| exciting. Admittedly, my bar is pretty low for excitement
| these days.
| AtNightWeCode wrote:
| I have done Java for 25 years and never felt any need for
| records. There are so many issues...
| jsd1982 wrote:
| Using Dark Reader extension for Chrome, all of the sample code
| text goes to the same color as the background so I thought I was
| scrolling over huge chunks of blank space.
| tut-urut-utut wrote:
| It's not blog authors responsibility to test his blog for all
| possible extension that some readers might be using.
|
| If the reader is using some third-party software that modifies
| the original blog design, it's his responsibility to disable it
| if it doesn't work seamlessly.
| [deleted]
| knoebber wrote:
| I agree with this in general, though sometimes
| incompatibility with popular extensions is an indication that
| the author isn't following standards.
| tomc1985 wrote:
| Asking people to test against all the combinations of
| browsers _and_ extensions? That 's asking _a lot_
| capitainenemo wrote:
| I was surprised to encounter this as well in Firefox using Dark
| Mode. I'm still not 100% sure what's going on, because it's
| rather odd, but if I inspect the page, and add a: .language-
| java { opacity: 0.99999 } All content instantly renders.
| Interestingly: .language-java { opacity: 1 } or .language-java
| { opacity: 0.99999999 } /* probably same as 1 */
|
| Blanks out the content again. Seems rather odd behaviour to me
| so definitely interested if anyone figures it out, even if this
| is kind of derailing the discussion.
| capitainenemo wrote:
| Kay. Day got a bit more quiet. I vaguely remembered running
| into this weirdness before. It's 'cause apparently opacity
| creates a new stacking context. Doing z-index:1;position:
| relative; does same thing. The rule that seems to be breaking
| everything is the one that forces a default opaque background
| on everything with dark text. For it to break this, there
| must be overlapping content, but haven't found it yet. But
| enough to know what was going on..
| billyjobob wrote:
| Kotlin data classes can use Java records as their implementation
| if running on JVM, so it's not like you have to choose one or the
| other.
|
| https://kotlinlang.org/docs/jvm-records.html#declare-records...
| _old_dude_ wrote:
| I wonder why, unlike a Java record, in Kotlin a data class
| annotated with @Record can not be local.
|
| Being able to use local records is a useful feature in
| particular in unit tests. @Test void
| testPoints() { record Point(int x, int y) {}
| ... }
| crdrost wrote:
| This is great news!
|
| I was also kind of surprised to see the article talking about
| algebraic data types... table stakes for ADTs is sum types and
| I have missed them considerably in the Java ecosystem.
|
| Kotlin has something like them with sealed classes, although
| I'm a newcomer to the Kotlin and Spring Boot ecosystem so I
| don't see explicitly how I make some simple case like JSON
| {"type": "left", "abc": 123} {"type": "right", "def":
| "456"}
|
| turn into some structure like: sealed class
| EitherTest { data class Left(val abc: Long):
| EitherTest() data class Right(val def: String):
| EitherTest() }
|
| rather than the hacky version that you have to do in relational
| databases and Java which don't support such things,
| enum class EitherType { LEFT, RIGHT } data class
| EitherTest(val type: EitherType, val abc: Int?, val def:
| String?)
|
| Like I'm not saying that there's _no way_ , I'm sure there's a
| way... just that the ecosystem seems so hesitant to embrace sum
| types that like the above sealed class is widely viewed as a
| hack and there is no statement about "here is how you actually
| use sum types for everything in your Spring application with
| Kotlin."
|
| Was gonna give the choose-your-own-adventure example of why sum
| types are handy and how you have to kind of hack around them
| with inheritance when you don't have them but it occurs to me
| that anyone who has stuck with this comment this far probably
| already has some familiarity with this?
| TJSomething wrote:
| In traditional Java, you're probably using Jackson for your
| JSON. You can achieve those sorts of results by specifying
| the classes and type tags in annotations on an abstract
| Either class to use Jackson's polymorphic serialization
| feature.
| balefrost wrote:
| The point of sealed classes is that you have a known number
| of possible representations. So you can have `when` blocks
| that exhaustively check all possibilities. Having an open
| class hierarchy would not work for that purpose.
| oftenwrong wrote:
| Sealed classes are (most likely) going to be in the next
| version of Java, Java 17: https://openjdk.java.net/jeps/409
| The_rationalist wrote:
| Kotlin data classes can be used with the JPA contrary to Java
| records. It's good to encourage immutability, but it is often a
| misfit and isn't the role of a "data class", they could have
| added a separate class qualifier immutable that would have been a
| better separation of concerns, here it's ad-hoc. Kotlin is
| enabling such immutable support thanks to Java records ironically
| https://kotlinlang.org/docs/jvm-records.html#declare-records...
|
| Note however that an upcoming version of Java will get first
| class ergonomic support for manipulating immutable data:
| https://github.com/openjdk/amber-docs/blob/master/eg-drafts/...
|
| There is also https://github.com/hrldcpr/pcollections
| hueho wrote:
| > Kotlin data classes can be used with the JPA contrary to Java
| records.
|
| Arguably this is more of an issue of JPA than an strict
| advantage of Kotlin: JPA was designed at a time where the
| general consensus was to primarily use mutable data, and was
| heavily influenced not only by existing Java ORM APIs, but by
| their implementations.
|
| Kotlin itself supports JPA by the use of a compiler plugin,
| which is a good enough solution, but nevertheless, not one
| native to the language. Data classes mostly work by accident,
| but pretty much any documentation you will find points it to
| _not_ use them with JPA.
| vips7L wrote:
| I'm really not sure if using data classes with JPA is smart
| idea. Solely because of generated hashCode/equals and JPA lazy
| loading. For instance ebean recommends against it [0].
|
| https://ebean.io/docs/best-practice/#kotlin-data-class
| Bjartr wrote:
| > Kotlin is enabling such immutable support thanks to Java
| records ironically
|
| That a member of the JVM ecosystem is leveraging new JVM
| capabilities isn't ironic, it's totally expected.
| rdsubhas wrote:
| I believe the article focuses too much on "perceived/future"
| benefits of records, while ignoring the actual benefits that
| Lombok & Kotlin data classes provide today.
|
| For example, article does not mention lombok @Builder and Kotlin
| `copy` when talking about boilerplate. Boilerplate is not just
| about application code, it's also about test code!
|
| We have dozens of entities, and when unit testing them - always
| having to construct the COMPLETE record with all attributes from
| scratch is a pain. Nested records things worse. We now have all
| data classes as @Value+@Builder, and test factories provide
| consistent builders which the actual test cases can chain,
| override and use. This is possible in Lombok & Kotlin, but not in
| Record.
| MichaelMoser123 wrote:
| yes, java records are part of jdk14, many places are still
| stuck with jdk8 or jdk11, hoewever everyone can use lombok
| (they didn't mention that detail in the article)
| valenterry wrote:
| Scala's case classes are missing in the comparison (only
| mentioned briefly at the very end). They offer everything that
| records do and more. Good to see that Java finally catches up a
| bit.
| pron wrote:
| I don't think they offer more. Deconstructing patterns and
| "reconstructors" (generalised "withers") are on the way. And
| Java features are often designed as a complete whole: some of
| the feature is in the language, some in the core libraries, and
| some, even, in the VM. In the case of records, they're treated
| in a special way by the runtime (e.g. in serialisation).
| halfmatthalfcat wrote:
| Scala is usually omitted for one reason or another when Kotlin
| is compared against Java as a better alternative, which is a
| shame.
| aero142 wrote:
| Scala has to the solution to every problem except the problem
| of too many features.
| AzzieElbab wrote:
| Maybe but scalas case classes are super easy to grasp and
| require no magic like annotations
| xenomachina wrote:
| What annotations are you referring to?
| scubbo wrote:
| I'm not the person you were asking, but, presumably,
| Lombok's annotations.
| AzzieElbab wrote:
| Lomboks. Seriously, scala case classes are like the very
| first thing people start using when learning the
| language. Scala3 enums are even more straightforward
| xenomachina wrote:
| The ancestors of your comment mention Kotlin, not Lombok,
| which is why I asked. Kotlin's data classes are probably
| the analog to Scala's case classes, and they do not
| require annotations.
| ernst_klim wrote:
| > except the problem of too many features
|
| Scala is a pretty simple, concise and coherent language
| though. Never understood why people deem it has too many
| features, I write it professionally and never felt so.
|
| At least comparing it to C, C++, Python. Java may be more
| simple, but you have tons of features added with
| metaprogramming via dozens of annotations generating lots
| and lots of boilerplate, Lombok and Spring are examples of
| that.
| kerblang wrote:
| > Never understood why people deem it has too many
| features
|
| I'll start with one (key)word: `implicit`
|
| I agree with your distaste for metaprogramming though.
| halfmatthalfcat wrote:
| You can use Scala without introducing implicits and even
| if you have to interopt with a library that does require
| them, it's quite easy to learn how to use them. It's also
| easy to abuse them but then that's not really Scala's
| problem.
|
| They are changing implicits in Scala 3 though with the
| "given" keyword which is more ergonomic.
| cutler wrote:
| Scala can't let go of implicits as they're a fundamental
| part of the language. I just don't believe this Scala 3
| fudge to give the impression implicits are not alive and
| well beneath the surface.
| asimpletune wrote:
| You don't have to use implicits though, but you'd be
| super happy they're there should you ever be in a
| situation where they're helpful
| diroussel wrote:
| Doesn't a monad or for comprehension use implicits to
| find the right CanBuildFrom?
|
| Are you suggesting to use scala without using for
| comprehensions? Or do you mean you don't need to write
| your own?
|
| It's been a long time since I wrote scala, so may be
| getting it wrong.
| ernst_klim wrote:
| > I'll start with one (key)word: `implicit`
|
| I don't think implicit counts as "too many features" or
| as something complex. Basically all it does is finding a
| canonical value in scope for a hole of certain type.
| kjeetgill wrote:
| I only worked in Scala briefly so maybe it's coming from
| Java habits, but implicits were huge pain. When first
| reading through code you don't really know if that
| function call you eyed over really has the params you
| think it does. It makes it WAY harder to track what's
| derived from what.
|
| Either way, the local Scala guru there said the Scala
| community was starting to get over implicits.
| adambatkin wrote:
| Lombok and Kotlin are both much easier to integrate into
| existing Java applications and libraries than Scala.
| krzyk wrote:
| Lombok is the problem not a solution (see
| https://github.com/projectlombok/lombok/issues/2681
| regarding support for JDK 16 to understand why) and a
| ticking time bomb in every project that wants to move past
| JDK 15/16.
|
| But why do you think Kotlin is easier to integrate than
| Scala? Both work on JVM.
| kelnos wrote:
| I don't see how Kotlin is easier to integrate into an
| existing Java app than Scala is. They both require adding
| new dependencies and changing your project build config,
| and require developers who know the respective new
| language. That's... about it. They both offer similar
| levels of interop with Java libraries.
|
| If you want to assert that finding Kotlin developers is
| easier or that Kotlin is an easier language to learn, sure,
| that might be the case (I really don't know), but that's
| not really an integration task.
| throwpupper wrote:
| What about the fact that Kotlin collections are fully
| interoperable with Java collection? That makes the
| transition significantly easier.
| halfmatthalfcat wrote:
| I believe Scala's are as well, this seems to be a pretty
| complete list:
|
| https://www.scala-
| lang.org/api/2.13.5/scala/jdk/javaapi/Coll...
| balefrost wrote:
| Kotlin's STDLIB collection types are essentially aliases
| for the Java types. So while the Scala adapters are low-
| cost, in Kotlin everything's zero-cost.
|
| One other benefit of that is you maintain object
| identity. I don't think that Scala's wrappers do that.
| darksaints wrote:
| Scala has the full suite of Java collections without any
| conversion or overhead whatsoever.
|
| But it also has Scala collections. With scala collections
| you get the full power of the Scala type system, as well
| as a much richer and full featured collections api. So
| most scala programmers won't bother with java collections
| unless they have specific java interop requirements.
|
| The Scala adapters are merely ways of converting java
| collections to scala collections and vice versa.
| mumblemumble wrote:
| I think that case classes are roughly equivalent to Kotlin data
| classes for the purposes of this comparison. In particular, one
| of the extra features they offer is the ability to make fields
| mutable. Which, in some cases, may be useful, but also means
| that they aren't, strictly speaking, _transparent carriers of
| immutable data_.
| throwpupper wrote:
| I think the article is misleading in the list of advantages over
| Kotlin's Data Classes.
|
| 1. Destructuring - available in Kotlin
|
| 2. Copy with change - available in Kotlin
|
| 3. Serialization - not sure why Kotlin data class would not be
| serializable
|
| 4. Boilerplate - Kotlin takes care of equals and hashCode
|
| Huge disadvantage that matters to me is that record fields cannot
| be mutated. It makes the records much less useful.
| throwaway4good wrote:
| "Huge disadvantage that matters to me is that record fields
| cannot be mutated. It makes the records much less useful."
|
| No. It makes them much more useful.
| throwpupper wrote:
| Well it means that the second you need a setter you can't use
| records so all the boilerplate remains.
| zaphar wrote:
| Why would you need a setter for a data class? They add no
| value there.
| [deleted]
| valenterry wrote:
| You are supposed to create a new copy with some of the
| fields changed. Just like you do it with the java.time.*
| classes and others.
| bcrosby95 wrote:
| Yet the only mechanism for this is error prone or relying
| on mountains of boilerplate.
| vbezhenar wrote:
| Instead of changing few bytes, now I have to copy
| hundreds of bytes around and add more stuff for GC to
| collect.
|
| Well, they have to obey Wirth's law, I guess.
| kaba0 wrote:
| Or you know, the JIT will trivially optimize away the old
| class if it is reassigned to the same variable, as you
| would use it inside a loop. How do you think the litany
| of FP languages work? Like Haskell, Scala, Clojure?
| vbezhenar wrote:
| That's a theory not happening in practice. In practice
| Java programs are slow and memory-hungry because of those
| issues when some people think that it's cheap to create
| small objects or that escape analysis will solve their
| issues without verifying that it works for their case.
| kaba0 wrote:
| Most of the world's server applications would like to
| disagree with you.
| slver wrote:
| Java isn't perfect. But you underestimate the amount of
| software written in it. Or even things like Python and JS
| which are a lot more basic but have similar elements in
| regards to their memory model. What do you use?
| vbezhenar wrote:
| I work as Java developer for the last 10 years, I
| perfectly understand the amount of software and other
| things.
|
| I don't know much about Python and JS, but I do know that
| they're not using immutable model, everything is mutable
| in Python and in JS, so I'm not sure what's your point.
| The only immutable language I'm aware of is Haskell which
| is not used widely. Just because JVM is faster than
| Python or V8 does not mean that it's OK to slow it down
| with immutables.
| slver wrote:
| Using immutables doesn't mean you go full Haskell.
| Strings are also immutable you know.
| slver wrote:
| It can be done in theory, but the JVM does nothing of the
| sort right now.
| kaba0 wrote:
| False. The JVM already does quite a good job with escape
| analysis, and record types just add extra semantic
| information to potentially further improve the situation.
| slver wrote:
| What precisely of what I said is "false"?
| kaba0 wrote:
| the JVM does _something_ of the sort right now.
| slver wrote:
| Every time you rebuild a record you run through its
| constructor. I doubt this can be optimized the same as
| with a plain C struct.
|
| Eventually with some more evolution. But not yet.
| jandrese wrote:
| Counterpoint: Java programs with memory consumption
| graphs that have decided sharktooth patterns, which is
| extremely common.
| kaba0 wrote:
| As opposed to what exactly? How would a C program's
| memory graph look with quick bursts of memory-allocation
| requiring functionality, especially if it is very dynamic
| in nature? Yeah you can overallocate with memory pools
| and the like, and there are cases of course where escape
| analysis can't help -- that's why Valhalla is in the
| works for quite some times now.
|
| But GC-wise the JVM is far ahead the game, whatever you
| see is likely better than the same functionality would be
| under JS, Python, C#, Go, etc (though the latter two do
| have value types/structs already so they can at some
| place manually do the "escape-analysis". But not every
| problem requires/can use value types either)
| kelnos wrote:
| I don't know if the JVM developers have actually
| implemented this, but since records are immutable,
| there's no reason why a copy couldn't share memory
| between the instances.
|
| The major downside is that could ruin cache locality and
| make passing the instance across a FFI boundary require a
| copy.
|
| Another optimization would be that the JIT (or even
| perhaps javac) could notice cases where you make a copy
| (with one field changed) of a record and then never use
| the original reference again. If the JIT (or javac) can
| prove that no other bit of code holds a reference to the
| original record, it can reuse and mutate the original one
| instead of making a copy. I don't know if this
| optimization is or will be implemented, of course.
|
| Either way, I expect the overhead you mention ends up
| being worth the benefits of immutable data. (That's been
| my experience using Scala, anyway.)
| JackFr wrote:
| You have to copy less than you think. Because the data is
| immutable, you can share everything but the changed
| fields.
| The_rationalist wrote:
| Then you've invented mutability without
| references/identity. Except those are desired properties
| for data classes, unlike for value classes which have
| such semantic difference.
|
| Btw Kotlin allow to make immutable Java records too so
| clear winner.
| pkulak wrote:
| Not sure what you're getting at. Immutable means exactly
| that. If you hand out an object, then do a copy change,
| that change isn't reflected in the object you gave to
| another method/thread/fiber/etc. Immutability doesn't
| mean application state never changes; it means that a
| single reference will always point to memory that hasn't
| changed.
| the_gipsy wrote:
| You write java and worry about bytes copied?
| vbezhenar wrote:
| Yes, I do. Java could be quite fast if you won't slow it
| down on purpose.
| marcinzm wrote:
| I mean, you do realize that you're writing Java code
| right? If you want ultimate low level optimization and
| control then you're already about ten miles too far
| downstream to make that turn. Also, I'm guessing the copy
| overhead is more than offset by the JVM being able to do
| better optimizations around these data structures.
| iainmerrick wrote:
| Structs with mutable fields is hardly "ultimate low level
| optimization", it's something a lot of programmers still
| use as a matter of course. (I say this as a fan of
| immutable data!)
|
| Ultimate low-level optimization in Java would be more
| like packing your structure into arrays of integers -
| which is something _people actually do_ in Java. Just
| because you're using Java doesn't mean you don't want
| your code to run as fast as possible.
| davewritescode wrote:
| This has been argued ad nauseam around the time Scala
| started gaining traction because scala's collections are
| grouped into immutable and mutable. The consensus at the
| time is that the GC overhead is well worth the ability to
| parallelize computation.
| krzyk wrote:
| GC is there for a reason, unless you do HFT, use it to
| your advantage.
___________________________________________________________________
(page generated 2021-05-07 23:02 UTC)