Can null be assigned to or be compared to a value type variable?
Asked Answered
R

3

5

In Java, there have always existed primitive types and references, but not value types.

One of the goals of Project Valhalla is to explore and incubate feature candidates such as value types.

I would like to know if null can be assigned to a value type variable, or if a value type variable can be compared to null.

If not, I would also like to know why.

Reversible answered 8/2, 2018 at 21:14 Comment(12)
null is a value of reference type. Inasmuch as the whole point of JEP-169 value types is that they are not reference types, no, null cannot be assigned as the value of such a type. At least, not without specifically attributing special-case significance to such an assignment.Discoverer
@JohnBollinger Intuitively, null means nothing, so a value type representing nothing is conceivable. I know that the traditional meaning of null is a reference that points to nowhere. Do you know if the sentence null is a value of reference type (or a similar one) is somewhere in the JLS?Reversible
Yes, Federico, albeit not in exactly the words I used: "The null type has one value, the null reference, represented by the null literal null" (JLS9, 3.10.7; formatted as in the original).Discoverer
Hey @JohnBollinger , thank you very much for that referenceReversible
See also comments about the null type and null reference in JLS9 section 4.1.Discoverer
Afaik this is the latest draft for the prototype: mail.openjdk.java.net/pipermail/valhalla-dev/2017-December/… and it does have "not nullable" for value types.Peachy
@JornVernee Thanks for that brainstorming transcriptionReversible
what a good question! @JornVernee that very much sounds like an answer, I doubt that this part will be changed...Cimbri
@Cimbri It's not that good... I remember when I used to code in C (in a glorious past, ages ago), and assigning NULL to a struct variable didn't make any sense. Why would it mean anything different now? Anyways, I think that my real intention with this question is to know if a value type can represent an empty/zero/void/nothing value, and how to implement that behavior, i.e. a number could be 0, a string "", a location could be Greenwich, etcReversible
@Cimbri In C, I could do memset(myStructVar, 0, size) and that filled my value type with all its bits set to 0. In modern C there are other ways to do the same, i.e. struct MyStructType myStructVar = {0};. I believe this is what I want to know, i.e. if we'll have a general way to initialize value types to their default values in Java... Maybe I should post another question?Reversible
@FedericoPeraltaSchaffner I'll ask my wife about this code, she is waaay better in C than me. But that is my thought now too, what is a default value for a value type? Integer i; for example ?Cimbri
@Cimbri Here's the question, properly written this time: https://mcmap.net/q/2032845/-how-to-generically-initialize-a-value-type-with-its-default-value/1876620Reversible
V
5

From here: https://wiki.openjdk.java.net/display/valhalla/Minimal+Value+Types

Value types are "immutable, identity-agnostic, non-nullable, non-synchronizable, final"

So no, it can't be null

Vaporish answered 8/2, 2018 at 21:18 Comment(0)
K
2

Value type variable is value, null is absense of any value. So null and value types are incompatible by definition.

Kalvn answered 9/2, 2018 at 4:53 Comment(1)
Yes, you are absolutely correct. I think I mixed up the terms in my question (indeed it's not a very good question). My intention was to ask about value types that represent nothing/zero/empty, i.e. the 0 number, the empty string, the person with no name, etc. In C, I remember I could do a memset(myStruct, 0, size)...Reversible
I
1

Yes!

This changed during the long development of Project Valhalla.

As of 2024, the value types proposal, JEP 401, which is probably now very close to the final form, has value types as nullable:

Value class types are reference types. In Java, any code that operates on an object is really operating on a reference to that object; member accesses must resolve the reference to locate the object (throwing an exception in the case of a null reference). Value objects are no different in this respect.

But why?

It's not ideal that value types are nullable, because it adds an extra possible state to the type representation, which both makes it harder to reason about the state of your data and means that even when a value field is "flattened" into another object at runtime, it still needs an extra bit to store whether or not the "reference" is null. The VM work is truly complicated.

The reason it ended up like this, in short, is compatibility. There are many existing classes which are morally value types, like Integer, Long, Double, LocalDate, Optional, any number of little immutable data carriers out there. But three decades of Java existing code will already do things like Integer value = null;. Making value types non-nullable would have prevented the migration of these classes. My understanding is that early attempts at non-nullable value types ("primitive classes") also played havoc with generics and required a new complicated set of bytecodes and type descriptors to cope with the new types.

As it is, the model they've ended up with provides fantastic compatibility. Adding (or removing) the keyword value in front of a class or record is a mostly binary compatible change, meaning that code that uses the class can be compiled separately from the value class itself. You mostly don't need to know whether the class you're using is a value class or not. No new bytecodes, nor type descriptors, nor constant pool forms. Migration becomes easy. The proposed diffs to the language spec and VM spec are reassuringly small.

So what is a value class?

As best as I can explain it, a value class is a class whose instances are described purely by the values of their fields. Its fields are final, it has no synchronized lock/monitor (because that would need a hidden state variable), System.identityHashCode is computed based on its field values (because there is no hidden hash code field), and == compares instances of value classes by comparing the bit value of each field.

(You can still have .equals and == that differ. For example, if you make a value class with String fields, you should provide a .equals method to compare the Strings with .equals, whereas == would merely check if the fields point at the same String instance.)

The opposite of a value class is an identity class. An identity class is a classic Java class where each new instance lives somewhere distinct in memory, and == compares the memory address.

The slogan of Project Valhalla is "Codes like a class, works like an int". For example, imagine:

int a = 3, b = 3;

We don't have to ask "is this 3 the same 3 as the other 3?" The question doesn't make sense. There is only the value 3. There is no individual identity to "each" 3. So of course a == b must compare them as equal. It can't compare identity (the way it would with new Integer) because an int primitive doesn't have identity, it only has value.

So, given some value class:

value record Point(int x, int y) {}

it will be the case that:

new Point(3, 4) == new Point(3, 4) // true!!

Which is obviously absolutely impossible in the pre-Valhalla times. They are separately created instances, but totally indistinguishable. (You could pretend that all possible values of a value class pre-exist somewhere as singletons and new just gives the pointer to the cached instance.)

But null is, yes, still a possible value of the type:

Point pointless = null; // 👍

In the language model, value types are still nullable reference types, just not identity types.

What you get in exchange for giving up object identity is excellent performance. The early access releases warn not to use them for benchmarking, but I did, and I was ecstatic. When the VM knows it doesn't need to keep track of individual objects, it can aggressively shred them into naked fields passed around in CPU registers (plus a boolean for isItNull). It beats the hell out of escape analysis.

I wholeheartedly encourage everyone to watch the July 2024 talk by Brian Goetz: https://www.youtube.com/watch?v=IF9l8fYfSnI

Nullity control

A closely-connected part of Project Valhalla is exploring null-restricted types, in which Java types (value or not) can be decorated with ! or ? to specify whether or not they are nullable, at the point of use. For example, a variable of type String! ("string bang") is a reference to a String and is enforced non-null. Obviously, this will marry well with value types. So types int and Integer! will have exactly the same possible values and become essentially the same thing: non-null pure 32-bit integer. Meanwhile, int? would mean "nullable int".

The nullity control feature is frontier language development and still evolving.

Ingmar answered 7/11 at 18:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.