JavaRush /جاوا بلاگ /Random-SD /جاوا ۾ عارضي ترميم ڪندڙ ڇا لڪائي ٿو؟
Анзор Кармов
سطح
Санкт-Петербург

جاوا ۾ عارضي ترميم ڪندڙ ڇا لڪائي ٿو؟

گروپ ۾ شايع ٿيل
سلام! اڄ جي آرٽيڪل ۾، اسان جاوا ۾ عارضي موڊيفائر تي نظر ڪنداسين. اچو ته ان بابت ڳالهايون ڇو ته هي موڊيفائر جي ضرورت آهي ۽ ان کي صحيح طريقي سان ڪيئن استعمال ڪجي. وڃ! جاوا ۾ عارضي ترميمي ڇا لڪائي ٿو - 1

اچو ته سيريلائيزيشن کي ياد رکون

تبديل ڪندڙ transientشين کي ترتيب ڏيڻ ۽ ترتيب ڏيڻ جي عمل ۾ استعمال ڪيو ويندو آهي. سو اچو ته پهرين ان بابت مختصر ڳالهايون. جاوا - 2 ۾ عارضي ترميم ڪندڙ ڇا لڪائي ٿوفرض ڪريو اسان وٽ ڪجھ اعتراض آھي، ۽ ان ۾ فيلڊ آھن، جن مان ھر ھڪ وٽ ڪجھ قدر آھي. هي سڀ شئي جي حالت سڏيو ويندو آهي. سيريلائيزيشن هڪ شئي جي حالت کي بائيٽ جي تسلسل ۾ تبديل ڪرڻ آهي. اهي بائيٽ عام طور تي ڪجهه فائلن ۾ ذخيرو ٿيل آهن. Deserialization ريورس عمل آهي. اچو ته تصور ڪريون ته اسان هڪ شئي کي بائيٽ ۾ سيريل ڪيو ۽ بائيٽ جي هن سيٽ کي ڪنهن فائل ۾ محفوظ ڪيو. جڏهن deserializing، پروگرام جي ضرورت آهي:
  1. فائل مان بائيٽ جو هڪ سيٽ پڙهو.
  2. بائٽس جي هن سيٽ مان هڪ ابتدائي اعتراض ٺاهيو ۽ هر فيلڊ کي سيٽ ڪريو قيمت تي جيڪا شئي سيريلائيزيشن جي وقت هئي.
جڏهن اهو مفيد ٿي سگهي ٿو؟ مثال طور، جڏهن اسان چاهيون ٿا ته پروگرام پنهنجي رياست کي محفوظ ڪري جڏهن بند ڪيو وڃي ۽ ان کي بحال ڪيو وڃي ته ايندڙ وقت ان کي آن ڪيو وڃي. جڏهن توهان IntelliJ IDEA بند ڪيو ٿا، توهان وٽ گهڻو ڪري ساڳيون ٽيب ۽ ڪلاس کليل هوندا جڏهن توهان ان کي آن ڪندا.

اچو ته عملي طور تي سيريلائيزيشن کي ياد رکون

خير، هاڻي اچو ته عملي طور تي سيريلائيزيشن کي ڏسو. جيڪڏهن توهان موضوع کي بهتر سمجهڻ چاهيو ٿا، ته اسان جاوا ۾ مواد سيريلائيزيشن ۽ ڊيسيريلائيزيشن پڙهڻ جي صلاح ڏيون ٿا . خير، هن مضمون ۾ اسين مٿي وڃو ۽ سڌو مثالن ڏانهن وڃو. اچو ته چئون ته اسان وٽ هڪ ڪلاس آهي Userجنهن ۾ ڪجهه شعبن جو هڪ سيٽ آهي، حاصل ڪندڙ ۽ سيٽرز، ۽ هڪ طريقو 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 + '\'' +
                '}';
    }
}
اسان مستقبل ۾ هن طبقي جي شين کي ترتيب ڏيڻ چاهيون ٿا. اچو ته هڪ طريقو لکون جيڪو هڪ اعتراض User۽ اسٽرنگ وٺي ٿو path- فائل ڏانهن رستو جنهن ۾ اسان بائيٽ محفوظ ڪنداسين:
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();
        }
    }
}
اسان به deserialization لاء هڪ طريقو لکندا. طريقو هڪ اسٽرنگ وٺندو آهي path(فائل ڏانهن رستو جنهن مان اعتراض "لوڊ ڪيو ويندو") ۽ قسم جو هڪ اعتراض موٽائي ٿو 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();
        }
    }
}
سڀ اوزار استعمال لاء تيار آهن. اهو وقت آهي بائيٽ کي ائٽم ۾ ورهائڻ جو . اچو ته هڪ طريقو لکون mainجنهن ۾ اسان هڪ طبقاتي اعتراض ٺاهي User۽ ان کي ترتيب ڏيو. پوءِ اسان ان کي لوڊ ڪنداسين ۽ ان جو مقابلو ڪنداسين جيڪو اصل ۾ هو:
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");
}
جيڪڏهن اسان طريقي سان هلون ٿا، اسان هيٺ ڏنل پيداوار ڏسندا سين:
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'}
جئين توھان ٻاھرين مان ڏسي سگھو ٿا، شيون ھڪڙي ھڪڙي آھن. پر اتي ھڪڙو ننڍڙو آھي پر... ۽ اھو ئي آھي جتي اسپيني شرم transient اچي ٿي .

تبديل ڪندڙ (آخرڪار)transient

ڇا ڪنهن کي مونجهارو هو ته اسان صارف جو پاسورڊ محفوظ ڪيو؟ خاص طور تي اهڙو پاسورڊ... ها، ها، اسان پاڻ ان سان گڏ آيا آهيون، پر تڏهن به... ڪڏهن ڪڏهن اهڙيون حالتون هونديون آهن جڏهن ڪجهه فيلڊز کي سيريل نه ڪري سگهجي، يا اهو نه ڪرڻ بهتر آهي. مٿي ڏنل مثال ۾، مان پاس ورڊ کان سواءِ سڀني شعبن کي محفوظ ڪرڻ چاهيندس. اهو ڪيئن حاصل ڪجي؟ جواب: تبديل ڪندڙ استعمال ڪريو transient. transientھڪڙو تبديل ڪندڙ آھي جيڪو ھڪڙي طبقي جي فيلڊ جي اڳيان رکيل آھي (ٻين ترميم ڪندڙن جھڙوڪ public، finalوغيره) اشارو ڪرڻ لاء ته فيلڊ کي سيريل نه ڪيو وڃي. لفظ سان نشان لڳل فيلڊز transientسيريل نه ڪيا ويا آهن. ھاڻي اچو ته پنھنجي استعمال ڪندڙ سان مثال کي ايڊٽ ڪريون ھڪ ننڍڙي مونجهاري کي درست ڪرڻ ۽ صارف جو پاسورڊ محفوظ نه ڪرڻ لاءِ. ائين ڪرڻ لاءِ، ڪلاس ۾ لاڳاپيل فيلڊ کي لفظ سان نشان لڳايو 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...
     */
}
جيڪڏهن اسان مٿي ڏنل مثال مان طريقو ٻيهر هلون ٿا main، اسان ڏسنداسين ته پاسورڊ محفوظ نه آهي:
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'}
عظيم، اسان اسان جو مقصد حاصل ڪيو ۽ ڳجھي معلومات کي ذخيرو نه ڪيو. خاص ڪري هن قسم جي معلومات... (معاف ڪجو)

جڏهن عارضي استعمال ڪرڻ لاء؟

هڪ صارف سان هڪ مثال جي ضرورت هئي سيريلائيزيشن جي حوالي سان ڊيو ڪرڻ لاء. هاڻي اچو ته وڌيڪ خاص طور تي ڳالهايون جڏهن موڊيفائر استعمال ڪيو وڃي transient.

  • فيلڊس جيڪي حساب ڪتاب جي حساب سان ڪيا ويا آهن

ڪجهه طبقن ۾ ڪڏهن ڪڏهن فيلڊ هوندا آهن جيڪي حساب ڪيا ويندا آهن ٻين شعبن يا ٻين معلومات جي بنياد تي. اهي حساب ڪتاب آهن، تنهنڪري ڳالهائڻ لاء، مکڻ تي. اهڙي فيلڊ جو مثال ڏيڻ لاءِ، اچو ته تصور ڪريون آرڊر ڪنهن آن لائن اسٽور يا ڪجهه کاڌي جي ترسيل سروس ۾. هر آرڊر، ٻين معلومات جي وچ ۾، سامان جي فهرست ۽ مجموعي قيمت تي مشتمل آهي. اهو، موڙ ۾، هر پيداوار جي مجموعي قيمت تي مشتمل آهي. اهو ظاهر ٿئي ٿو ته آخري قيمت مقرر نه ٿيڻ گهرجي "هٿ سان": اهو پروگرام جي حساب سان حساب ڪيو وڃي، سڀني سامان جي قيمت کي گڏ ڪندي. ھنن جھڙا شعبا جن کي پروگرام جي حساب سان حساب ڪيو وڃي، سيريلائز ٿيڻ جي ضرورت ناھي. تنهن ڪري، اسان انهن کي تبديل ڪندڙ سان نشان لڳايو transient.
class Order implements Serializable {

    private List items;
    private transient BigDecimal totalAmount; //вычисляется на ходу

}

  • خانگي معلومات سان گڏ فيلڊ

ڪجھ طبقا پڻ آھن جيڪي نجي معلومات کي ذخيرو ڪن ٿا. اسان مضمون جي شروعات ۾ اهڙي طبقي جو هڪ مثال ڏٺو. توهان کي اهڙي معلومات کي JVM کان ٻاهر ليڪ ڪرڻ جي اجازت نه ڏيڻ گهرجي. transientتنهن ڪري، جيڪڏهن توهان اهڙي قسم جي درجي کي ترتيب ڏيڻ وارا آهيو ته اهڙي ڊيٽا سان فيلڊ کي تبديل ڪندڙ سان نشان لڳايو وڃي .

  • فيلڊ جيڪي انٽرفيس تي عمل نه ڪندا آھنSerializable

ڪڏهن ڪڏهن هڪ ڪلاس ۾ فيلڊز شامل آهن - ٻين طبقن جون شيون جيڪي انٽرفيس تي عمل نه ڪندا آهن Serializable. اهڙن شعبن جا مثال آهن لاگرز، I/O اسٽريم، شيون جيڪي ذخيرو ڪن ٿا ڊيٽابيس ڪنيڪشن ۽ ٻيون يوٽيلٽي ڪلاس. جيڪڏهن توهان ڪنهن شئي کي ترتيب ڏيڻ جي ڪوشش ڪندا آهيو جنهن ۾ غير سيريلائيز فيلڊ شامل آهن، توهان کي هڪ غلطي ملندي java.io.NotSerializableException. هن کان بچڻ لاء، سڀئي شعبا جيڪي انٽرفيس تي عمل نه ڪندا آهن انهن کي Serializableتبديل ڪندڙ سان نشان لڳايو وڃي 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();
            }
        }
    }
}

  • اعتراض جي حالت بابت معلومات سان فيلڊ

خير، هڪ آخري شيء. انهن شعبن کي سيريل ڪرڻ جي ڪا ضرورت ناهي جيڪي اعتراض جي رياستي معلومات جو حصو نه آهن. مٿي ڏنل مثال هن قاعدي هيٺ اچي وڃن ٿا. پر توھان ھتي شامل ڪري سگھوٿا ٻيا سڀ شعبا ڊيبگنگ لاءِ شامل ڪيا ويا آھن يا ڪنھن قسم جي سروس فنڪشن کي انجام ڏيڻ لاءِ جيڪي اعتراض جي حالت بابت معلومات نٿا رکن.

transient۽final

نتيجا

اهو ئي سڀ ڪجهه آهي. اڄ اسان موڊيفائر جي باري ۾ ڳالهايون ٿا transient:
  1. اسان کي نظريي ۽ عمل ۾ سيريلائيزيشن ياد آهي.
  2. اسان محسوس ڪيو ته ڪلاس جي ڪجهه شعبن کي ترتيب نه ڏيڻ لاء، انهن کي تبديل ڪندڙ سان نشان لڳڻ جي ضرورت آهي transient.
  3. اسان بحث ڪيو ته ڪهڙين حالتن ۾ هي ترميمي استعمال ٿيڻ گهرجي. اهڙيون چار حالتون هيون:
    1. فيلڊز جيڪي پروگرام جي حساب سان حساب ڪيا ويا آهن؛
    2. فيلڊ جيڪي ڳجهي معلومات تي مشتمل آهن؛
    3. فيلڊ جيڪي انٽرفيس تي عمل نه ڪندا آھن Serializable؛
    4. فيلڊ جيڪي اعتراض جي رياست جو حصو نه آهن.
تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION