Salom! Bugungi maqolamizda Java tilidagi vaqtinchalik modifikatorni ko'rib chiqamiz. Keling, ushbu modifikator nima uchun kerakligini va uni qanday qilib to'g'ri ishlatish haqida gapiraylik. Bor!
Baytlarni atomlarga bo'lish vaqti keldi . ispan sharmandaligi Modifikator (nihoyat)
Kimdir foydalanuvchi parolini saqlab qolganimizdan adashdimi? Ayniqsa, shunday parol... Ha, ha, biz buni o'zimiz o'ylab topdik, lekin baribir... Ba'zida shunday vaziyatlar bo'ladiki, ba'zi maydonlarni ketma-ketlashtirib bo'lmaydi yoki buni qilmaslik yaxshiroqdir. Yuqoridagi misolda men paroldan tashqari barcha maydonlarni saqlamoqchiman. Bunga qanday erishish mumkin? Javob: modifikatordan foydalaning
Ba'zi sinflarda ba'zan boshqa maydonlar yoki boshqa ma'lumotlar asosida hisoblangan maydonlar mavjud. Ular, ta'bir joiz bo'lsa, hisoblab chiqiladi. Bunday sohaga misol keltirish uchun onlayn-do'kondagi buyurtma yoki oziq-ovqat yetkazib berish xizmatini tasavvur qilaylik. Har bir buyurtma, boshqa ma'lumotlar bilan bir qatorda, tovarlar ro'yxati va umumiy xarajatlardan iborat. U, o'z navbatida, har bir mahsulotning umumiy qiymatidan iborat. Ma'lum bo'lishicha, yakuniy xarajat "qo'lda" belgilanmasligi kerak: u barcha tovarlarning narxini umumlashtirib, dasturiy ravishda hisoblanishi kerak. Dasturiy tarzda hisoblanishi kerak bo'lgan bu kabi maydonlarni ketma-ketlashtirish kerak emas. Shuning uchun biz ularni modifikator bilan belgilaymiz
Shaxsiy ma'lumotlarni saqlaydigan ba'zi sinflar ham mavjud. Biz maqolaning boshida bunday sinfning namunasini ko'rib chiqdik. Bunday ma'lumotlarning JVM dan tashqariga chiqishiga yo'l qo'ymasligingiz kerak.
Ba'zan sinfda interfeysni amalga oshirmaydigan boshqa sinflarning maydonlari - ob'ektlari mavjud
Xo'sh, oxirgi narsa. Ob'ekt holati haqidagi ma'lumotlarning bir qismi bo'lmagan maydonlarni ketma-ketlashtirishning hojati yo'q. Yuqoridagi misollar ushbu qoidaga tegishli. Lekin siz bu yerga disk raskadrovka uchun qo'shilgan yoki ob'ekt holati haqida ma'lumot bermaydigan ba'zi xizmat funktsiyalarini bajarish uchun qo'shilgan barcha boshqa maydonlarni ham kiritishingiz mumkin.
Serializatsiyani eslaylik
Modifikatortransient
ob'ektlarni ketma-ketlashtirish va seriyadan chiqarish jarayonida qo'llaniladi. Shunday ekan, avvalo bu haqda qisqacha gaplashamiz. Faraz qilaylik, bizda qandaydir ob'ekt bor va uning har biri qandaydir qiymatga ega bo'lgan maydonlarga ega. Bularning barchasi ob'ektning holati deb ataladi. Seriyalashtirish - ob'ekt holatini baytlar ketma-ketligiga aylantirish. Bu baytlar odatda qandaydir faylda saqlanadi. Seriyadan chiqarish teskari jarayondir. Tasavvur qilaylik, biz ob'ektni baytlarga seriyalashtirdik va bu baytlar to'plamini qandaydir faylda saqladik. Seriyadan chiqarishda dasturga quyidagilar kerak bo'ladi:
- Fayldan baytlar to'plamini o'qing.
- Ushbu baytlar to'plamidan boshlang'ich ob'ektni tuzing va har bir maydonni ketma-ketlashtirish vaqtida ob'ektga ega bo'lgan qiymatga o'rnating.
Amalda ketma-ketlashtirishni eslaylik
Xo'sh, endi ketma-ketlashtirishni amalda ko'rib chiqaylik. Agar siz mavzuni yaxshiroq tushunmoqchi bo'lsangiz, Java-da Seriyalashtirish va seriyani yo'qotish materialini o'qishni tavsiya etamiz . Xo'sh, ushbu maqolada biz yuqoriga o'tamiz va to'g'ridan-to'g'ri misollarga o'tamiz. Aytaylik, bizdaUser
ba'zi maydonlar, qabul qiluvchilar va o'rnatuvchilar va usuldan iborat sinf mavjud 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 + '\'' +
'}';
}
}
Kelajakda biz ushbu sinf ob'ektlarini ketma-ketlashtirishni xohlaymiz. User
Ob'ekt va satrni oladigan usulni yozamiz path
- baytlarni saqlaydigan faylga yo'l:
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();
}
}
}
Seriyadan chiqarish usulini ham yozamiz. Usul satrni oladi path
(ob'ekt "yuklanadigan" faylga yo'l) va turdagi ob'ektni qaytaradi 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();
}
}
}
Barcha vositalar foydalanishga tayyor. main
Keling , sinf ob'ektini yaratadigan User
va uni seriyali qiladigan usulni yozaylik . Keyin biz uni yuklaymiz va uni avvalgisi bilan taqqoslaymiz:
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");
}
Agar biz usulni ishga tushirsak, biz quyidagi natijani ko'ramiz:
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'}
Chiqishdan ko'rinib turibdiki, ob'ektlar bir xil. Ammo kichik bir narsa bor, lekin ... Va aynan shu erda transient
o'ynaydi .
Modifikator (nihoyat)transient
Kimdir foydalanuvchi parolini saqlab qolganimizdan adashdimi? Ayniqsa, shunday parol... Ha, ha, biz buni o'zimiz o'ylab topdik, lekin baribir... Ba'zida shunday vaziyatlar bo'ladiki, ba'zi maydonlarni ketma-ketlashtirib bo'lmaydi yoki buni qilmaslik yaxshiroqdir. Yuqoridagi misolda men paroldan tashqari barcha maydonlarni saqlamoqchiman. Bunga qanday erishish mumkin? Javob: modifikatordan foydalaning transient
. transient
sinf maydoni oldiga qoʻyilgan modifikator (boshqa oʻzgartiruvchilarga oʻxshash, masalan public
, final
va hokazo) maydonni ketma-ketlashtirmaslik kerakligini bildiradi. Kalit so'z bilan belgilangan maydonlar transient
ketma-ketlashtirilmaydi. Keling, kichik chalkashlikni to'g'irlash va foydalanuvchi parolini saqlamaslik uchun foydalanuvchi bilan misolni tahrir qilaylik. Buning uchun sinfdagi tegishli maydonni kalit so'z bilan belgilang 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...
*/
}
Yuqoridagi misoldagi usulni yana ishga tushirsak main
, parol saqlanmasligini ko'ramiz:
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'}
Ajoyib, biz maqsadimizga erishdik va maxfiy ma'lumotlarni saqlamaymiz. Ayniqsa, bunday ma'lumotlar... (kechirasiz)
Vaqtinchalik vaqtni qachon ishlatish kerak?
Serializatsiya kontekstiga kirish uchun foydalanuvchi bilan misol kerak edi. Keling, modifikatordan qachon foydalanish haqida batafsilroq gaplashayliktransient
.
- Dasturiy tarzda hisoblangan maydonlar
Ba'zi sinflarda ba'zan boshqa maydonlar yoki boshqa ma'lumotlar asosida hisoblangan maydonlar mavjud. Ular, ta'bir joiz bo'lsa, hisoblab chiqiladi. Bunday sohaga misol keltirish uchun onlayn-do'kondagi buyurtma yoki oziq-ovqat yetkazib berish xizmatini tasavvur qilaylik. Har bir buyurtma, boshqa ma'lumotlar bilan bir qatorda, tovarlar ro'yxati va umumiy xarajatlardan iborat. U, o'z navbatida, har bir mahsulotning umumiy qiymatidan iborat. Ma'lum bo'lishicha, yakuniy xarajat "qo'lda" belgilanmasligi kerak: u barcha tovarlarning narxini umumlashtirib, dasturiy ravishda hisoblanishi kerak. Dasturiy tarzda hisoblanishi kerak bo'lgan bu kabi maydonlarni ketma-ketlashtirish kerak emas. Shuning uchun biz ularni modifikator bilan belgilaymiz transient
.
class Order implements Serializable {
private List- items;
private transient BigDecimal totalAmount; //вычисляется на ходу
}
- Shaxsiy ma'lumotlarga ega maydonlar
Shaxsiy ma'lumotlarni saqlaydigan ba'zi sinflar ham mavjud. Biz maqolaning boshida bunday sinfning namunasini ko'rib chiqdik. Bunday ma'lumotlarning JVM dan tashqariga chiqishiga yo'l qo'ymasligingiz kerak. transient
Shuning uchun, agar siz bunday sinfni ketma-ketlashtirmoqchi bo'lsangiz, bunday ma'lumotlarga ega maydonlar modifikator bilan belgilanishi kerak .
- Interfeysni amalga oshirmaydigan maydonlar
Serializable
Ba'zan sinfda interfeysni amalga oshirmaydigan boshqa sinflarning maydonlari - ob'ektlari mavjud Serializable
Serializable
. Bunday maydonlarga loggerlar, kiritish-chiqarish oqimlari, ma'lumotlar bazasi ulanishlarini saqlaydigan ob'ektlar va boshqa yordam sinflari misol bo'ladi. Agar siz seriyali bo'lmagan maydonlarni o'z ichiga olgan ob'ektni ketma-ketlashtirishga harakat qilsangiz, siz xatolik olasiz java.io.NotSerializableException
. Bunga yo'l qo'ymaslik uchun interfeysni amalga oshirmaydigan barcha maydonlar Serializable
modifikator bilan belgilanishi kerak 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();
}
}
}
}
- Ob'ekt holati haqidagi ma'lumotlarga ega maydonlar
Xo'sh, oxirgi narsa. Ob'ekt holati haqidagi ma'lumotlarning bir qismi bo'lmagan maydonlarni ketma-ketlashtirishning hojati yo'q. Yuqoridagi misollar ushbu qoidaga tegishli. Lekin siz bu yerga disk raskadrovka uchun qo'shilgan yoki ob'ekt holati haqida ma'lumot bermaydigan ba'zi xizmat funktsiyalarini bajarish uchun qo'shilgan barcha boshqa maydonlarni ham kiritishingiz mumkin.
transient
Vafinal
Natijalar
Ana xolos. Bugun biz modifikator haqida gaplashdiktransient
:
- Biz nazariya va amaliyotda serializatsiyani esladik.
- Biz sinfning ba'zi maydonlarini ketma-ketlashtirmaslik uchun ularni modifikator bilan belgilash kerakligini tushundik
transient
. - Biz ushbu modifikatordan qanday holatlarda foydalanish kerakligini muhokama qildik. Bunday to'rtta holat mavjud edi:
- dasturiy jihatdan hisoblangan maydonlar;
- maxfiy ma'lumotlarni o'z ichiga olgan maydonlar;
- interfeysni amalga oshirmaydigan maydonlar
Serializable
; - ob'ekt holatining bir qismi bo'lmagan maydonlar.
GO TO FULL VERSION