Hacker News new | ask | show | jobs
by mabbo 1744 days ago
> Language

> Pattern Matching for instanceof (16)

> Records (16)

> Restore Always-Strict Floating-Point Semantics (17)

> Sealed Classes (17)

> Switch Expressions (14)

> Text Blocks (15)

This is what excites me. Records, switch expressions and sealed classes are all excellent and even better together. Along with pattern matching switch statements, Java is finally losing a lot of cruft people complain about.

2 comments

a lot of these were the killer feature of scala that separated it from other languages
I'm trying to find a good use case for records, but the best I can come up with is using it for composite hashmap keys. I suppose when combined with sealed classes and pattern matching features at some point it might be more useful, but what is the main use for records right now? Given that they're immutable and have no convenient way to be copied when modified, I find them quite tedious to use.
I work as a systems developer for a bank and records is an easy replacement for a very popular dependency called lombok. Now, records doesn't necessarily do everything that lombok does, but for us it replaces what we actually need. One less dependency and I'm a happy camper.
I think it's worth highlighting that while Lombok is a dependency it is only a compile time dependency (it's not part of the output JAR).
You say only, but I find that to be much more fussy.
Exactly, I hate dealing with Lombok projects for that reason. I'd rather the cruft than the compiler add-on.
Do you not just use maven? Any of the major IDEs will automatically configure annotation processors for you when they're configured in your pom. Similar for gradle.
Honestly, I expect that half the classes I write will be records, once I have access to this.

A lot of the time, the software I'm working on has data objects that are really amalgamations of other fields. Example: "Address" is the street address, the city, the postal code, etc, etc. These sorts of objects should be immutable. Records are perfect for that.

If I need to add additional logic, methods, then you can add those to a record. But it continues to enforce that the state is immutable.

For example,

* tuples (complex numbers, points, dimensions, colors, IP addresses),

* database query results,

* stateless beans for DI frameworks where it cuts down on the verbosity of using constructor injection (actually a slight misuse)

* composite natural keys in database modeling

The immutability can help to enforce API contracts and proper service layering. A common problem in legacy code is modules communicating with each other by modifying objects that were passed as arguments.

Eventually, Project Valhalla will introduce the possibility to declare records as primitive, which will also reduce the overhead of Wither methods.

Edit: Building web APIs should also benefit from records because the argument and result types are only supposed to be created and read, not modified.

I guess records will make valhalla (value types) easier which enables more efficient data structures and will probably make passing data over FFI (valhalla) easier too.

They reduce a lot of boilerplate, e.g. when passing multiple return values.

Records are orthogonal to value types (now called primitive types).
I thought they are light weight ways of declaring a structure. From there they take different paths for immutability extensibility allocation … etc
I find records super useful! You can not only express things like a Point(x, y) easily, but you can also wrap primitive types like integer to give values semantic, behavior and typesafety. Records are the perfect fit for value types as used for example in Domain-driven Design.
We would use them as data transfer objects between different layers of the system - however, they cannot extend another class and thus are not suitable in our specific case.
Probably 1/2 of all Java classes written should be records.
No more Lombok @Data annotations needed...
Actually, I think it would be the lombok @Value. Record classes are immutable, while @Data adds set methods.
So one thing peculiar in Java is public records have to be in their own files. Now I wanted to treat records as less ceremonial than classes to organize code. I'd have liked to have a dozen or so records in a file along with some basic operations on them but it is not possible have multiple records without that many files.

I know the answer is always use IDE and all but it causes more context switches than scrolling a bit to see types I created.

If you have a bunch of related records you can make them public and nested within a top-level public class. You could also throw some static utility or factory methods in there too.
Sure, but that's still ceremony.
It's a core restriction of Java that there can only be one public class in each file. Nesting records inside a class would solve the issue. It's not that pretty though because only lower-casing the class name would create the illusion of it being a package.
I would use records a lot more (pretty much everywhere) if I could easily derive new values from existing ones.
There are some funny ways to work with records. I can recommend this article: https://benjiweber.co.uk/blog/2020/09/19/fun-with-java-recor...
Still way too much typing compared to lombok's @Value @With.
This will be solved[1]:

record Point(int x, int y) {}

Point p = new Point(1, 2); Point pp = p with { x = 3; }

[1] https://github.com/openjdk/amber-docs/blob/master/eg-drafts/...

Interesting. It's ok. It seems like they're adding this syntax just to avoid extra copies eg, `p with {x = 3, y = 4}` instead of `p.withX(3).withY(4)`. I really don't mind the later.

My gut feel is that records break encapsulation and will make refactoring slightly more difficult than the equivalent lombok value class. But if this gets more people making objects immutable, I'm all for it.

TBH both approaches are just poor design of the object model. The one from my link is a clever but inefficient way to manipulate records (reflection), the one with Lombok is creating redundant interfaces without business meaning. A record with few business methods is lean enough and ensures that only valid transitions can happen.
Eh? This is pretty good:

   Colour changed = colour.withRed(5);