Kelas Enum adalah Serializable sehingga tidak ada masalah untuk membuat serial objek dengan enum. Kasus lainnya adalah di mana kelas memiliki bidang kelas java.util.Optional. Dalam kasus ini, pengecualian berikut akan ditampilkan: java.io.NotSerializableException: java.util.Optional
Bagaimana menangani kelas-kelas seperti itu, bagaimana cara membuatnya bersambung? Apakah mungkin mengirim objek tersebut ke Remote EJB atau melalui RMI?
Ini contohnya:
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Optional;
import org.junit.Test;
public class SerializationTest {
static class My implements Serializable {
private static final long serialVersionUID = 1L;
Optional<Integer> value = Optional.empty();
public void setValue(Integer i) {
this.i = Optional.of(i);
}
public Optional<Integer> getValue() {
return value;
}
}
//java.io.NotSerializableException is thrown
@Test
public void serialize() {
My my = new My();
byte[] bytes = toBytes(my);
}
public static <T extends Serializable> byte[] toBytes(T reportInfo) {
try (ByteArrayOutputStream bstream = new ByteArrayOutputStream()) {
try (ObjectOutputStream ostream = new ObjectOutputStream(bstream)) {
ostream.writeObject(reportInfo);
}
return bstream.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
java
serialization
java-8
optional
vanarchi
sumber
sumber
Optional
ditandai sebagaiSerializable
, lalu apa yang akan terjadi jikaget()
mengembalikan sesuatu yang tidak dapat diserialkan?NotSerializableException,
kursus.Jawaban:
Jawaban ini untuk menjawab pertanyaan pada judul "Shouldn't Opsional menjadi Serializable?" Jawaban singkatnya adalah bahwa kelompok ahli Java Lambda (JSR-335) mempertimbangkan dan menolaknya . Catatan itu, dan yang satu ini dan yang ini menunjukkan bahwa tujuan desain utama untuk
Optional
digunakan sebagai nilai hasil fungsi ketika nilai yang dikembalikan mungkin tidak ada. Maksudnya adalah agar pemanggil segera memeriksaOptional
dan mengekstrak nilai sebenarnya jika ada. Jika nilainya tidak ada, pemanggil dapat mengganti nilai default, membuat pengecualian, atau menerapkan beberapa kebijakan lain. Ini biasanya dilakukan dengan merangkai panggilan metode yang lancar dari ujung pipa aliran (atau metode lain) yang mengembalikanOptional
nilai.Itu tidak pernah dimaksudkan untuk
Optional
digunakan dengan cara lain, seperti untuk argumen metode opsional atau untuk disimpan sebagai bidang dalam suatu objek . Dan dengan ekstensi, membuatOptional
serializable akan memungkinkannya untuk disimpan secara terus-menerus atau ditransmisikan melalui jaringan, yang keduanya mendorong penggunaan jauh melampaui tujuan desain aslinya.Biasanya ada cara yang lebih baik untuk mengatur data daripada menyimpan
Optional
di lapangan. Jika getter (sepertigetValue
metode dalam pertanyaan) mengembalikan aktualOptional
dari lapangan, itu memaksa setiap pemanggil untuk mengimplementasikan beberapa kebijakan untuk menangani nilai kosong. Ini kemungkinan akan menyebabkan perilaku tidak konsisten di seluruh penelepon. Seringkali lebih baik memiliki kumpulan kode apa pun yang bidang itu menerapkan beberapa kebijakan pada saat disetel.Terkadang orang ingin memasukkan
Optional
ke dalam koleksi, sepertiList<Optional<X>>
atauMap<Key,Optional<Value>>
. Ini juga biasanya merupakan ide yang buruk. Seringkali lebih baik mengganti penggunaan iniOptional
dengan nilai Null-Object (bukannull
referensi sebenarnya ), atau hanya menghilangkan entri ini dari koleksi seluruhnya.sumber
Banyak
Serialization
masalah terkait dapat diatasi dengan memisahkan formulir serial yang persisten dari implementasi runtime aktual tempat Anda beroperasi.Kelas
Optional
mengimplementasikan perilaku yang memungkinkan untuk menulis kode yang baik ketika berhadapan dengan nilai yang mungkin tidak ada (dibandingkan dengan penggunaannull
). Tapi itu tidak menambah manfaat apa pun untuk representasi data Anda yang persisten. Itu hanya akan membuat data serial Anda lebih besar…Sketsa di atas mungkin terlihat rumit tetapi itu karena ini menunjukkan pola hanya dengan satu properti. Semakin banyak properti yang dimiliki kelas Anda, semakin banyak kesederhanaannya yang harus diungkapkan.
Dan jangan lupa, kemungkinan untuk mengubah implementasi
My
sepenuhnya tanpa perlu menyesuaikan bentuk persisten…sumber
class My
, yang biasanya Anda lakukan karena berguna untuk penggunaan lain juga,readResolve
bisa menjadi implementasi satu baris sehingga mengurangi pelat boiler menjadi satu baris per properti. Yang tidak banyak mengingat fakta bahwa setiap properti yang dapat berubah memiliki setidaknya tujuh baris kode di kelasMy
.Jika Anda menginginkan opsional yang dapat diserialkan, pertimbangkan untuk menggunakan opsi jambu biji yang dapat diserialkan.
sumber
Ini kelalaian yang aneh.
Anda harus menandai bidang sebagai
transient
dan memberikanwriteObject()
metode kustom Anda sendiri yang menulisget()
hasil itu sendiri, danreadObject()
metode yang memulihkanOptional
dengan membaca hasil itu dari aliran. Tidak lupa menelepondefaultWriteObject()
dandefaultReadObject()
masing - masing.sumber
Library Vavr.io (sebelumnya Javaslang) juga memiliki
Option
kelas yang dapat diserialkan:sumber
Jika Anda ingin mempertahankan daftar tipe yang lebih konsisten dan menghindari penggunaan null, ada satu alternatif yang kooky.
Anda dapat menyimpan nilai menggunakan perpotongan tipe . Digabungkan dengan lambda, ini memungkinkan sesuatu seperti:
Memiliki
temp
variabel terpisah menghindari penutupan pemilikvalue
anggota dan dengan demikian terlalu banyak melakukan seri .sumber