Queries regarding value classes

Julian Waters tanksherman27 at gmail.com
Thu Mar 17 02:00:14 UTC 2022


Alternatively, something like

X x = new X(1);
x.a = 3;

could be valid while

final X x = new X(1);
x.a = 3;

would not?

best regards,
Julian

On Tue, Mar 15, 2022 at 11:12 AM Julian Waters <tanksherman27 at gmail.com>
wrote:

> So if I understand correctly, value objects are essentially the same as
> JEP-401's primitives but with nullability, and according to JEP-401,
> guarantee of atomic modification?
>
> "you are saying "change the a field of the object referred to by x to 3.""
>
> Regarding this earlier x.a = 3 example, if X was a good ol' identity
> object, x would then be a reference to the actual instance, and we'd simply
> follow the reference to where the actual object is stored and set a to 3.
> But if it was a value object, my understanding from your previous post is
> that it would be stored directly on the abstract (Ignoring HotSpot's actual
> complex implementation) stack to be operated on as a bunch of fields with
> no additional metadata other than the check for null. What's stopping us
> from then changing those fields directly? Like Quân Anh mentioned earlier,
> we would've effectively created a new object if we did do that, since a
> value object has no identity, but wouldn't we have technically changed the
> value of a after initialization? At the very least, I'd say it would be
> useful syntactic sugar to be able to do x.a on a value object instead of
> having to do new X(3); every time we wanted to change it, unless a is
> explicitly marked as final, without affecting == or related checks in any
> way, since (from what I know) value objects are compared by field with ==.
>
> Apologies for my lack of knowledge in this area, it still feels like I
> haven't really gotten a correct idea of what value types really are,
> especially compared to the true primitives of 401
>
> Thanks for the reply and have a great day!
>
> best regards,
> Julian
>
> On Tue, Mar 15, 2022 at 5:59 AM Brian Goetz <brian.goetz at oracle.com>
> wrote:
>
>> You are (understandably) conflating the properties of identity with the
>> properties of reference-ness.
>>
>> If you say
>>
>>     x.a = 3
>>
>> you are saying "change the a field of the object referred to by x to 3."
>> The key to this sentence is *the object*; in order for assignment to make
>> sense, you have to know exactly which variable you are talking about.  And
>> if that variable is an instance field, then you have to know exactly which
>> object it lives in.  This is where identity comes in; if x is a reference
>> to an identity object, we then know how to find it.  Which means, you need
>> an identity in order to be able to talk about mutability in a well-defined
>> way.
>>
>> So if that's true, what is a *reference* to a value?  This is the
>> confusing part.  If you think in terms of implementation, you'll probably
>> think "reference means pointer", which puts you into a C frame of mind,
>> because pointers always point at things.  But that's not what reference
>> means in Java; its a more abstract kind of indirection.
>>
>> The distinction between int and Integer may be helpful.  At one level,
>> int and Integer may seem like "almost the same sets of values"; the Integer
>> value set has one more value -- null -- than the int value set, and for
>> each of the other values, there is a bidirectional, 1:1 mapping between the
>> two value sets.  But if we look closer, in fact these value sets are
>> disjoint!  An int is not an Integer (even if they describe the same
>> number.)
>>
>> So one big difference between references and values is nullability; null
>> is a special kind of reference, the reference to no object at all.
>> Reference types can be null; primitive types cannot.  (There's another,
>> even more subtle distinction, which is tearability, which comes from the
>> guarantees of the Java memory model.)
>>
>> If we have a value class:
>>
>>     value class X { }
>>
>> this gives rise to a reference type X, whose values are references to
>> instances of X.  But those instances do not have identity, which means we
>> can freely shred an X into the values of its fields, and later reconstitute
>> it into a new X, all without anyone noticing.  That's what the lack of
>> identity enables.  But the flip side of that means that any given X does
>> not "live" anywhere; it is just a loose aggregation field values, which
>> behaves like an object when called upon to do object-y things.
>>
>>
>>
>>
>>
>> On 3/13/2022 5:46 AM, Julian Waters wrote:
>>
>> Hi Quân Anh, thanks for the reply,
>>
>> I think I understand what you mean; Since value objects have no identity,
>> changing their fields would essentially mean the object is now entirely
>> different. However since that's the case, I'm still a little confused by
>> the semantics of what they really are. Specifically, most of their benefits
>> are centered around them being nothing more than their fields in memory,
>> but at the same time documentation states that they're referred to by
>> reference, which I find a little contradictory. If it's the former, they'd
>> be no different from primitives, and if the latter, they'd be the exact
>> same as identity objects, which has left me puzzled for quite some time.
>>
>> Sorry for all the trouble, have a great day
>>
>> best regards,
>> Julian
>>
>> On Sun, Mar 13, 2022 at 4:26 PM Quân Anh Mai <anhmdq at gmail.com> <anhmdq at gmail.com> wrote:
>>
>>
>> Hi,
>>
>> Regarding your concern of mutable value objects, having a mutable
>> identity-less object is illogical. Because a value class does not have a
>> unique identity, upon modification, the object is changed to become another
>> object. A value object is immutable in the same way that an int is
>> immutable. You can change a variable int a from containing a value of 3
>> to a value of 4, but you can’t change the number itself, it has been
>> mathematically and programmatically defined to be a specific bit sequence.
>> Similarly, you can change a variable Point a from enclosing the point (3,
>> 4) into the point (2, 5), but you can’t change the coordination of the
>> points themselves, they have been (in this case) also mathematically
>> defined. Your understanding of how value classes work is also not correct.
>> The fact that a value object can be deconstructed to its fields does not
>> mean that it will. This is simply an optimisation choice of the compiler.
>>
>> Regards,
>> Quan Anh
>>
>> On Sun, 13 Mar 2022 at 15:42, Julian Waters <tanksherman27 at gmail.com> <tanksherman27 at gmail.com>
>> wrote:
>>
>>
>> Hi all,
>>
>> I'd like to discuss several topics related to the current draft on value
>> classes.
>>
>> As mentioned in another post to this list at
>> https://mail.openjdk.java.net/pipermail/valhalla-dev/2022-January/009871.html
>> ,
>> currently value classes are specified as immutable, with all fields being
>> declared as final. If I understand this correctly, value based classes,
>> unlike the true primitives which work is currently focused on, can still
>> be
>> referred to by references; It is only identity that has been given up. In
>> that instance, naively speaking, wouldn't it be possible for value objects
>> to have mutable fields? In the same way that one can reference the fields,
>> one might possibly be able to also change their values through the
>> available object reference as well. From what I can tell, value objects
>> are
>> planned to work internally by decomposing them to nothing more than their
>> constituent fields and reconstructing them elsewhere. If that is the case,
>> shouldn't modification of their fields be possible? To me it seems the
>> modification would simply modify the copied value object *b *while leaving
>> original value object *a *unchanged, which sits perfectly with the
>> constraint that identity should not be supported. Am I mistaken in my
>> assumption?
>>
>> Additionally, if the above holds true, I also suggest allowing an object
>> to
>> be declared as value based at the site of their usage, instead of just at
>> their definition. Something like
>>
>> // Item is by default an identity class, but the field "item" here is now
>> // a value object due to the declaration of value
>> value Item item = new Item();
>>
>> would allow typical identity classes to be treated as value objects where
>> they're used. This would, to me, present a great deal of flexibility as
>> one
>> could then choose how to allocate a particular object without
>> constraining *every
>> *instance of that class to a specific value/identity dichotomy, and also
>> avoids the hassle of having to know which classes should be value or
>> identity types ahead of time. On a side note, the current proposal also
>> includes the ability to mark records as value based, given that records
>> are
>> meant exclusively as data classes, I suggest we flip that around and
>> instead have records as *value based by default, *and instead allow
>> marking
>> them as identity objects explicitly if required, with the currently used
>> ref keyword (Or whatever ref will eventually become), both at definition
>> and when an actual instance is constructed, as mentioned above. This could
>> save frustration from having to type value over and over whenever writing
>> the definition of a new record.
>>
>> Have a great day, hope I can hear your opinions on this! :)
>>
>> best regards,
>> Julian
>>
>>
>>
>>



More information about the valhalla-dev mailing list