
The Current State of Java Value Types - pjmlp
https://www.infoq.com/news/2018/06/JavaValuesJun18
======
bluejekyll
The thing I realized, that may not be obvious, is that this allows for a
“real” Optional type in Java, where the Option itself can not be null. This
will allow us to remove bare null usage from existing and future Java
codebases, without the annoyance of checking if the Option itself is null.

I hope that there will be a compiler flag at some point to enable a warning or
compiler failure on any bare null usage.

~~~
pjmlp
That is the plan.

In a few of Java Language Summit talks, they mention about such cases.

~~~
he0001
How does that work in the case of fex Map<String,Optional<String>>?

~~~
pjmlp
In the new world of Java value types, generics will support specialization for
them.

"Adventures in Parametric Polymorphism" from Brian Goetz at JVM Language
Summit 2016.

[http://www.oracle.com/technetwork/java/javase/community/jlss...](http://www.oracle.com/technetwork/java/javase/community/jlssessions-2016-3114175.html)

------
pdpi
One thing with the current proposal that I haven't quite figured out is that
it seems to me that the decision of whether a certain type is an "object" or a
"value" is pushed to the use site rather than definition site, so the same
type can be used as both object and value at different sites — in a way that
doesn't quite match the intuition for boxed types in, say, C++.

~~~
kodablah
I believe this is because of compatibility concerns when types migrate from
object to value or vice-versa. The linked doc[0] says "operations can differ
between value and reference types [...] This means that, if we are to support
migration, we need a way for legacy classfiles to make a local decision to
treat a given type as a reference type".

It is agreed in general that whether something is a value type is a
definition-side attribute. However if code was compiled expecting the Optional
value (e.g. does an ==) but it is now an Optional object, what happens? The
identity check is different than the value-equals one. The doc goes into more
detail on some differing things here.

I haven't studied the arguments or read the doc fully, but I'd say if you make
it where it can only migrate one direction, object types to value types, you
can solve the two big issues of equality (equals() is intercepted by the JVM
for value types to imply ==) and nullability (value is never null, == null
becomes always false). There may be other issues with hashCode, use as mutex
in synchronized block, etc.

Maybe another approach is to have the value type implement "ObjectLike" if it
wants to exist in the L-world. There needs to be a separation between what an
"object type" is and what an "object type" can do. The latter causes migration
concerns, the former is just about state and copying/reference semantics.

0 - [http://cr.openjdk.java.net/~jrose/values/value-type-
hygiene....](http://cr.openjdk.java.net/~jrose/values/value-type-hygiene.html)

~~~
xenadu02
Are they going for the C# model of automatic boxing of value types?

------
himom
Ever since the JDK 1.0 days, I didn’t get why there was this C/C++ carry-over
inconsistency of manually-boxed types and non-Objects primitive types
separated from Objects. A type hierarchy, patterned similar to Ruby’s as an
example, makes the most sense:

\- Object contains a Class that it derrives from (no BaseObject or Modules)

\- Class is an Object

\- String is an Object

\- Boolean is a two-value singleton of true and false

\- Number is an abstract subclass of Object

\- Decimal and Integer are abstract subclasses of Number

\- Float, Double, LongDouble, BigDecimal are concrete subclasses of Decimal

\- SignedByte, Byte, Short, UnsignedShort, Int, Unsigned, Long, UnsignedLong,
Char, BigInt are concrete subclasses of Integer (or U/I/F## types reminiscent
of Rust instead of C type names)

and so on.

Then there is no boxing/unboxing of simple types or literals because they are
one-and-the-same, and no there’s no confusion about how to interact with any
truly generic type of value.

~~~
MaxBarraclough
I've heard theorists say exactly this a number of times before.

The reason Java isn't a 'pure' object-oriented language is simply performance.

Suppose everything - even every int - is heap-allocated. You now need a very
sophisticated JIT compiler (as in, better than any we have today), or it's
going to run dog slow. Having a huge number of needless allocations happening
at every step is going to:

1\. Slow things down by doing vastly more heap allocations that you otherwise
would (even with Java's ultra-fast allocations)

2\. Slow things down by doing violence to your code's locality and cache
behaviour, because your ints no longer live in the stack

3\. Slow things down by doing violence to your code's locality and cache
behaviour, because Java objects are bloated compare to raw ints

4\. Slow things down by hugely increasing garbage-collection pressure

If Gosling had taken that route, we wouldn't be talking about Java today.

~~~
marcosdumay
Languages do not need a 1 to 1 relationship between the storage medium of a
value and the interface it exposes to a programmer.

Java's situation is even worse because it's a compiled language that does not
need a JIT or even much sophistication from a compiler to keep a single
hierarchy on its type system.

I suspect the reason Java did it was to not surprise C++ programmers. Solely
dictated by marketing, not by technical reasons.

~~~
kjeetgill
> Languages do not need a 1 to 1 relationship between the storage medium of a
> value and the interface it exposes to a programmer. ... I suspect the reason
> Java did it was to not surprise C++ programmers. Solely dictated by
> marketing, not by technical reasons.

The situation is almost the opposite of what you described it. If anything one
of the major design points was to _solve_ the surprises inherent to C/C++.

Take integers for example. In java they're defined to be 2s compliment; the
processor architecture doesn't matter. C/C++ left the spec open to let the
language be 1 to 1 with the medium, Java did not.

You can see the proposals to close this headache: [http://www.open-
std.org/jtc1/sc22/wg21/docs/papers/2018/p090...](http://www.open-
std.org/jtc1/sc22/wg21/docs/papers/2018/p0907r0.html) [http://www.open-
std.org/jtc1/sc22/wg14/www/docs/n2218.htm](http://www.open-
std.org/jtc1/sc22/wg14/www/docs/n2218.htm)

This is similar to all the issues with how threads interact with memory. Java
lend the way in making the memory model a part of the language specification
rather than allow it to be implementation (and architecture) defined.

[http://www.theregister.co.uk/2011/06/11/herb_sutter_next_c_p...](http://www.theregister.co.uk/2011/06/11/herb_sutter_next_c_plus_plus?page=2)

~~~
MaxBarraclough
> If anything one of the major design points was to solve the surprises
> inherent to C/C++.

Sure, but you're speaking past each other.

* Java was designed to be more predictable and have fewer dark corners than C++ (no undefined behaviour, precisely defined primitives and generally far less platform-specific behaviour, etc)

* Java was designed to feel familiar to C++ developers in order to aid adoption (specifically its syntax)

These aren't in contradiction.

------
diebir
My personal ask for the language designers is somewhat similar, but not quite
this (it seems). I'd like to have either the language support for builders or
setters where after creation an object becomes immutable.

The options we have right now are bad: the long constructor arguments are too
verbose, the setters are causing non-immutability and builders are worst due
to lack of discoverability and standards.

~~~
jdmichal
That sounds like a need for named and default constructor parameters. With the
two of those, you can mix-and-match whatever values you want, with non-
defaulted ones being required. And since the parameters are named, they self-
document at the usage site.

