Java の Java.IO.NotSerializableException を修正
-
Java で
java.io.NotSerializableException
を再現する -
Java での
java.io.NotSerializableException
の原因 -
Java の
java.io.NotSerializableException
を修正
今日は、Javaでプログラムを書いているときにjava.io.NotSerializableException
を再現します。 また、このエラーが何を意味するのかを理解し、その原因と解決策を導きます。
Java で java.io.NotSerializableException
を再現する
コード例 (Student.java
ファイル):
package com.serializertest;
class Student {
private String studentId;
public String getId() {
return studentId;
}
public void setId(String id) {
this.studentId = id;
}
}
Student
クラスは、studentId
というメンバー変数を持つヘルパー クラスです。 また、学生の id
を取得および設定するための getId()
および setId()
というメンバー メソッドもあります。
サンプルコード (SerializerTest.java
ファイル):
package com.serializertest;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class SerializerTest {
public static void main(String[] args) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream("students.txt");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
Student student = new Student();
student.setId("0001");
objectOutputStream.writeObject(student);
objectOutputStream.close();
}
}
SerializerTest
は、main()
ドライバー メソッドを持つメイン クラスです。 main()
内で、ファイルを作成するために FileOutputStream
クラスのインスタンスを作成します。
同様に、ObjectOutputStream
クラスの別のインスタンスを作成します。
次に、Student
クラスのオブジェクトを作成し、文字列引数を渡してその setId()
メソッドを呼び出します。 次に、ObjectOutputStream
クラスのオブジェクトを使用して、オブジェクトをストリームに書き込みます。
そのために、writeObject()
メソッドを使用しています。
その後、close()
メソッドを使用してストリームを閉じ、プログラムを実行しますが、プログラムの出力コンソールに次の 例外
が表示されます。
Exception in thread "main" java.io.NotSerializableException: com.serializertest.Student
なぜ私たちはこれに直面しているのですか? エラーを理解して、以下の原因を見つけてみましょう。
Java での java.io.NotSerializableException
の原因
原因を見つけるには、NotSerializableException
と Serialization
を理解することが不可欠です。
シリアル化
は、オブジェクトの状態をバイト ストリームに書き込むために使用する Java プログラミングのメカニズムです。 これに対し、その逆の操作をデシリアライズ
と呼ぶ。
Serialization
と Deserialization
はプラットフォームに依存しません。 これは、両方のプロセスを異なるプラットフォームで実行できることを意味します。
私たちは、Remote Method Invocation (RMI
) と Enterprise Java Beans (EJB
) で Serialization
を使用しています。 Java Persistence API (JPA
)、Hibernate などでも使用されます。
NotSerializableException
は、オブジェクト ストリーム クラスに固有の他のすべての例外のスーパークラスとして定義される ObjectStreamException
クラスを拡張する例外です。
さらに、ObjectStreamException
は IOException
を拡張し、I/O 例外が生成されたことをさらに通知します。
これで、Java の Serialization
と NotSerializableException
がわかりました。 この議論により、Java での NotSerializableException
の理由を発見することができます。
- クラスのインスタンスが
Serializable
インターフェイスを実装する必要がある場合、NotSerializableException
が発生します。 - この例外は、クラスのインスタンスまたはシリアライゼーション ランタイムでも発生します。
NotSerializableException
の引数はクラスの名前であることを思い出してください。 - ドキュメント によると、完全なオブジェクト グラフはシリアライズ可能である必要があります。
NotSerializableException
は、クラスのインスタンスをシリアル化しようとしたときに、フィールドの少なくとも 1つがSerializable
インターフェイスを実装していない場合にも発生します。
Java の java.io.NotSerializableException
を修正
次の解決策を使用して、Java の java.io.NotSerializableException
を修正できます。
-
この例外を
throws
するクラスを見つけ、Serializable
インターフェースを実装してSerializable
にします。NotSerializableException
をスローするクラスがサードパーティ ライブラリに属している場合、このソリューションは適切な選択ではない可能性があることに注意してください。 -
クラスがシリアライズ可能でないオブジェクトを参照する場合、これらのオブジェクトがシリアライズ可能であってはならない場合、オブジェクトを
transient
として宣言できます。 問題は、なぜそれをtransient
と宣言するのかということです。これは、
transient
として宣言されたクラスのフィールドがシリアライズ可能なランタイムによって無視され、例外が発生しないためです。 -
そのデータとそのサード パーティが必要な場合は、シリアル化の他の手段を検討できます。 たとえば、定義を変更せずにサードパーティ オブジェクトをシリアル化できる XML、JSON など。
私たちの場合、Serializable
を実装すると、java.io.NotSerializableException
が修正されました。 次のコード例を参照してください。
コード例 (Students.java
ファイル):
package com.serializertest;
import java.io.Serializable;
class Student implements Serializable {
private String studentId;
public String getId() {
return studentId;
}
public void setId(String id) {
this.studentId = id;
}
}
サンプルコード (SerializerTest.java
ファイル):
package com.serializertest;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class SerializerTest {
public static void main(String[] args) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream("students.txt");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
Student student = new Student();
student.setId("0001");
objectOutputStream.writeObject(student);
objectOutputStream.close();
}
}