Abstractly, my conception of “object” is that it is a bundle of type state, 
identity (optionally), and zero or more fields.  I think this most closely 
corresponds to Kevin’s notion of “compound value”, though it might only have 
zero or one fields — but since there is type state and potentially identity, it 
is still a composite.  Historically we touched objects only through references, 
and we can still do so for all objects, but we now have the ability that a 
variable can store some objects directly.

How we choose to see the formerly-primitive types is mostly a matter of 
choosing which fiction we prefer.  At the VM level, we have I/J/F/D carriers, 
which are definitely some sort of primitive value.  At the language level, we 
can tell ourselves that `int` is an identity-free direct instance of class 
Integer, if we like (though we still have to cut off the turtle-regress when 
declaring Integer.java.).


I think some of us would like to reserve the term “object” for something that 
has a header and a storage block in the heap.

I’m not in that camp.  The header and storage block is how we reassociate type 
state with a (non-flattened) object *reference*.  But a field of type C.val 
stores its typestate “statically”, in the field descriptor.  (Theoretically, a 
field of type C.ref could too, though we don’t currently make that 
optimization.). But these are all just implementation options a JVM has.

In the most idealized version of this world, values are either “bare objects” 
(bag of type state and fields) or references to objects.  In the slightly less 
idealized version, we would call out the legacy primitives as distinguished 
bare values.


On Jul 13, 2022, at 4:54 PM, John Rose 
<[email protected]<mailto:[email protected]>> wrote:


On 13 Jul 2022, at 13:23, John Rose wrote:

…Another result of backing away from “primitive” is that we have to engage with 
the question of “where are the objects?” Obviously every non-null value of a 
variable whose type is an identity class refers to “an object”. But beyond that 
it gets dicey and we will have to adjust our agreements, I think. This is 
probably worth a separate thread, which I will start, and which I expect Kevin 
will be very interested in.

A class defines ways to “realize” the class in its types, that is, in variables 
of its companion types.

Examples: C r = new C(); and C.val v = C.default; and new C.val[1].

(For class declared non-atomic, races can also “realize” values of the class.)

I’m using a more neutral term “realize” instead of “instantiate”. You can think 
“instantiate” or “construct” if you like. A long-winded way to say “realize a 
class” without tripping over words I want to avoid is “make a non-null runtime 
configuration of a variable of a type of that class, using, directly or 
indirectly, an expression allowed by the declaration of that class”.

These propositions seem to be all true (“at least” in part):

  *   The result of realizing at least some classes in some types is, in fact, 
an “object”.
  *   The result of realizing at least some classes in some types is, in fact, 
an “instance” of that class.
  *   The result of realizing at least some classes in a value type is a 
“value” of that class.
  *   Every variable “has a value”.
  *   Every reference, other than null, “refers to an object”.
  *   Every non-reference variable “contains a value” (as well as having it).

So, do we think they are true? And of which classes, and for which of their 
companion types, are they true?

I think some of us would like to reserve the term “object” for something that 
has a header and a storage block in the heap. Although talking about memory 
blocks and headers and machine pointers is probably illegitimate for a JVMS, it 
is semi-transparent enough to “see” that stuff like that is going on. (Except 
when it isn’t: Both Valhalla flattened references and classic escape analysis 
break those intuitions.) Users will want something to visualize about objects, 
and maybe that just doesn’t jibe with how we want them to think about values.

OTOH, it is really freeing to be able to say that “every class makes objects”, 
and build from there into a world of “identity objects” and “value objects”.

(I can also appeal to various C standards, in which everything is either an 
object or a function. Yes, a C int is a C object. Take that, Mr. 
Objects-Are-Everywhere Java. That might work for us too with minor adjustments.)

Even if we give up on making everything an object, I will still request that we 
cling to some word that can uniformly be applied to the result of realizing any 
Java class. If that word is not “object” I think it is “instance”.

Also I think it is still useful to at least pretend (virtually) that a 
reference is always to an object. So, something like this:

  *   The result of realizing any class in its reference companion is an object 
of that class.

  *   The result of realizing any class into any of its companion types is an 
instance of that class.

  *   The result of realizing any value class into its value companion is a 
“value” of that class.

  *   Maybe also: The result of realizing any value class into its reference 
companion is a “value” of that class (as well a an “object” of that class).

  *   Every variable “has a value”. (Same as above.)

  *   Every reference, other than null, “refers to an object”. (Same as above.)

  *   Every non-reference variable “contains a primitive” or “contains an 
instance”.

  *   Any value is (therefore) either a primitive, an instance, a null 
reference, or a reference to an object.

  *   An object (therefore) is an instance or an array. (Cribbing from Kevin 
here.)

  *   By an abuse of language, it is common to ignore the reference part of a 
reference variable, and say that it “has” or “contains” an instance if not 
null. (This makes opportunities for consistent reasoning about C.ref and C.val 
variables.)

Get those spray-paints shaking! Bonus points if we finish before Brian gets 
back from his vacation, he’ll be so pleased!

Reply via email to