Halo! Pada artikel hari ini, kita akan melihat pengubah sementara di Java. Mari kita bahas mengapa pengubah ini diperlukan dan bagaimana menggunakannya dengan benar. Pergi!
atom . Mari kita menulis sebuah metode rasa malu orang Spanyol Pengubah (akhirnya)
Adakah yang bingung karena kami menyimpan kata sandi pengguna? Terutama kata sandi seperti itu... Ya, ya, kami membuatnya sendiri, tapi tetap saja... Terkadang ada situasi ketika beberapa bidang tidak dapat diserialkan, atau lebih baik tidak melakukan ini. Pada contoh di atas, saya ingin menyimpan semua kolom kecuali kata sandi. Bagaimana cara mencapainya? Jawaban: gunakan pengubah
Beberapa kelas terkadang memiliki bidang yang dihitung berdasarkan bidang lain atau informasi lainnya. Bisa dikatakan, mereka dihitung dengan cepat. Sebagai contoh bidang tersebut, mari kita bayangkan pemesanan di toko online atau layanan pesan-antar makanan. Setiap pesanan antara lain informasi terdiri dari daftar barang dan total biaya. Ini, pada gilirannya, terdiri dari total biaya setiap produk. Ternyata biaya akhir tidak boleh ditetapkan “dengan tangan”: biaya tersebut harus dihitung secara terprogram, menjumlahkan harga semua barang. Bidang seperti ini yang harus dihitung secara terprogram tidak perlu diserialkan. Oleh karena itu, kami menandainya dengan pengubah
Ada juga beberapa kelas yang menyimpan informasi pribadi. Kami melihat contoh kelas seperti itu di awal artikel. Anda tidak boleh membiarkan informasi tersebut bocor di luar JVM. Oleh karena itu, bidang dengan data tersebut harus ditandai dengan pengubah
Terkadang suatu kelas berisi field – objek dari kelas lain yang tidak mengimplementasikan antarmuka
Nah, satu hal terakhir. Tidak perlu membuat serial bidang yang bukan bagian dari informasi status objek. Contoh di atas termasuk dalam aturan ini. Tapi Anda juga bisa memasukkan di sini semua bidang lain yang ditambahkan untuk debugging atau untuk melakukan beberapa jenis fungsi layanan yang tidak membawa informasi tentang keadaan objek.
Mari kita ingat serialisasi
Pengubahtransient
digunakan dalam proses serialisasi dan deserialisasi objek. Jadi mari kita bahas secara singkat tentang hal ini terlebih dahulu. Misalkan kita memiliki suatu objek, dan objek tersebut memiliki bidang, yang masing-masing memiliki nilai tertentu. Semua ini disebut keadaan obyek. Serialisasi adalah konversi status objek menjadi urutan byte. Byte ini biasanya disimpan dalam beberapa file. Deserialisasi adalah proses sebaliknya. Bayangkan kita membuat serial suatu objek menjadi byte dan menyimpan kumpulan byte ini dalam beberapa file. Saat melakukan deserialisasi, program memerlukan:
- Membaca satu set byte dari sebuah file.
- Buatlah objek awal dari kumpulan byte ini dan atur setiap bidang ke nilai yang dimiliki objek tersebut pada saat serialisasi.
Mari kita ingat serialisasi dalam praktiknya
Nah, sekarang mari kita lihat serialisasi dalam praktiknya. Jika Anda ingin memahami topik ini dengan lebih baik, kami sarankan membaca materi Serialisasi dan deserialisasi di Java . Nah, pada artikel kali ini kita akan membahasnya dan langsung ke contohnya. Katakanlah kita memiliki kelasUser
dengan sekumpulan beberapa bidang, pengambil dan penyetel, dan sebuah metode toString
:
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String firstName;
private String lastName;
private String email;
private LocalDate birthDate;
private String login;
private String password;
public User() {}
public User(String firstName, String lastName, String email, LocalDate birthDate, String login, String password) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.birthDate = birthDate;
this.login = login;
this.password = password;
}
/*
Геттеры, Сеттеры
*/
@Override
public String toString() {
return "User{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", email='" + email + '\'' +
", birthDate=" + birthDate +
", login='" + login + '\'' +
", password='" + password + '\'' +
'}';
}
}
Kami ingin membuat serialisasi objek kelas ini di masa mendatang. Mari kita tulis metode yang mengambil objek User
dan string path
- jalur ke file tempat kita akan menyimpan byte:
static void serialize(User user, String path) throws IOException {
FileOutputStream outputStream = null;
ObjectOutputStream objectOutputStream = null;
try {
//create 2 threads to serialize the object and save it to a file
outputStream = new FileOutputStream(path);
objectOutputStream = new ObjectOutputStream(outputStream);
// сохраняем an object в файл
objectOutputStream.writeObject(user);
} finally {
// Закроем потоки в блоке finally
if (objectOutputStream != null) {
objectOutputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
}
Kami juga akan menulis metode deserialisasi. Metode ini mengambil string path
(jalur ke file tempat objek akan "dimuat") dan mengembalikan objek bertipe User
:
static User deserialize(String path) throws IOException, ClassNotFoundException {
FileInputStream fileInputStream = null;
ObjectInputStream objectInputStream = null;
try {
//создаем 2 потока для десериализации an object из file
fileInputStream = new FileInputStream(path);
objectInputStream = new ObjectInputStream(fileInputStream);
//загружаем an object из file
return (User) objectInputStream.readObject();
} finally {
if (fileInputStream != null) {
fileInputStream.close();
}
if (objectInputStream != null) {
objectInputStream.close();
}
}
}
Semua alat siap digunakan. Saatnya membagi byte menjadi main
di mana kita membuat objek kelas User
dan membuat cerita bersambung. Kemudian kita akan memuatnya dan membandingkannya dengan aslinya:
public static void main(String[] args) throws IOException, ClassNotFoundException {
// вставьте свой путь до file
final String path = "/home/zor/user.ser";
// create our object
User user = new User();
user.setFirstName("Stefan");
user.setLastName("Smith");
user.setEmail("ssmith@email.com");
user.setBirthDate(LocalDate.of(1991, 7, 16));
user.setLogin("ssmith");
user.setPassword("gemma_arterton_4ever_in_my_heart91");
System.out.println("Initial user: " + user + "\r\n");
serialize(user, path);
User loadedUser = deserialize(path);
System.out.println("Loaded user from file: " + loadedUser + "\r\n");
}
Jika kita menjalankan metode ini, kita akan melihat output berikut:
Initial user: User{firstName='Stefan', lastName='Smith', email='ssmith@email.com', birthDate=1991-07-16, login='ssmith', password='gemma_arterton_4ever_in_my_heart91'}
Loaded user from file: User{firstName='Stefan', lastName='Smith', email='ssmith@email.com', birthDate=1991-07-16, login='ssmith', password='gemma_arterton_4ever_in_my_heart91'}
Seperti yang Anda lihat dari keluarannya, objek-objeknya identik. Tapi ada sedikit tapi... Dan di sinilah transient
ikut berperan .
Pengubah (akhirnya)transient
Adakah yang bingung karena kami menyimpan kata sandi pengguna? Terutama kata sandi seperti itu... Ya, ya, kami membuatnya sendiri, tapi tetap saja... Terkadang ada situasi ketika beberapa bidang tidak dapat diserialkan, atau lebih baik tidak melakukan ini. Pada contoh di atas, saya ingin menyimpan semua kolom kecuali kata sandi. Bagaimana cara mencapainya? Jawaban: gunakan pengubah transient
. transient
adalah pengubah yang ditempatkan sebelum bidang kelas (mirip dengan pengubah lain seperti public
, final
dll.) untuk menunjukkan bahwa bidang tersebut tidak boleh diserialkan. Bidang yang ditandai dengan kata kunci transient
tidak berseri. Sekarang mari kita edit contoh dengan pengguna kita untuk memperbaiki kebingungan kecil dan tidak menyimpan kata sandi pengguna. Untuk melakukan ini, tandai bidang yang sesuai di kelas dengan kata kunci transient
:
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String firstName;
private String lastName;
private String email;
private LocalDate birthDate;
private String login;
private transient String password;
/*
Конструкторы, геттеры, сеттеры, toString...
*/
}
Jika kita menjalankan kembali metode dari contoh di atas main
, kita akan melihat bahwa kata sandi tidak disimpan:
Initial user: User{firstName='Stefan', lastName='Smith', email='ssmith@email.com', birthDate=1991-07-16, login='ssmith', password='gemma_arterton_4ever_in_my_heart91'}
Loaded user from file: User{firstName='Stefan', lastName='Smith', email='ssmith@email.com', birthDate=1991-07-16, login='ssmith', password='null'}
Hebat, kami mencapai tujuan kami dan tidak menyimpan informasi rahasia. Terutama informasi semacam ini... (maaf)
Kapan menggunakan sementara?
Contoh dengan pengguna diperlukan untuk menyelami konteks serialisasi. Sekarang mari kita bicara lebih spesifik tentang kapan harus menggunakan modifiertransient
.
- Bidang yang dihitung secara terprogram
Beberapa kelas terkadang memiliki bidang yang dihitung berdasarkan bidang lain atau informasi lainnya. Bisa dikatakan, mereka dihitung dengan cepat. Sebagai contoh bidang tersebut, mari kita bayangkan pemesanan di toko online atau layanan pesan-antar makanan. Setiap pesanan antara lain informasi terdiri dari daftar barang dan total biaya. Ini, pada gilirannya, terdiri dari total biaya setiap produk. Ternyata biaya akhir tidak boleh ditetapkan “dengan tangan”: biaya tersebut harus dihitung secara terprogram, menjumlahkan harga semua barang. Bidang seperti ini yang harus dihitung secara terprogram tidak perlu diserialkan. Oleh karena itu, kami menandainya dengan pengubah transient
.
class Order implements Serializable {
private List- items;
private transient BigDecimal totalAmount; //вычисляется на ходу
}
- Bidang dengan informasi pribadi
Ada juga beberapa kelas yang menyimpan informasi pribadi. Kami melihat contoh kelas seperti itu di awal artikel. Anda tidak boleh membiarkan informasi tersebut bocor di luar JVM. Oleh karena itu, bidang dengan data tersebut harus ditandai dengan pengubah transient
jika Anda ingin membuat serialisasi kelas tersebut.
- Bidang yang tidak mengimplementasikan antarmuka
Serializable
Terkadang suatu kelas berisi field – objek dari kelas lain yang tidak mengimplementasikan antarmuka Serializable
Serializable
. Contoh bidang tersebut adalah logger, aliran I/O, objek yang menyimpan koneksi database, dan kelas utilitas lainnya. Jika Anda mencoba membuat serialisasi objek yang berisi bidang yang tidak dapat diserialkan, Anda akan menerima kesalahan java.io.NotSerializableException
. Untuk menghindari hal ini, semua bidang yang tidak mengimplementasikan antarmuka Serializable
harus ditandai dengan pengubah transient
.
public class FileReader implements Serializable {
// Первые 2 поля не реализуют Serializable
// Помечаем их How transient поля
private transient InputStream is;
private transient BufferedReader buf;
private String fileName;
// Constructors, Getters, Setters
public String readFile() throws IOException {
try {
is = new FileInputStream(fileName);
buf = new BufferedReader(new InputStreamReader(is));
String line = buf.readLine();
StringBuilder sb = new StringBuilder();
while (line != null) {
sb.append(line).append("\n");
line = buf.readLine();
}
return sb.toString();
} finally {
if (buf != null) {
buf.close();
}
if (is != null) {
is.close();
}
}
}
}
- Bidang dengan informasi tentang status objek
Nah, satu hal terakhir. Tidak perlu membuat serial bidang yang bukan bagian dari informasi status objek. Contoh di atas termasuk dalam aturan ini. Tapi Anda juga bisa memasukkan di sini semua bidang lain yang ditambahkan untuk debugging atau untuk melakukan beberapa jenis fungsi layanan yang tidak membawa informasi tentang keadaan objek.
transient
Danfinal
Hasil
Itu saja. Hari ini kita berbicara tentang pengubahtransient
:
- Kami ingat serialisasi dalam teori dan praktik.
- Kami menyadari bahwa agar tidak membuat serialisasi beberapa bidang kelas, bidang tersebut perlu ditandai dengan pengubah
transient
. - Kami membahas dalam situasi apa pengubah ini harus digunakan. Ada empat situasi seperti itu:
- bidang yang dihitung secara terprogram;
- bidang yang berisi informasi rahasia;
- bidang yang tidak mengimplementasikan antarmuka
Serializable
; - bidang yang bukan bagian dari status objek.
GO TO FULL VERSION