どう違うの?というと割と難しくて、パッと見は大きな違いを感じないかもしれません。
言語的な定義を言ってしまえば、 class宣言で identity class と宣言されていればそのインスタンスは Identity Objects ですし、value class と宣言されていればそのインスタンスは Value Objects です。でも、そんな説明では納得されないことでしょう。
Value Objects はメモリ上に直接展開可能なデータで、メモリレイアウトを効率化することができます。
int i = 12;
int iSize = i.SIZE;
double iAsDouble = i.doubleValue();
Supplier<String> iSupp = i::toString;
int 型変数に対して、あたかも普通の参照型のようにメソッド呼び出しをしているかのように記述することができます。これは、裏の仕組みとしてはラッパー型のIntegerの該当メソッドを呼ぶような仕組みを想定しているようですが、これにより言語の表面上はプリミティブ型も参照型も同じように扱えるように見えるのではないでしょうか。
Project Valhalla では既存のJavaとの互換性を維持する方針が示されています。この背景については Background: How We Got the Generics We Have という文章があります。これは2004年にリリースされたJava5のときに、いかにして互換性を保ちながらジェネリクスを導入したのか?ということについて書かれています。この文章はとてもエモいと私は思っていて、機会を改めて解説したいところですが、要点を超訳すると
'Foo!' refers to a non-null Foo, and 'Foo?' refers to a Foo or null
'Foo!' は nullではないFoo を参照し、'Foo?' は Foo または null を参照します。
Type variable types have nullness, too. Besides 'T!' and 'T?', there's also a "parametric" 'T*' that represents "whatever nullness is provided by the type argument".
型変数の型にも nullness があります。 「T!」のほかに および「T?」、「型引数によって提供される nullness が何であれ」を表す「パラメトリックな」「T*」もあります。
JEP 401 でもうひとつ触れられていることは non-atomic についてで、背景を説明するのが難しいのですが、端的に言えばマルチスレッド下で同時にValue型の値を作成するようなケースで、“Atomicity”(原子性/不可分性)を犠牲にしてパフォーマンスを出すオプションを用意しようというテーマです。本稿では深入りしません。
これがB2Cシステム(Business to Customerの略で企業と一般消費者の取引のこと)だと、ユーザーの反応を見て素早い対応をすることが強く求められるので、最初からある程度の「変更性」を備えたプロジェクト運用をしていないとユーザー満足度を高められない。日頃からの不断のリファクタリングによって「変更性」をキープし続ける必要がある。