私は Java の ArrayList のソースを読んでいて、そのバッキング配列宣言に出くわしました:
private transient Object[] elementData;
なぜこれは一時的である必要があるのですか? このクラスをシリアル化できないのはなぜですか?
助けてくれてありがとう!
シリアル化できます。クラスはArrayList
、デフォルトのメカニズムを使用するのではなく、それ自体で処理を行います。標準のシリアル化メカニズムの一部である、そのクラスのメソッドwriteObject()
とメソッドを見てください。readObject()
ソースを見るとwriteObject()
、バッキングアレイが保存されていないことがわかります。代わりに、要素(null値を含む)を一度に1つずつsize()
制限までシリアル化します。これにより、アレイ、特にアレイの最後にある未使用のスロットをシリアル化するオーバーヘッドが回避されます。デシリアライズ時に、必要最小限のサイズの新しいバッキング配列がによって作成されreadObject()
ます。
なぜこれは一時的である必要があるのですか?
これは、デフォルトよりも優れたシリアル化の仕事をするカスタムreadObject
とメソッドを提供するためです。writeObject
具体的には、writeObjectメソッドは、要素のサイズとシーケンスのみを書き込みます。これにより、1)独自のヘッダーとオーバーヘッドがあり、2)通常はnull
sが埋め込まれているプライベート配列オブジェクトのシリアル化が回避されます。スペースの節約は重要です。
このクラスをシリアル化できないのはなぜですか?
ArrayList
クラス全体をシリアル化できます1。はObject[]
直接シリアル化することもできますが、transient
別の方法でシリアル化を実装するようにマークすることを選択しました。
1-実際、これは要素のランタイムタイプによって異なります。たとえば、ArrayList
含まれているThread
参照をシリアル化しようとすると、最初のnull以外の参照に対して実行時例外が発生します。
ArrayList
を実装Serializable
しているので、シリアル化できます。これが、プライベートバッキング配列がである理由です。すべてが'sとメソッドtransient
によって処理されるため、クラス内の他のデータと一緒にシリアル化されません。ArrayList
writeObject
readObject
明示的なシリアル化を実装しているためです。ArrayList#writeObjectを参照してください。
変数はシリアル化できません。
変数は冗長です。
リンク: http://onjava.com/pub/a/onjava/excerpt/JavaRMI_10/index.html?page=3