CodeGym /جاوا بلاگ /Random-SD /جاوا ۾ خارجي قابل انٽرفيس
John Squirrels
سطح
San Francisco

جاوا ۾ خارجي قابل انٽرفيس

گروپ ۾ شايع ٿيل
سلام اڄ اسان جاوا شين جي سيريلائيزيشن ۽ ڊيسيريلائيزيشن جي ڄاڻ حاصل ڪندا رهنداسين . پوئين سبق ۾، اسان سيريلائيبل مارڪر انٽرفيس جي ڄاڻ حاصل ڪئي، ان جي استعمال جي مثالن جو جائزو ورتو، ۽ اهو پڻ سکيو ته توهان سيريلائيزيشن جي عمل کي ڪنٽرول ڪرڻ لاءِ عارضي ڪي ورڊ ڪيئن استعمال ڪري سگهو ٿا. خير، اهو چوڻ ته اسان 'پروسيس کي ڪنٽرول' ڪري سگهون ٿا ان کي ختم ڪرڻ. اسان وٽ ھڪڙو لفظ آھي، ھڪڙو نسخو سڃاڻپ ڪندڙ، ۽ اھو ان بابت آھي. باقي عمل جاوا اندر لڪيل آهي، ۽ اسان ان تائين رسائي نٿا ڪري سگهون. يقينن، سهولت جي لحاظ کان، اهو سٺو آهي. پر هڪ پروگرامر کي صرف پنهنجي پنهنجي آرام سان رهنمائي نه ڪرڻ گهرجي، صحيح؟ :) اهڙا ٻيا عنصر آهن جيڪي توهان کي غور ڪرڻ جي ضرورت آهي. اهو ئي سبب آهي ته جاوا ۾ سيريلائيزيشن-ڊيسيريلائيزيشن جو واحد ميکانيزم Serializable ناهي. اڄ اسان کي Externalizable انٽرفيس سان واقف ٿي ويندس . پر ان کان اڳ جو اسان ان جو مطالعو شروع ڪريون، توهان وٽ شايد هڪ معقول سوال هجي: اسان کي ڪنهن ٻئي ميکانيزم جي ضرورت ڇو آهي؟ Serializableان جي نوڪري ڪئي، ۽ سڄي عمل جي خودڪار عمل درآمد جي باري ۾ ڇا پيار نه آهي؟ ۽ جيڪي مثال اسان ڏٺا سي به غير پيچيده هئا. پوء ڇا مسئلو آهي؟ اسان کي لازمي طور تي ساڳئي ڪمن لاءِ ٻئي انٽرفيس جي ضرورت ڇو آهي؟ حقيقت اها آهي ته ان Serializable۾ ڪيترائي نقص آهن. اسان انهن مان ڪجهه فهرست ڪريون ٿا:
  1. ڪارڪردگي. انٽرفيس Serializableڪيترائي فائدا آھن، پر اعلي ڪارڪردگي واضح طور تي انھن مان ھڪڙو نه آھي.

    Externalizable Interface متعارف ڪرائڻ - 2

    پهريون، Serializable 'اندروني عمل درآمد وڏي مقدار ۾ خدمت جي معلومات ۽ هر قسم جي عارضي ڊيٽا ٺاهي ٿو.

    ٻيو، Serializable Reflection API تي ڀروسو ڪري ٿو (توهان کي هن وقت هن تي گهيرو ڪرڻ جي ضرورت ناهي؛ توهان پنهنجي فرصت تي وڌيڪ پڙهي سگهو ٿا، جيڪڏهن توهان دلچسپي رکو ٿا). اها شيءِ توهان کي اجازت ڏئي ٿي ته جاوا ۾ بظاهر ناممڪن شيون: مثال طور، خانگي شعبن جا قدر تبديل ڪريو. CodeGym Reflection API بابت هڪ بهترين مضمون آهي . توھان ان بابت پڙھي سگھوٿا اتي.

  2. لچڪدار. جڏهن اسان انٽرفيس استعمال ڪندا آهيون سيريلائيزيشن-ڊيسيريلائيزيشن جي عمل کي ڪنٽرول نه ڪندا آهيون Serializable.

    هڪ طرف، اهو تمام آسان آهي، ڇاڪاڻ ته جيڪڏهن اسان ڪارڪردگي بابت خاص طور تي فڪرمند نه آهيون، پوء اهو سٺو لڳي ٿو ته ڪوڊ لکڻ جي ضرورت ناهي. پر ڇا جيڪڏهن اسان کي حقيقت ۾ سيريلائيزيشن منطق ۾ پنهنجون ڪجهه خاصيتون شامل ڪرڻ گهرجن (اسين هيٺ هڪ مثال ڏينداسين)؟

    بنيادي طور تي، اسان سڀني کي ڪنٽرول ڪرڻو آهي پروسيس کي transientڪجهه ڊيٽا کي خارج ڪرڻ لاء لفظ. بس اهو آهي. اھو آھي اسان جو سڄو ٽول باڪس :/

  3. سيڪيورٽي. هي شيون اڳئين شيون مان جزوي طور تي نڪتل آهي.

    اسان اڳ ۾ ان بابت سوچڻ ۾ گهڻو وقت نه گذاريو آهي، پر ڇا جيڪڏهن توهان جي ڪلاس ۾ ڪجهه معلومات ٻين جي اکين ۽ ڪنن لاء نه آهي؟ ھڪڙو سادو مثال ھڪڙو پاسورڊ يا ٻيون ذاتي صارف ڊيٽا آھي، جيڪي اڄ جي دنيا ۾ قانونن جي ھڪڙي گروپ جي ذريعي سنڀاليندا آھن.

    جيڪڏهن اسان استعمال ڪريون ٿا Serializable، اسان واقعي ان بابت ڪجهه نٿا ڪري سگهون. اسان هر شي کي ترتيب ڏيو جيئن اهو آهي.

    پر جيڪڏهن اسان اهو صحيح طريقي سان ڪريون ٿا، اسان کي ان قسم جي ڊيٽا کي انڪرپٽ ڪرڻ گهرجي ان کي فائل ۾ لکڻ يا نيٽ ورڪ تي موڪلڻ کان اڳ. پر Serializableاهو ممڪن ناهي.

Externalizable Interface متعارف ڪرائڻ - 3خير، اچو ته آخر ۾ ڏسون ته ڪلاس ڪيئن نظر ايندو جيڪڏهن اسان انٽرفيس استعمال ڪريون Externalizable.

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

public class UserInfo implements Externalizable {

   private String firstName;
   private String lastName;
   private String superSecretInformation;

private static final long SERIAL_VERSION_UID = 1L;

   // ...constructor, getters, setters, toString()...

   @Override
   public void writeExternal(ObjectOutput out) throws IOException {

   }

   @Override
   public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {

   }
}
جئين توهان ڏسي سگهو ٿا، اسان وٽ اهم تبديليون آهن! مکيه هڪ واضح آهي: جڏهن Externalizableانٽرفيس کي لاڳو ڪرڻ، توهان کي لازمي طور تي ٻه گهربل طريقا لاڳو ڪرڻ گهرجن: writeExternal()۽ readExternal(). جيئن اسان اڳ ۾ چيو آهي، سيريلائيزيشن ۽ ڊيسيريلائيزيشن جي ذميواري پروگرامر سان گڏ هوندي. پر هاڻي توهان پروسيس تي ڪنٽرول نه ڪرڻ جو مسئلو حل ڪري سگهو ٿا! سڄو عمل سڌو سنئون توهان جي طرفان پروگرام ڪيو ويو آهي. قدرتي طور، هي هڪ وڌيڪ لچڪدار ميکانيزم جي اجازت ڏئي ٿو. اضافي طور تي، سيڪيورٽي سان مسئلو حل ڪيو ويو آهي. جئين توهان ڏسي سگهو ٿا، اسان جي ڪلاس ۾ هڪ ذاتي ڊيٽا فيلڊ آهي جيڪا محفوظ نه ٿي ڪري سگھجي اڻ ڳڻي. هاڻي اسان آساني سان ڪوڊ لکي سگهون ٿا جيڪو هن پابندي کي پورو ڪري ٿو. مثال طور، اسان پنھنجي ڪلاس ۾ ٻه سادو پرائيويٽ طريقا شامل ڪري سگھون ٿا جيڪي حساس ڊيٽا کي انڪرپٽ ۽ ڊڪرپٽ ڪرڻ لاءِ. اسان ڊيٽا کي فائل ۾ لکنداسين ۽ ان کي فائل مان انڪريپٽ فارم ۾ پڙهنداسين. باقي ڊيٽا جيئن لکيل ۽ پڙهي ويندي :) نتيجي ۾ اسان جو ڪلاس ڪجهه هن طرح نظر اچي ٿو:

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Base64;

public class UserInfo implements Externalizable {

   private String firstName;
   private String lastName;
   private String superSecretInformation;

   private static final long serialVersionUID = 1L;

   public UserInfo() {
   }

   public UserInfo(String firstName, String lastName, String superSecretInformation) {
       this.firstName = firstName;
       this.lastName = lastName;
       this.superSecretInformation = superSecretInformation;
   }

   @Override
   public void writeExternal(ObjectOutput out) throws IOException {
       out.writeObject(this.getFirstName());
       out.writeObject(this.getLastName());
       out.writeObject(this.encryptString(this.getSuperSecretInformation()));
   }

   @Override
   public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
       firstName = (String) in.readObject();
       lastName = (String) in.readObject();
       superSecretInformation = this.decryptString((String) in.readObject());
   }

   private String encryptString(String data) {
       String encryptedData = Base64.getEncoder().encodeToString(data.getBytes());
       System.out.println(encryptedData);
       return encryptedData;
   }

   private String decryptString(String data) {
       String decrypted = new String(Base64.getDecoder().decode(data));
       System.out.println(decrypted);
       return decrypted;
   }

   public String getFirstName() {
       return firstName;
   }

   public String getLastName() {
       return lastName;
   }

   public String getSuperSecretInformation() {
       return superSecretInformation;
   }
}
اسان ٻن طريقن تي عمل ڪيو جيڪي ساڳيا ObjectOutput۽ ObjectInputپيرا ميٽر استعمال ڪن ٿا جيڪي اسان اڳ ۾ ئي سبق ۾ مليا هئا Serializable. صحيح وقت تي، اسان گهربل ڊيٽا کي انڪرپٽ يا ڊڪرپٽ ڪريون ٿا، ۽ اسان انڪريپ ٿيل ڊيٽا کي استعمال ڪريون ٿا پنھنجي اعتراض کي سيريل ڪرڻ لاءِ. اچو ته ڏسو ته اهو عمل ۾ ڪيئن نظر اچي ٿو:

import java.io.*;

public class Main {

   public static void main(String[] args) throws IOException, ClassNotFoundException {

       FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Username\\Desktop\\save.ser");
       ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);

       UserInfo userInfo = new UserInfo("Paul", "Piper", "Paul Piper's passport data");

       objectOutputStream.writeObject(userInfo);

       objectOutputStream.close();

   }
}
encryptString()۽ طريقن ۾ decryptString()، اسان خاص طور تي شامل ڪيو ڪنسول ٻاھر ان فارم جي تصديق ڪرڻ لاءِ جنھن ۾ ڳجھي ڊيٽا لکي ۽ پڙھي ويندي. مٿي ڏنل ڪوڊ هيٺ ڏنل لائن ڏيکاري ٿو: SXZhbiBJdmFub3YncyBwYXNzcG9ydCBkYXRh انڪريپشن ڪامياب ٿي وئي! فائل جو پورو مواد هن طرح نظر اچي ٿو: ¬н sr UserInfoГ!}ҐџC‚ћ xpt Ivant Ivanovt $SXZhbiBJdmFub3YncyBwYXNzcG9ydCBkYXRhx هاڻي اچو ته ڪوشش ڪريون اسان جي ڊيسيريلائيزيشن منطق کي استعمال ڪندي.

public class Main {

   public static void main(String[] args) throws IOException, ClassNotFoundException {

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\save.ser");
       ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);


       UserInfo userInfo = (UserInfo) objectInputStream.readObject();
       System.out.println(userInfo);

       objectInputStream.close();

   }
}
خير، هتي ڪجھ به پيچيده نه لڳي. اهو ڪم ڪرڻ گهرجي! اسان ان کي هلون ٿا ۽ حاصل ڪريون ٿا... استثنا "main" سلسلي ۾ java.io.InvalidClassException: UserInfo; ڪو به صحيح تعمير ڪندڙ ناهي Externalizable Interface متعارف ڪرائڻ - 4 اوهه! :( بظاهر، اهو ايترو آسان ناهي! ڊيسيريلائيزيشن ميڪانيزم هڪ استثنا اڇلائي ڇڏيو ۽ مطالبو ڪيو ته اسان هڪ ڊفالٽ ڪنسٽرڪٽر ٺاهيو. مون کي تعجب آهي ته ڇو. سان، اسان Serializableبغير هڪ جي ذريعي حاصل ڪيو... :/ هتي اسان هڪ ٻي اهم nuance سان منهن ڪيو آهي. فرق Serializable۽ Externalizableڪوڙ جي وچ ۾ نه رڳو پروگرامر جي 'وڌايل' پهچ ۾ ۽ وڌيڪ لچڪدار طريقي سان پروسيس کي ڪنٽرول ڪرڻ جي صلاحيت ۾، پر پروسيس ۾ پڻ. سڀ کان وڌيڪ، ڊيسيريلائيزيشن ميڪانيزم ۾ . استعمال ڪرڻ وقت Serializable، ميموري صرف اعتراض لاء مختص ڪئي وئي آهي، ۽ پوءِ قدرن کي اسٽريم مان پڙهايو ويندو آهي ۽ آبجیکٹ جي فيلڊس کي سيٽ ڪرڻ لاءِ استعمال ڪيو ويندو آهي. جيڪڏهن اسان استعمال ڪندا آهيون ته Serializableاعتراض جي ڪنسٽرڪٽر کي نه سڏيو ويندو آهي! سمورو ڪم ريفريڪشن ذريعي ٿئي ٿو (ريفليڪشن API، جنهن جو اسان مختصر طور تي گذريل سبق ۾ ذڪر ڪيو آهي) سان Externalizable، ڊيسيريلائيزيشن ميڪانيزم مختلف آهي. ڊفالٽ ڪنسٽرڪٽر کي پهريون سڏيو ويندو آهي، صرف ان کان پوء ٺاهيل UserInfoاعتراض جو readExternal()طريقو سڏيو ويندو آهي. اهو اعتراض جي فيلڊ کي ترتيب ڏيڻ جو ذميوار آهي. ان ڪري انٽرفيس کي لاڳو ڪرڻ واري ڪنهن به طبقي Externalizableکي هڪ ڊفالٽ ڪنسٽرڪٽر هجڻ گهرجي . اچو ته هڪ کي پنهنجي UserInfoڪلاس ۾ شامل ڪريون ۽ ڪوڊ ٻيهر هلايون:

import java.io.*;

public class Main {

   public static void main(String[] args) throws IOException, ClassNotFoundException {

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\save.ser");
       ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);


       UserInfo userInfo = (UserInfo) objectInputStream.readObject();
       System.out.println(userInfo);

       objectInputStream.close();
   }
}
ڪنسول آئوٽ: پال پائپر جي پاسپورٽ ڊيٽا UserInfo \ firstName = 'Paul', lastName = 'Piper', superSecretInformation = 'Paul Piper's passport data' } ھاڻي اھو ڪجھھ مختلف آھي! پهرين، ڳجهي معلومات سان گڏ ڊسڪ ٿيل اسٽرنگ ڪنسول تي ڏيکاريل هئي. پوءِ جيڪا شئي اسان فائل مان هٿ ڪئي اها اسٽرنگ طور ڏيکاري وئي! تنهنڪري اسان ڪاميابيءَ سان سڀني مسئلن کي حل ڪيو آهي :) سيريلائيزيشن ۽ ڊيسيريلائيزيشن جو موضوع سادو لڳي ٿو، پر، جيئن توهان ڏسي سگهو ٿا، سبق ڊگهو ٿي چڪو آهي. ۽ گهڻو ڪجهه آهي جيڪو اسان نه ڍڪيو آهي! اڃا به ڪيتريون ئي ذيلي ذخيري شامل آهن جڏهن انهن مان هر هڪ انٽرفيس کي استعمال ڪندي. پر توهان جي دماغ کي وڌيڪ نئين معلومات جي ڌماڪي کان بچڻ لاء، آئون مختصر طور تي ڪجهه وڌيڪ اهم نقطا لسٽ ڪندس ۽ توهان کي اضافي پڙهڻ لاء لنڪس ڏيندس. تنهن ڪري، ٻيو ڇا توهان کي ڄاڻڻ جي ضرورت آهي؟ پهريون ، سيريلائيزيشن دوران (قطع نظر توهان استعمال ڪري رهيا آهيو Serializableيا Externalizablestaticمتغيرن تي ڌيان ڏيو. جڏھن توھان استعمال ڪندا آھيو Serializable، اھي فيلڊ بلڪل سيريل نه آھن (۽، مطابق، انھن جا قدر تبديل نه ٿيندا آھن، ڇاڪاڻ⁠تہ staticشعبن جو تعلق طبقي سان آھي، اعتراض سان نه). پر جڏهن توهان استعمال ڪريو ٿا Externalizable، توهان پروسيس کي پاڻ سنڀاليو ٿا، تنهنڪري ٽيڪنيڪل طور تي توهان انهن کي ترتيب ڏئي سگهو ٿا. پر، اسان ان جي سفارش نٿا ڪريون، ڇاڪاڻ ته ائين ڪرڻ سان تمام گهڻا ذيلي ڪيڙا پيدا ٿيڻ جو امڪان آهي. ٻيو ، توهان کي پڻ ڌيان ڏيڻ گهرجي متغير سان finalتبديل ڪندڙ سان. جڏهن توهان استعمال ڪندا آهيو Serializable، اهي سيريلائيز ۽ ترتيب ڏنل آهن، پر جڏهن توهان استعمال ڪندا آهيو ، هڪ متغير Externalizableکي ختم ڪرڻ ناممڪن آهيfinal ! سبب سادو آهي: سڀ finalفيلڊ شروع ڪيا ويندا آهن جڏهن ڊفالٽ تعمير ڪندڙ کي سڏيو ويندو آهي - ان کان پوء، انهن جي قيمت تبديل نه ٿي سگهي. تنهن ڪري، شين کي سيريل ڪرڻ لاء جيڪي finalفيلڊ آهن، استعمال ڪريو معياري سيريلائيزيشن پاران مهيا ڪيل Serializable. ٽيون ، جڏهن توهان وراثت استعمال ڪندا آهيو، سڀني نسلن وارا طبقن جيڪي ڪجهه Externalizableطبقي کي ورثي ۾ آڻيندا آهن انهن وٽ پڻ ڊفالٽ تعمير ڪندڙ هوندا. هتي سيريلائيزيشن ميڪانيزم بابت سٺي مضمون جي لنڪ آهي: ٻئي دفعي تائين! :)
تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION