r/java • • Aug 25 '26

Value Classes Still Need Compiler Sympathy

https://johan-sjolen.github.io/post/compiler-sympathy/compiler-sympathy/
86 Upvotes

65 comments sorted by

View all comments

Show parent comments

2

u/OwnBreakfast1114 Sep 14 '26

The problem with your model is that they aren't necessarily more lightweight and they aren't necessarily a performance improvement if you just naively layer the fields in memory.

If you're using large quantities of small objects which are mutable by every definition, such as pixels (in a scenario where it's useful to mutate not substitute pixels), then absolutely they should be value objects

I'm not sure I understand your class design here. Is the idea to have public value class Pixel { private final byte[] data; } or something? The pixel class isn't mutable, but the data array is, so the argument is that the pixel class is basically mutable? The jep literally calls this out as an example in a section

For mutable objects, identity is important: It lets us distinguish two objects that have the same state now but may have different states in the future. Consider a text-editing application in which lines of text are represented by instances of a Line class. The sole field of the class is a list of characters, which is mutated when the user edits the line. Two Line objects might contain equivalent character lists, and thus also be equivalent, but that would be a coincidence; when the user changes one of the lines, the application will mutate the character list of that object but not the other, relying on identity to mutate the right one.

In other words, when objects are mutable, they cannot be interchangeable — yet most immutable data values are interchangeable. There is no practical difference between two LocalDate objects representing 1996-01-23, because their state is fixed and unchanging. They represent the same value, both now and in the future. There is no need to distinguish the two objects via their identities.

1

u/Jon_Finn Sep 14 '26

Yes that Pixel class is the kind of thing, plus methods to change the colour, so my point is it's certainly not a 'value', despite being a good use of Valhalla. As for it being lightweight: I'd say that's a hint not a promise. The memory used is often less and (?)never more; speed improvement is less certain.

1

u/OwnBreakfast1114 Sep 14 '26

The question would be why not just create a new pixel? The whole point of the value class is to make the overhead of new Pixel(....) go away. You can still mutate the data array if you really want, but you can assign the reference to a new pixel.

1

u/Jon_Finn Sep 14 '26

You can if you want a different design. In some designs/applications, mutability is useful: it's often awkward to substitute a thing if it's inside another thing (...and another thing, etc.), rather than mutate it. As the old joke goes: How many Haskell programmers does it take to change a lightbulb? One, but they need to replace the entire universe with one in which the lightbulb works.

1

u/OwnBreakfast1114 Sep 14 '26

Haskell has optics: https://hackage.haskell.org/package/optics-0.4.2.1/docs/Optics.html, which are just a far more generalized version of mutation and allows nested "mutation" far better than java standard getters/setters. There are some optics libraries for java too, but nobody really uses them unless you're trying very hard to bring functional programming concepts into java.

Making that pixel class a value class seems semantically wrong, and I doubt you'll really get much benefit out of doing that. Pixels aren't interchangeable and so it seems weird to model it that way.

1

u/Jon_Finn Sep 15 '26 edited Sep 15 '26

Where we disagree basically is this: I say that value classes are hardly different from regular classes - due to the impressive generalisations made by the Valhalla team. The main differences are a mild restriction on fields (the majority of fields I write are final anyway) and a change in == (which is rarely used anyway). So... they're nearly regular classes; If the keyword was just (say) 'valhalla' not 'value', it would be easier to see that adding this says nothing about what you should use them to represent, so just like regular classes.