Goetzが2020年2月にアップデートする前のエントリを基にしています。アップデート後のエントリは以下からご覧頂けます。Modelhttps://logico-jp.io/2020/02/27/state-of-valhalla-section-2-language-model/原文はこちら。翻訳いただき、転載の許可をいただきました。ありがとうございます!このドキュメントでは、インライン型を組み込むための言語モデルについて説明します。別のドキュメントで、インライン型のJVMモデル、およびJavaソースコードからJavaクラスファイルへの変換戦略について説明します(このドキュメントでは、インライン型を使わない現在の言語を“currently”(現在)と表現することにします)。現在、型はプリミティブ型と参照型に分けられています。8個の組み込みプリミティブ型(voidは型ではありません)があります。参照型は、プリミティブ型ではないもので、これには、クラスまたはインターフェイスとして宣言された型だけでなく、配列型(String[]、int[])および参照型のパラメーター化(List<String>、List<?>)といった非宣言型があります。参照型とプリミティブ型は、考えられるほとんどすべての点で異なります。参照型にはメンバー(メソッドとフィールド)とスーパータイプ(スーパークラスとインターフェイス)があり、すべて(直接的または間接的に)Objectを拡張したものです。プリミティブ型にはメンバーがなく、型システムにおいて島のように孤立した存在であり、スーパータイプやサブタイプはありません。プリミティブ型を参照型に接続するために、各プリミティブ型はラッパー型に関連付けられています(Integerはintのラッパー型です)。ラッパー型は参照型であるため、メンバーを持つことができ、サブタイピングに参加できます。プリミティブ型とそれに対応するラッパー型の間では、ボクシングとアンボクシングの変換があります。world値集合すべての型には値集合があります。これは、その型の変数に格納できる値のセットです(例えば、プリミティブ型intの値集合は32ビット整数の集合です)。記述して、Tという型の値集合を記述します。オブジェクトはクラスのインスタンスです。現在、すべてのオブジェクトには一意のオブジェクトアイデンティティがあります。参照型の値集合はオブジェクトではなく、オブジェクトへの参照で構成されます。String型の変数が取り得る値は、Stringオブジェクト自体ではなく、Stringオブジェクトへの参照です。経験豊富なJava開発者にとってさえも、オブジェクトを直接保存、操作、またはアクセスできないことは驚きかもしれません。オブジェクト参照を扱うことに慣れているので、違いに気付かないことさえあります。実際、これはJavaオブジェクトが値渡しか参照渡しかという一般的な「落とし穴」の質問であり、答えは「どちらでもない」です。オブジェクト参照は値で渡されます。プリミティブ型の値集合は、プリミティブ値で構成されます(nullは含まれません)。参照型の値集合は、オブジェクトインスタンスへの参照、またはnullで構成されます。前段の重要な事実(すべてのオブジェクトには一意のIDがあり、オブジェクトを操作する唯一の方法は参照を介すること)は、インライン型を取り込むと変わります。Javaプログラムの変数に格納できる値を強調表示するために、下図で表現可能な値を赤いボックスで示します。world現時点では、値はプリミティブ値とオブジェクトへの参照で構成されています。現在の状況をまとめると以下の通りです。型は、プリミティブ型と参照型に分かれている。参照型はプリミティブ型とは異なり、宣言されたクラス、宣言されたインターフェイス、および配列型を含む。プリミティブ型には対応する参照型のラッパー型がある。プリミティブ型と対応するラッパー型の間でボクシングとアンボクシングの変換がある。プリミティブ型の値集合にnullは含まない。参照型の値集合はオブジェクトではなく、オブジェクトへの参照で構成され、常にnullが含まれる。オブジェクトにはオブジェクトアイデンティティがある。インラインクラスお膳立てが出来たので、ようやくJava言語の型システムでインラインクラスへの対処方法に取り組むことができます。インラインクラスのモットーは次のとおりです。クラスのようなコードintのように機能このモットーの後半部分は、インライン型がこれまでに概説したプリミティブ型の動作と整合する必要があることを意味します(実際、インライン型の傘下にプリミティブ型を含めたいと考えています。2つに分かれている型システムを細分化するのは望ましくないからです)。インラインクラスはクラスのようにコーディングされるため、クラスが持ち得るほとんどのもの(フィールド、メソッド、コンストラクタ、スーパーインターフェース、型変数など)を持つことが出来ます。}}Valhallaがもたらす最初の大きな違いは、インラインクラスのインスタンス(これらをインラインオブジェクトと呼びます)にはオブジェクトアイデンティティがないことです。これは、同期のようなアイデンティティに依存する特定の操作がインラインオブジェクトでは許可されないことを意味します。混乱を避けるために、従来のクラスをアイデンティティクラスと呼び、そのインスタンスをアイデンティティオブジェクトと呼ぶことにします。インラインクラスのインスタンスはオブジェクトですが、アイデンティティはありません。オブジェクトアイデンティティによって、特に可変性とレイアウトのポリモーフィズムを実現します。(換言すると)アイデンティティを放棄することにより、インラインクラスは可変性やレイアウトのポリモーフィズムなどを放棄しなければなりません。したがって、インラインクラスは暗黙的にfinalであり、(インターフェイスは実装できるものの)Object以外の他のクラスを拡張することはできず、それらのフィールドは暗黙的にfinalです。オーバーライドできません)。Valhallaでは型をプリミティブ型と参照型に分割するのではなく、インライン型と参照型に分割します。インライン型にはプリミティブ型が含まれます。「参照型」の意味はこれまでと同じで、インライン型ではないものです(宣言されたアイデンティティクラス、宣言されたインターフェイス、配列型など)。型のダイアグラムを更新して、インライン型を含めたのが下図です。値集合がオブジェクトインスタンスへの参照(またはnull)で構成されているアイデンティティクラスとは異なり、インラインクラス型の値集合は、そのクラスでとり得るインスタンスの集合です(プリミティブ型と同様に、インラインクラスではnullは使えません)。今日のプリミティブ型と同様にインラインオブジェクトを直接表現します。この内容を値集合の図に反映しましょう。Valhallaプリミティブ型のように、インラインクラスの値集合は当該クラスのインスタンスの集合であり、オブジェクト参照ではありません。すべての型にはデフォルト値があります。フィールドの各々の型のデフォルト値Cというクラス型の場合、Cのデフォルト値をC.defaultと記載します(ジェネリックなコードでは、T.defaultと表現する場合があります。型消去されたジェネリクスの場合、Tは常に参照型であるため、これはnullと評価されます。ジェネリクスが特殊化されると、T.defaultも特殊化されます)。新しいトップインターフェースコンパイル時と実行時にインラインクラスとアイデンティティクラスを区別するために、IdentityObjectとInlineObjectという一対の制約付きインターフェイスを導入します。インラインクラスでは、InlineObjectを暗黙のうちに実装しますが、アイデンティティクラススでは、IdentityObjectを暗黙のうちに実装します(両方を実装しようとするとエラーになります)。これにより、アイデンティティに依存する操作を実行する前にオブジェクトのアイデンティティを動的にテストするコードを作成できます。}}さらに、型(およびジェネリックな型の境界)でのアイデンティティの要件を静的に反映します。現時点では、プリミティブ型ごとに==が定義されています。参照型の場合、両方がnullであるか、同じオブジェクトへの参照である場合に、2つの値は==です。現在、すべての参照はアイデンティティを持つオブジェクトを参照しているため、オブジェクトアイデンティティを使用して「同じオブジェクト」を定義できます。使い、==をインラインオブジェクトに拡張できます。具体的には、2つのインラインオブジェクトが同じ型で、フィールドの各々が当該フィールドの静的な型の==に従って両者が等しい(Float::equalsおよびDouble::equalsのセマンティクスに従って比較するfloatとdoubleを除く)場合に、両インラインオブジェクトは==です。この定義では、2つのインラインオブジェクトが置換可能である、つまり違いを識別できない場合にのみ等値であると言います。配列インターフェイスIを実装する任意の(インラインまたはアイデンティティ)クラスXの場合、Xの配列に対して以下のサブタイプの関係を保持します。現在、オブジェクトアイデンティティの観点から定義されている操作があり、これらの操作の中には、すべてのオブジェクトインスタンスをカバーするように適切に拡張できるものもあれば、部分的な拡張になるものもあります。Object上で==を全域化する。現在において意味がある場合に、この新しい定義はその意味と一致する(次章で説明するように、インラインオブジェクトへの参照に関して、ここで追加の作業を行う必要がある)。identityHashCodeの主な用途は、IdentityHashMapなどのデータ構造を==の前のフィルタとして実装すること等値性の場合と同様、identityHashCodeを全域化できる(すべてのフィールドのハッシュからハッシュを導出できる)。実行時に同期が失敗することを静的に検出できる場合(インラインクラスでの同期メソッドの宣言を含む)、コンパイルエラーを発行できる。ない場合、インラインインスタンスをロックしようとすると、実行時にIllegalMonitorStateExceptionが発生する。これを正当化できるのは、当該オブジェクトのロックプロトコルを明確に理解していない状態でオブジェクトをロックする(例えば、任意のオブジェクトまたはインターフェイスインスタンスのロック)ことは本質的に軽率なことだからである。どちらの方法も考えられる。Object上で弱参照作成の部分化もできるが、厄介な結果をもたらす。何らかの弱いデータ構造を維持したいすべてのクラスは、アイデンティティオブジェクトとインラインオブジェクトの別々のパスに分岐する必要があるため、弱参照はほとんど役に立たなくなる(これはidentityHashCodeの部分化に類似)。単純な動作(例えば、インラインオブジェクトが保持されている弱参照を決して消去しない)を選択すると、そもそも弱参照を使っているGCに適した振る舞いの一部が失われてしまう(この点ではさらなる分析が必要)。「プログラム可能」な部分は、インライン型がメンバとスーパータイプを持つことができるという点で、ギャップをある程度狭めていますが、私たちはこのギャップをさらに狭めたいと考えています。現時点では、ボクシング変換によってプリミティブ型から参照型に変換しています。この変換は、サブタイピングまたはボクシングのいずれかによって、任意の値をObjectで表すことができるため、より多様なコードを記述できて便利ですが、ボクシングには多くの深刻な欠点があります。ボクシングした結果の型はカスタマイズされた手作りのクラスであり、プリミティブ型との言語的なつながりは限られているため、インラインクラスに確実に対応しません。悪いことに、ボクシング後に生成されたオブジェクトには、多くのVM最適化を妨げる「偶発的な」オブジェクトアイデンティティがあります。「ボクシングは遅い」という信念は、この偶発的なアイデンティティに由来するものです。私たちがやりたいのは、インライン型の世界と参照型の世界を、アドホックでなく、実行時に軽量な方法で接続することです。ボクシングは死んだ、インライン展開よ栄えよインラインクラスの値集合はオブジェクトインスタンスで構成されていますが、アイデンティティクラスの値集合はオブジェクトインスタンスの参照で構成されています。この表現の違いが現在のプリミティブ型とオブジェクトの違いの重要な要因の一つです。インラインクラスを残りの型システムに接続し、インターフェースを実装したりObjectを拡張したりできるようにしますが、インターフェースI、Iを実装するアイデンティティクラスC、そしてIを実装するインラインクラスVがある場合、Iの値集合は何になるのでしょうか。明らかに、CとVの両方の値集合を含める必要がありますが、これらの値集合は構造的にまったく異なります。一方にはオブジェクトが含まれ、もう一方にはオブジェクトへの参照が含まれます。これは、橋渡しする必要があるオブジェクトとプリミティブの分断です。現時点では、この分断を不器用にボクシングで埋めているため、より統一した軽量な方法で橋渡しをしたいと考えています。インターフェース(とObject)は参照型、つまり値集合はオブジェクト参照で構成されている必要があります。Valhallaでは次の大きな違いがもたらされます。アイデンティティオブジェクトは参照を使ってのみ操作できるのに対し、インラインクラスは直接もしくはオブジェクト参照を使って操作ならびに保存できます。Valhallaのvalue(値)の世界はプリミティブ型の値、インラインオブジェクト、アイデンティティオブジェクトとインラインオブジェクトの両方への参照で構成されます。conversion(インライン拡大変換)を使って、インライン型から参照型に変換します。これはボクシングと似ていますが、変換の結果は(ボクシングのように)アイデンティティオブジェクトではなく、インラインオブジェクトへの参照(生成されたObjectでObject::getClassを呼び出すと、ボクシング結果の型ではなく、元のインラインオブジェクトのクラスが返されます)という、大きな違いがあります。これにより、VMの最適化能力を損なうことなく、インライン型と参照型の間で必要な相互運用が可能になります。インライン拡大変換を使うと、ボクシングによるパフォーマンス劣化がほとんどなく、所望のボクシングセマンティクスを得ることができます。vは、vがインラインオブジェクトの場合、vへの参照、vがオブジェクト参照である場合はv自体、として定義すると便利です。refは、すべての表現可能な値を総合したものであり、常に参照を返します(反対の意味である演算子unrefは部分的であり、インラインオブジェクトへの参照にのみ適用され、両者は射影と埋め込みのペアを形成します)。インライン拡大変換はインライン型から実装される任意のインターフェース、またはオブジェクトに存在し、ref演算子のアプリケーションとして定義されています。これにより、Iの値集合に関する疑問に回答できます。Cのすべてのインスタンスへの参照と、Vのすべてのインスタンスへの参照が含まれます。インターフェイス(およびObject)の値集合は、値nullと、オブジェクトへの参照で構成されます。このオブジェクトはアイデンティティオブジェクトまたはインラインオブジェクトのいずれかをとり得ます。インターフェースのインスタンスもしくはObjectのアイデンティティに依存する操作を実行すると、実行時に失敗する場合があります。置き換え、単に命名法でだまそうとしただけでは、と思われるかもしれません。やったことが名称変更だけなのであれば、確かにだましているだけでしょう。JVMでは、インライン展開および縮小変換が、対応するボクシングおよび案ボクシング変換よりもはるかに軽量だからです。ボクシングの問題は、アドホックであり、コストが大きいことです。これらの両方の懸念に対処しようとしています。projections)特定のインラインクラスのオブジェクトへの参照の集合に加えてnullを表現できると便利な場合があります。インライン型Vがある場合、以下のように値集合が指定される型Iが必要です。1個のインラインサブタイプのみを許可するsealedインターフェイスを使用して、参照射影を簡単に作成できます。}参照射影は、現在のラッパークラスが果たす役割を果たしますが、すべてのインラインクラスに手書きのアドホックなラッパーを持たせたくありません。インラインクラスから参照射影を機械的に導出し、それを参照するための統一された方法が必要です。維持する必要はありません。任意の型Tについて、T.refがTの参照射影を示すようにします。VはIのエイリアスです。Vがそのようなインターフェイスを1つだけ実装していない場合、合成インターフェイスが暗黙的に作成され、V.refはそのインターフェイスのエイリアスになります。Vのスーパーインターフェイスとパブリックメソッドが合成インターフェイス上に載せられます。参照射影はインラインクラスのスーパーインターフェイスであるため、VからV.refへのインライン拡大変換が既にあります。V.refからVへのインライン縮小変換を定義します。この変換は、unref演算子を適用します。nullの場合はNullPointerExceptionをスローします。この変換のペアでは、インラインクラスは、プリミティブ型が従来からラッパータイプで行っていた参照射影と同じ関係を持ちます。ボクシング変換(オートボクシング、条件の入力、オーバーロードの選択)の観点で定義されている既存のルールを簡単に拡張して、インライン展開および縮小変換を組み込むこともできます。その結果、既存のユーザーにとってこれらの変換は、新しい世界でも変わらないように感じられることでしょう。インライン展開では現在のように「偶発的な」アイデンティティを持つオブジェクトが作成されないため、ボクシングの実行コストはかかりません。参照型Rは、それ自体の参照射影になるためのすべての要件をすでに満たしているため、参照型Rの場合、R.refをR自体のエイリアスにします。これで、すべての型Tに、T.refで示される参照射影が確実に含まれるようになりました。インターフェース歴史的に、クラスがインターフェースを実装することにはいくつかの意味がありました。Conformanceクラスは、メンバーとして、インターフェースのすべてのメンバーを持つTransitivityこのクラスの任意のサブクラスもまたインターフェースを実装するSubtypingクラス型はインターフェース型のサブタイプこの最後の箇条書きのサブタイピングを、インラインクラスをサポートするよう少しずつ改良する必要があります。クラス型の参照射影は、インターフェイス型のサブタイプと言います(アイデンティティクラスの型は、それ自体の参照射影です)。オブジェクト全てのクラス、インラインとアイデンティティのルート型としての役割ゆえに、Objectは多くの特性をインターフェースと共有します。既述の通り、全てのインライン型からObjectへのインライン拡大変換があります。Objectは具象クラスなので、残念ながらObjectを直接コンストラクタを使ってインスタンス化できてしまいます。インターフェースを継承するため、ObjectはInlineObjectもIdentityObjectも実装できません。インスタンスを生成した場合、アイデンティティ型のインスタンスでなければなりません(他の理由でObjectのインスタンス化するポイントがないためです)。このtrapからうまく切り抜けるには手の込んだ動きが必要です。既存のソースおよびバイナリでの利用をこの方向に移行していき、最終的には(protectedにすることで)直接インスタンス化するためのObjectコンストラクタを非推奨にします。拡張はまだ終わっていません。インラインオブジェクト自体に対しては定義したものの、参照型の値集合でインラインオブジェクトへの参照を持つ可能性がある参照型に対してはまだなので、以下の条件を満たす場合に等値であるとします。2個のオブジェクト参照がともにnullである(または)両者とも同じアイデンティティオブジェクトへの参照である(または)両者が等値のインラインオブジェクトへの参照であるこれにより==の代入可能性のセマンティクスを全ての値に拡張します。NaNの従来の動作を除き、どのような方法でも両者を区別できない場合にのみ2値は==です。これにより、==に関する以下の有用な不変式を得ることができます(NaNの従来の動作を法とするすべて)。v2つのインライン値を参照に展開すると、初期値がそうであった場合にのみ、結果は==になる。2つの参照をインラインオブジェクトに縮小すると、元の参照があった場合にのみ、結果は==になる。Object::equalsの基本実装は、==への委任です。Object::equalsを明示的にオーバーライドしないインラインクラスの場合、これがデフォルトです(同様に、Object::hashCodeの基本実装はSystem::identityHashCodeに委任されるが、これもデフォルト)。参照射影の定義は理に適っており、参照型との関係についてのこれまでの直観と一致していますが、これらの型が非常に重要な理由をまだ完全に説明してきてはいません。以下のような場合にはインライン型を利用できません。Nullはインライン型の値ではないが、全ての参照型の値である。時として「型VのNullを許容する値」という概念を表現したいことがある。インライン型の値は定期的にオブジェクトと配列に平坦化され、通常これで問題ない。場合によっては、例えば、「幅の広い」インラインクラス(多くのフィールドを持つクラス)があり、それらの疎らな配列が必要な場合に、メモリ使用率をより細かく制御したい場合がある。平坦化された値の配列ではなく、参照の配列を使用すると、メモリ効率が向上する場合がある。インラインクラスは、再帰的に自分自身を表現できない。通常、これは重大な制限ではないが、(「next」フィールドを持つNodeクラスなど)参照型でこれをシミュレートしたくなることがある。既存の型消去ジェネリクスの場合、型パラメーターが参照型であることを前提としている。アイデンティティに依存する操作やnull値などを許容する。特殊化されたジェネリクスができるまで、参照型を型パラメーターとして使用したい。インライン型のデフォルト値は、すべてのフィールドがデフォルト値をとる値。Pointにとって問題ないデフォルト値)が、場合によっては(Rationalなど)、この値は無意味であるか、さらには危険な場合がある。この場合、nullを使用して初期化されていない値を表すことができるよう、参照型を使いたいことがある。これらの状況すべてにおいて、インライン型ではなく参照型を使用できます。Objectなどの幅広い参照型を使用すると、多くの損失が発生します。型の安全性が失われ、クライアントはコードに未チェックのキャストを挿入してインラインドメインに戻る必要があります。インライン展開・縮小変換を伴うインライン型の参照射影を使用することで、特定のインラインクラスの値集合と密に結合した値集合を持つ参照型を持ち、この参照型を明示的な変換を使わずにインラインクラスに戻すことが自由にできます。これにより、型安全と所望する利便性を取り戻します。例として、Mapインターフェースを特殊化されたインスタンス化をサポートするために移行するという問題を考えましょう。要求されたキーがmapにない場合、Map::getメソッドはnullを返しますが、MapのVパラメータがインライン型の場合、nullは値集合のメンバーではありません。get()メソッドを以下のように宣言することでこれを捕捉できます。key);この表現で、Map::getの戻り値の型がVへの参照もしくはnull参照のいずれかになるという概念を記録しています。移行これまでに議論したテクニックは新規のコードにとってはよいのですが、移行する場合には、準備しておきたいシナリオがいくつかあります。値ベースのクラス既存の値ベースのクラスがたくさんあり、これらはスムーズなインラインクラスへの移行を可能にするために設計された一連の制約を満足します。そのような例の1つにjava.util.Optionalがあります。8にインラインクラスがあれば、インラインクラスとして宣言していたでしょう。インラインクラスの実行時の利点を活用するために、Optionalをインラインクラスに移行します(java.util.timeパッケージのクラスも同様の状況にあります)。Classeshttps://docs.oracle.com/javase/8/docs/api/java/lang/doc-files/ValueBased.html既存のクライアントでは、変数の型、メソッドパラメータや戻り値の型、型パラメータなど、Optional型が多数使用されています。これらのクライアントはすべて、Optionalが参照型であると想定しており、参照型はnullを許容しますので、Optionalを直接インライン型に移行することはできません。次善の策は、Optionalをインラインクラス(privateクラスなど)の参照射影として定義することです。Optionalをインターフェイスに移行し(これを互換性のある移行にするために少しJVMに手を入れる必要があります)、インラインクラスを1つだけ許可するようにsealするように手配します。(実際に宣言されている方法に関係なく)T.refとの対称性のために、このインラインクラスはOptional.inlineと呼ばれます。この移行で、Optionalのインスタンスはアイデンティティクラスではなくインラインクラスになりますが、既存のコードは引き続き、参照を使ってOptionalの値を格納して渡します。した直接表現で実際に違いが出るのは、ヒープに出会う場所、つまりフィールドと配列要素です。ここでは、これらのOptionalの特定の用途をOptional.inlineに自由に段階的に移行できます。インライン展開・縮小変換ゆえに、フィールドまたは配列のOptionalからOptional.inlineへの変更は、ソース互換の変更になります。既存のAPIは、参照射影のOptionalを引き続き使用する可能性があります。このような移行から生じる可能性のある非互換モードが1つあります。それはクライアントがgetClass()の結果をM.classと比較する場合です。移行前の段階では、OptionalのインスタンスにはクラスOptional.classがありますが、Optionalをインターフェイスに移行すると、Optionalのインスタンスは、getClassで照会されたときに何らかの実装クラスを報告します。M.classの使用を取り巻くこの非互換性は、ここで概説する移行アプローチの主要な互換性コストですが、インターフェイスのクラスリテラルに対しgetClass()の結果を==で比較するときにコンパイル警告を発行することで多少緩和できます。これは実行時に失敗することがわかっているためです。プリミティブインライン型をプリミティブの抽象化という役割を与えましたが、実際にプリミティブをインライン型に包含できるようにするための作業が必要です。Optionalを移行するのと同じテクニックを使って、ラッパー型Integerとその仲間をインターフェースに移行することからはじめます(Numberでは追加のトリッキーなことがあって対処する必要があります)。これらのインターフェースはプリミティブの参照射影になるでしょうが、このためには、まずユーザーをプリミティブラッパーのアイデンティティへの依存から引き離す必要があります。169を参照してください)。Objectshttp://openjdk.java.net/jeps/169この動きはプリミティブのラッパーのアイデンティティに依存するコードを壊すリスクがあります。代入可能性を持つ==の定義を考慮すれば、==を用いた比較はおそらく問題ないでしょうが、ラッパーをロックするコードは実行時に失敗するでしょう。これで、明示的にプリミティブ型をインラインクラスとして宣言できます。}明らかに、自己参照に対して調整が必要ではありますが、これでスーパーインターフェイスとインスタンスメソッドをintに追加し、一般的にクラスのように扱うことができるようになりました。参照射影int.refはIntegerのエイリアスになり、Integer.inlineはintのエイリアスになります。2つの型の関係は、移行された値ベースのクラスの場合と同じです。プリミティブが真のインライン型である場合、配列間で次のサブタイピング関係も持ちます。Object[]これで、intとIntegerの間で2つの変換が定義されました。既存のボクシング変換と、新しいインライン縮小および拡大変換、これらを調和する必要がありますが、便利なことに、ラッパークラスの偶発的なアイデンティティ(非推奨です)を除き、これらは同じセマンティクスを持つように定義してきました。ランタイムが定期的に最適化して除去するためにボクシングはより簡単になりますが、変換、オーバーロード選択、および推論を取り巻く既存のすべてのルールはそのまま維持されます。同様に、オーバーロード選択でのボクシングの役割を一般化して、代わりにインライン展開・縮小を使用できるため、この移行ではオーバーロード選択の決定は変更されません。特殊化されたジェネリクスジェネリクスは現在のところ、単一の参照に型消去されますが、最終的にはジェネリクスがその表現を特殊化できるようにして、ArrayList<Point>のようなジェネリック型が、Point[]が得ているような平坦性と密度のメリットを享受できるようにしたいのです。これには追加の時間がかかり、移行互換性の問題がさらに発生します。ArrayListを特殊化可能な型に移行した場合、既存のクラスファイルは引き続きArrayListへの型消去された参照だらけでしょうし、引き続き動作する必要があります。将来の機能として、特殊化されたジェネリクスの余地を残そうとしています。現在型消去されたジェネリクスは、参照型でのみ機能し続ける可能性があります。将来的には、List<int>やOptional<int>などの特殊化された型のための自然表記を予約したいと考えています。これを行うには、型消去されたジェネリクスでは、参照型のみが型引数として有効である必要があります。今日、Listと書きますが、これは、List<int.ref>およびList<Point.ref>に一般化されます。まとめこれまでのアプローチは既存のプリミティブと参照の分断の構造を維持しつつ、より規則的でパフォーマンスに優れたものにすることです。ボクシングはより安価になって影の奥に遠ざかり、「インライン」が「プリミティブ」の新しい言葉であり、プリミティブの集合は拡張可能です。「重いボクシングを使う参照とプリミティブ」から「軽いボクシングを使う参照とインライン」に移行してきましたが、両世界はほぼ同一構造のままです。コメントをキャンセルコメントを入力してください。以下に詳細を記入するか、アイコンをクリックしてログインしてください。アカウントを使ってコメントしています。アカウントを使ってコメントしています。新しいコメントがついたらメールで通知。Inside現在40人フォロワーがいます。購読管理このバーを折りたたむ%d人のブロガーが「いいね」をつけました。