Fight the Future

Java言語とJVM、そしてJavaエコシステム全般にまつわること

Value Typesもろもろ

以前Project ValhallaのL-World Value Typesのアーリーアクセスビルドを試しました。

www.sakatakoichi.com

今回もう少し触ってみます。

利用バージョン

$ 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はクラスを継承できないけれど、インタフェースは実装できるそうです。

試します。

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をどのように使うのか私はわかっていません。