JavaRush /Java blogi /Random-UZ /Vaqtinchalik modifikator Java-da nimani yashiradi?
Анзор Кармов
Daraja
Санкт-Петербург

Vaqtinchalik modifikator Java-da nimani yashiradi?

Guruhda nashr etilgan
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! Vaqtinchalik modifikator Java-da nimani yashiradi - 1

Serializatsiyani eslaylik

Modifikator transientob'ektlarni ketma-ketlashtirish va seriyadan chiqarish jarayonida qo'llaniladi. Shunday ekan, avvalo bu haqda qisqacha gaplashamiz. Vaqtinchalik modifikator Java-da nimani yashiradi - 2Faraz 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:
  1. Fayldan baytlar to'plamini o'qing.
  2. Ushbu baytlar to'plamidan boshlang'ich ob'ektni tuzing va har bir maydonni ketma-ketlashtirish vaqtida ob'ektga ega bo'lgan qiymatga o'rnating.
Bu qachon foydali bo'lishi mumkin? Misol uchun, biz dasturni o'chirishda o'z holatini saqlab qolishni va keyingi safar yoqilganda uni tiklashni xohlaganimizda. IntelliJ IDEA-ni o'chirib qo'yganingizda, keyingi safar uni yoqqaningizda xuddi shu yorliqlar va sinflar ochiladi.

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, bizda Userba'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. UserOb'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. Baytlarni atomlarga bo'lish vaqti keldi . mainKeling , sinf ob'ektini yaratadigan Userva 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 ispan sharmandaligi 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. transientsinf maydoni oldiga qoʻyilgan modifikator (boshqa oʻzgartiruvchilarga oʻxshash, masalan public, finalva hokazo) maydonni ketma-ketlashtirmaslik kerakligini bildiradi. Kalit so'z bilan belgilangan maydonlar transientketma-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 gaplashaylik transient.

  • 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. transientShuning uchun, agar siz bunday sinfni ketma-ketlashtirmoqchi bo'lsangiz, bunday ma'lumotlarga ega maydonlar modifikator bilan belgilanishi kerak .

  • Interfeysni amalga oshirmaydigan maydonlarSerializable

Ba'zan sinfda interfeysni amalga oshirmaydigan boshqa sinflarning maydonlari - ob'ektlari mavjud 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 Serializablemodifikator 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.

transientVafinal

Natijalar

Ana xolos. Bugun biz modifikator haqida gaplashdik transient:
  1. Biz nazariya va amaliyotda serializatsiyani esladik.
  2. Biz sinfning ba'zi maydonlarini ketma-ketlashtirmaslik uchun ularni modifikator bilan belgilash kerakligini tushundik transient.
  3. Biz ushbu modifikatordan qanday holatlarda foydalanish kerakligini muhokama qildik. Bunday to'rtta holat mavjud edi:
    1. dasturiy jihatdan hisoblangan maydonlar;
    2. maxfiy ma'lumotlarni o'z ichiga olgan maydonlar;
    3. interfeysni amalga oshirmaydigan maydonlar Serializable;
    4. ob'ekt holatining bir qismi bo'lmagan maydonlar.
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION