クラスがSerializable
Java であるとはどういう意味ですか?または一般的に、そのことについて...
クラスがSerializable
Java であるとはどういう意味ですか?または一般的に、そのことについて...
回答:
シリアル化は、オブジェクトをメモリから一連のビットに永続化します。たとえば、ディスクに保存します。逆シリアル化はその逆です。ディスクからデータを読み取り、オブジェクトをハイドレート/作成します。
あなたの質問のコンテキストでは、クラスに実装されている場合、このクラスは異なるシリアライザによって自動的にシリアル化および逆シリアル化できるインターフェイスです。
ほとんどのユーザーはすでに答えを出していますが、アイデアを説明するためにそれを必要とする人のために例を追加したいと思います。
次のようなクラスの人がいるとします。
public class Person implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
public String firstName;
public String lastName;
public int age;
public String address;
public void play() {
System.out.println(String.format(
"If I win, send me the trophy to this address: %s", address));
}
@Override
public String toString() {
return String.format(".....Person......\nFirst Name = %s\nLast Name = %s", firstName, lastName);
}
}
次に、次のようなオブジェクトを作成します。
Person william = new Person();
william.firstName = "William";
william.lastName = "Kinaan";
william.age = 26;
william.address = "Lisbon, Portugal";
そのオブジェクトを多数のストリームにシリアル化できます。これを2つのストリームに対して行います。
標準出力へのシリアル化:
public static void serializeToStandardOutput(Person person)
throws IOException {
OutputStream outStream = System.out;
ObjectOutputStream stdObjectOut = new ObjectOutputStream(outStream);
stdObjectOut.writeObject(person);
stdObjectOut.close();
outStream.close();
}
ファイルへのシリアライズ:
public static void serializeToFile(Person person) throws IOException {
OutputStream outStream = new FileOutputStream("person.ser");
ObjectOutputStream fileObjectOut = new ObjectOutputStream(outStream);
fileObjectOut.writeObject(person);
fileObjectOut.close();
outStream.close();
}
次に:
ファイルから逆シリアル化:
public static void deserializeFromFile() throws IOException,
ClassNotFoundException {
InputStream inStream = new FileInputStream("person.ser");
ObjectInputStream fileObjectIn = new ObjectInputStream(inStream);
Person person = (Person) fileObjectIn.readObject();
System.out.println(person);
fileObjectIn.close();
inStream.close();
}
ここにシリアライゼーションの詳細な説明があります:(私のブログ)
シリアル化:
シリアル化は、オブジェクトの状態をシリアル化するプロセスであり、一連のバイトの形式で表され、格納されます。これはファイルに保存できます。ファイルからオブジェクトの状態を読み取って復元するプロセスは、逆シリアル化と呼ばれます。
シリアル化の必要性は何ですか?
現代のアーキテクチャでは、常にオブジェクトの状態を保存して取得する必要があります。たとえばHibernateでは、オブジェクトを保存するために、クラスをSerializableにする必要があります。これは、オブジェクトの状態がバイトの形式で保存されると、別のシステムに転送され、その状態から読み取ってクラスを取得できるということです。オブジェクトの状態は、データベース、別のjvm、または別のコンポーネントから取得できます。シリアル化の助けを借りて、オブジェクトの状態を取得できます。
コード例と説明:
まず、Itemクラスを見てみましょう。
public class Item implements Serializable{
/**
* This is the Serializable class
*/
private static final long serialVersionUID = 475918891428093041L;
private Long itemId;
private String itemName;
private transient Double itemCostPrice;
public Item(Long itemId, String itemName, Double itemCostPrice) {
super();
this.itemId = itemId;
this.itemName = itemName;
this.itemCostPrice = itemCostPrice;
}
public Long getItemId() {
return itemId;
}
@Override
public String toString() {
return "Item [itemId=" + itemId + ", itemName=" + itemName + ", itemCostPrice=" + itemCostPrice + "]";
}
public void setItemId(Long itemId) {
this.itemId = itemId;
}
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
public Double getItemCostPrice() {
return itemCostPrice;
}
public void setItemCostPrice(Double itemCostPrice) {
this.itemCostPrice = itemCostPrice;
}
}
上記のコードでは、ItemクラスがSerializableを実装していることがわかります。
これは、クラスをシリアル化できるようにするインターフェイスです。
これで、serialVersionUIDという変数がLong変数に初期化されていることがわかります。この数は、クラスの状態とクラス属性に基づいてコンパイラーによって計算されます。これは、jvmがファイルからオブジェクトの状態を読み取るときに、オブジェクトの状態を識別するのに役立つ番号です。
そのために、オラクルの公式ドキュメントをご覧ください。
シリアル化ランタイムは、シリアル化可能な各クラスに、serialVersionUIDと呼ばれるバージョン番号を関連付けます。これは、シリアル化されたオブジェクトの送信者と受信者が、そのオブジェクトに対して、シリアル化に関して互換性のあるクラスを読み込んだことを確認するために使用されます。レシーバーが、対応するセンダーのクラスとは異なるserialVersionUIDを持つオブジェクトのクラスをロードした場合は、逆シリアル化によりInvalidClassExceptionが発生します。直列化可能クラスは、静的、最終、およびlong型である必要がある「serialVersionUID」という名前のフィールドを宣言することにより、独自のserialVersionUIDを明示的に宣言できます。ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L; シリアライズ可能なクラスがserialVersionUIDを明示的に宣言していない場合、次に、直列化ランタイムは、Java(TM)オブジェクト直列化仕様で説明されているように、クラスのさまざまな側面に基づいて、そのクラスのデフォルトのserialVersionUID値を計算します。ただし、デフォルトのserialVersionUIDの計算は、コンパイラーの実装によって異なる可能性があるクラスの詳細に非常に敏感であり、逆シリアル化中に予期しないInvalidClassExceptionsが発生する可能性があるため、すべてのシリアル化可能なクラスで明示的にserialVersionUID値を宣言することを強くお勧めします。したがって、さまざまなJavaコンパイラーの実装間で一貫したserialVersionUID値を保証するには、直列化可能クラスが明示的なserialVersionUID値を宣言する必要があります。また、可能であれば、明示的なserialVersionUID宣言でプライベート修飾子を使用することを強くお勧めします。
あなたが気づいたら、私たちが使用した別のキーワードが一時的です。
フィールドがシリアル化可能でない場合は、一時的としてマークする必要があります。ここでは、itemCostPriceを一時的としてマークし、ファイルに書き込まないようにします。
次に、オブジェクトの状態をファイルに書き込んで、そこから読み取る方法を見てみましょう。
public class SerializationExample {
public static void main(String[] args){
serialize();
deserialize();
}
public static void serialize(){
Item item = new Item(1L,"Pen", 12.55);
System.out.println("Before Serialization" + item);
FileOutputStream fileOut;
try {
fileOut = new FileOutputStream("/tmp/item.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(item);
out.close();
fileOut.close();
System.out.println("Serialized data is saved in /tmp/item.ser");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void deserialize(){
Item item;
try {
FileInputStream fileIn = new FileInputStream("/tmp/item.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
item = (Item) in.readObject();
System.out.println("Serialized data is read from /tmp/item.ser");
System.out.println("After Deserialization" + item);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
上記では、オブジェクトのシリアライゼーションとデシリアライゼーションの例を見ることができます。
そのために2つのクラスを使用しました。オブジェクトをシリアル化するために、ObjectOutputStreamを使用しました。メソッドwriteObjectを使用して、ファイルにオブジェクトを書き込みました。
逆シリアル化では、ファイルからオブジェクトを読み取るObjectInputStreamを使用しました。readObjectを使用して、ファイルからオブジェクトデータを読み取ります。
上記のコードの出力は次のようになります。
Before SerializationItem [itemId=1, itemName=Pen, itemCostPrice=12.55]
Serialized data is saved in /tmp/item.ser
After DeserializationItem [itemId=1, itemName=Pen, itemCostPrice=null]
逆シリアル化されたオブジェクトのitemCostPriceは、書き込まれていないためnullであることに注意してください。
シリアル化では、オブジェクトの現在の状態をストリームに保存し、そのストリームから同等のオブジェクトを復元します。ストリームはオブジェクトのコンテナとして機能します
Serializableは、インターフェイスのように呼び出されますが、実行時にSerializationサブシステムへのフラグのように呼び出されます。このオブジェクトは保存できると書かれています。シリアル化可能なオブジェクトを除くすべてのObjectsインスタンス変数と、volatileとマークされているものは保存されます。
アプリケーションがオプションとして色を変更できると想像してください。その設定を外部に維持せずに、実行するたびに色を変更する必要があります。
シリアライゼーションは、オブジェクトとデータをファイルに保存または書き込む手法です。ObjectOutputStream
およびFileOutputStream
クラスを使用する。これらのクラスには、オブジェクトを永続化する特定のメソッドがあります。お気に入りwriteObject();
数字付きの明確な外植用。詳細はこちらをご覧ください
別の視点から提示する。シリアライゼーションは、「マーカーインターフェイス」と呼ばれる一種のインターフェイスです。マーカーインターフェイスは、メソッド宣言を含まないインターフェイスですが、インターフェイスを実装するクラスをいくつかのプロパティを持つものとして指定(または「マーク」)するだけです。多態性を理解していれば、これは非常に理にかなっています。Serializableマーカーインターフェイスの場合、引数がインターフェイスを実装していない場合、ObjectOutputStream.write(Object)メソッドは失敗します。これはJavaの潜在的な間違いです。ObjectOutputStream.write(Serializable)である可能性があります
強く推奨:詳細については、Joshua BlochによるEffective Javaの Item 37を読んでください。
シリアル化:オブジェクトの状態をファイル/ネットワークまたはどこかに書き込みます。(平均Javaオブジェクトサポートフォームからファイルサポートフォームまたはネットワークサポートフォーム)
逆シリアル化:ファイル/ネットワークまたはどこからでもオブジェクトの状態を読み取ります。(平均ファイル/ネットワークサポートフォームからJavaオブジェクトサポートフォームへ)
Serializable
:Serializability of a class is enabled by the class implementing the java.io.Serializable interface. Classes that do not implement this interface will not have any of their state serialized or deserialized. All subtypes of a serializable class are themselves serializable. The serialization interface has no methods or fields and serves only to identify the semantics of being serializable.