以前Project ValhallaのL-World Value Typesのアーリーアクセスビルドを試しました。
今回もう少し触ってみます。
利用バージョン
$ java -version openjdk version "11-lworldea" 2018-09-25 OpenJDK Runtime Environment 18.9 (build 11-lworldea+0-2018-07-30-1734349.david.simms.valhalla) OpenJDK 64-Bit Server VM 18.9 (build 11-lworldea+0-2018-07-30-1734349.david.simms.valhalla, mixed mode)
Value Typesと継承
Value Typesはクラスを継承できないけれど、インタフェースは実装できるそうです。
Threadとかをフィールドに持ったものを継承するとValueTypeにできないし、ValueTypeを継承してフィールドを追加するとサイズが変わってis-a関係にできないので、継承はできないことにしたんだと思う
— きしだൠ (@kis) 2018年8月7日
試します。
public class ClassA { } __ByValue class MyValue extends ClassA { private int id; MyValue() { this.id = -1; } MyValue(int id) { this.id = id; } }
$ javac MyValue.java MyValue.java:1: エラー: value type may not extend another value or class __ByValue class MyValue extends ClassA { ^ エラー1個
次にインタフェースを実装させます。インタフェースにメソッドも定義します。
interface InterfaceA { void test(); } __ByValue class MyValue implements InterfaceA { private int id; MyValue() { this.id = -1; } MyValue(int id) { this.id = id; } public void test() { } }
$ javac MyValue.java $
コンパイルできました。
Value Typesのネスト
Value TypeのフィールドにValue Typeを設定する、つまりValue Typesのネストはできるのか?
__ByValue public class MyValue2 { private MyValue v; }
$ javac MyValue2.java MyValue2.java:2: エラー: 変数vは、デフォルト・コンストラクタで初期化されていません private MyValue v; ^ エラー1個
ではコンストラクタで初期化します。
__ByValue public class MyValue2 { private MyValue v; MyValue2() { this.v = new MyValue(100); } }
$ javac MyValue2.java $
コンパイルできました。
コレクションにValue Typesは格納できるか
import java.util.*; public class Main { public static void main(String[] args) { MyValue v1 = new MyValue(); MyValue v2 = new MyValue(100); List<MyValue> list = new ArrayList<>(); list.add(v1); list.add(v2); } }
コンパイルエラーでした(この記事のJDKはバージョン11-lworldea+0です)。
$ javac Main.java Main.java:9: エラー: 予期しない型 List<MyValue> list = new ArrayList<>(); ^ 期待値: 参照 検出値: MyValue
これは、たとえばList<int>
と書いたときと同じエラーメッセージです。
Main.java:9: エラー: 予期しない型 List<int> list = new ArrayList<>(); ^ 期待値: 参照 検出値: int
Value Typesは参照ではない、という扱いのようです。
JDKのソースコード
IDEの検索程度で探してみました。
package javax.lang.model.element; ... public enum Modifier { ... /** * The modifier {@code __ByValue} * @since 1.11 */ VALUE, /** * The modifier {@code __Flattenable} * @since 1.11 */ FLATTENABLE, /** * The modifier {@code __NotFlattened} * @since 1.11 */ NOT_FLATTENED, /*snip*/ }
__ByValue
だけでなく、__Flattenable
と__NotFlattened
という修飾子も追加されています。フラットにできる、しないなのでValue Typesに関連するものでしょう。
jdk.compiler/com/sun/tools/javac/parser/JavacParser.class
case FLATTENABLE : checkSourceLevel(Feature.VALUE_TYPES); checkFlattenabilitySpecOk(token.pos); flag = Flags.FLATTENABLE; break; case NOTFLATTENED: checkSourceLevel(Feature.VALUE_TYPES); checkFlattenabilitySpecOk(token.pos); flag = Flags.NOT_FLATTENED; break;
想像通り、Value Typesでのものでしたが、__Flattenable
と__NotFlattened
をどのように使うのか私はわかっていません。