ProgrammingKotlin開発者 / パフォーマンスエンジニア

Kotlinにおけるインラインプロパティアクセサ(インラインゲッターとセッター)はどのように機能しますか?使用時の特性や微妙な点は何ですか?パフォーマンスにどのように影響し、予期しないエラーが発生する可能性がある場所はどこですか?例を示してください。

Hintsage AIアシスタントで面接を突破

答え

Kotlinでは、プロパティのゲッターとセッターにinline修飾子を付けることができます。これにより、コンパイラはアクセサのコードを呼び出し元に直接インライン化(埋め込む)する権利を持ち、パフォーマンスを最適化します。

例:

val foo: Int inline get() = expensiveCalculation()
  • インライン化により、ゲッター関数は呼び出し時のオーバーヘッド(例えば、ループ内で)を発生させません。アクセサのコードが短い場合です。
  • インラインは、ステートレスなゲッターのみに可能です。すべてのロジックがインライン化できるわけではありません。
  • reifiedジェネリックパラメータやクロスリンクされたラムダ式が含まれている場合、set/getアクセサにinlineを使用することはできません。

ベストプラクティス: 副作用のない非常に短く頻繁に呼び出される式のためにのみインラインアクセサを使用します。


トリックな質問

インラインゲッター/セッターを持つプロパティにリフレクションのアノテーションを追加した場合(例えば、KPropertyを通じて使用する場合)、インラインは機能しますか?

答え: いいえ。プロパティがリフレクションAPIを通じて使用される場合やKPropertyを参照する場合、コンパイラはゲッター/セッターをインライン化できず、通常のメソッドとして残ります。インラインは、コード内での直接の呼び出し時にのみ発生します。


歴史

インラインゲッターによるリフレクションの影響によるパフォーマンスの損失:

ホットプロパティをインラインゲッターに書き換えて余分な呼び出しを排除しようとしました。その後、KPropertyを通じてバリデーションを追加した結果、呼び出しがリフレクションを通じて行われるようになり、インラインアクセサの利点が完全に無効になりました。


歴史

インライン化による望ましくない副作用:

インラインゲッターがロギングを行っていました:

inline get() { println("accessed!") return field }

この実装は、プロパティがコードの異なる部分で頻繁に読み取られるときに、多くの場所で予期しないロギングを引き起こし、ログが大きく乱雑になりました。


歴史

インラインプロパティの変更によるABIの破損:

ライブラリ内のインラインゲッターのロジックを変更したが、依存モジュールを再コンパイルせず、クライアントは古いシグネチャを使用し続けました。拡張ABIとインラインによる不整合と、クライアントの更新時の隠れたクラッシュが発生しました。