Serializable
அதன் வேலையைச் செய்தது, முழு செயல்முறையையும் தானாகச் செயல்படுத்துவதைப் பற்றி விரும்பாதது எது? மேலும் நாம் பார்த்த உதாரணங்களும் சிக்கலற்றவை. அதனால் என்ன பிரச்சனை? அதே பணிகளுக்கு நமக்கு ஏன் மற்றொரு இடைமுகம் தேவை? Serializable
இதில் பல குறைபாடுகள் உள்ளன என்பதே உண்மை . அவற்றில் சிலவற்றை நாங்கள் பட்டியலிடுகிறோம்:
-
செயல்திறன். இடைமுகம்
Serializable
பல நன்மைகளைக் கொண்டுள்ளது, ஆனால் உயர் செயல்திறன் தெளிவாக அவற்றில் ஒன்று அல்ல.முதலாவதாக,
Serializable
இன் உள் செயலாக்கமானது பெரிய அளவிலான சேவைத் தகவல்களையும் அனைத்து வகையான தற்காலிகத் தரவையும் உருவாக்குகிறது.இரண்டாவதாக,
Serializable
பிரதிபலிப்பு API ஐ நம்பியுள்ளது (இப்போது நீங்கள் இதை ஆழமாகப் படிக்க வேண்டியதில்லை; நீங்கள் ஆர்வமாக இருந்தால், உங்கள் ஓய்வு நேரத்தில் மேலும் படிக்கலாம்). ஜாவாவில் சாத்தியமற்றதாகத் தோன்றும் விஷயங்களைச் செய்ய இது உங்களை அனுமதிக்கிறது: எடுத்துக்காட்டாக, தனிப்பட்ட புலங்களின் மதிப்புகளை மாற்றவும். CodeGym இல் பிரதிபலிப்பு API பற்றிய சிறந்த கட்டுரை உள்ளது . அதைப் பற்றி நீங்கள் அங்கு படிக்கலாம். -
நெகிழ்வுத்தன்மை. இடைமுகத்தைப் பயன்படுத்தும் போது சீரியலைசேஷன்-டீரியலைசேஷன் செயல்முறையை நாங்கள் கட்டுப்படுத்த மாட்டோம்
Serializable
.ஒருபுறம், இது மிகவும் வசதியானது, ஏனென்றால் செயல்திறனைப் பற்றி நாம் குறிப்பாக அக்கறை காட்டவில்லை என்றால், குறியீட்டை எழுத வேண்டிய அவசியமில்லை. ஆனால், வரிசைப்படுத்தல் தர்க்கத்தில் நம்முடைய சில அம்சங்களை (கீழே ஒரு உதாரணம் தருவோம்) சேர்க்க வேண்டுமானால் என்ன செய்வது?
அடிப்படையில், செயல்முறையை நாம் கட்டுப்படுத்த வேண்டியதெல்லாம்
transient
சில தரவை விலக்குவதற்கான முக்கிய வார்த்தையாகும். அவ்வளவுதான். இது எங்கள் முழு கருவிப்பெட்டி :/ -
பாதுகாப்பு. இந்த உருப்படி முந்தைய உருப்படியிலிருந்து ஓரளவு பெறப்பட்டது.
இதற்கு முன்பு நாங்கள் இதைப் பற்றி அதிகம் சிந்திக்கவில்லை, ஆனால் உங்கள் வகுப்பில் உள்ள சில தகவல்கள் மற்றவர்களின் துருவியறியும் கண்கள் மற்றும் காதுகளை நோக்கமாகக் கொண்டிருக்கவில்லை என்றால் என்ன செய்வது? ஒரு எளிய உதாரணம் ஒரு கடவுச்சொல் அல்லது பிற தனிப்பட்ட பயனர் தரவு, இது இன்றைய உலகில் பல சட்டங்களால் நிர்வகிக்கப்படுகிறது.
நாம் பயன்படுத்தினால்
Serializable
, அதைப் பற்றி எதுவும் செய்ய முடியாது. எல்லாவற்றையும் அப்படியே தொடர்கிறோம்.ஆனால் நாம் அதைச் சரியாகச் செய்தால், இந்த வகையான தரவை ஒரு கோப்பில் எழுதும் முன் அல்லது நெட்வொர்க்கில் அனுப்பும் முன் அதை குறியாக்கம் செய்ய வேண்டும். ஆனால்
Serializable
இதை சாத்தியப்படுத்துவதில்லை.
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();
}
}
சரி, இங்கே எதுவும் சிக்கலானதாகத் தெரியவில்லை. அது வேலை செய்ய வேண்டும்! நாங்கள் அதை இயக்கி பெறுகிறோம்... இழை "முக்கிய" java.io இல் விதிவிலக்கு.InvalidClassException: UserInfo; சரியான கட்டமைப்பாளர் இல்லை அச்சச்சோ! :( வெளிப்படையாக, இது அவ்வளவு எளிதானது அல்ல! டீரியலைசேஷன் பொறிமுறையானது ஒரு விதிவிலக்கை எறிந்து, ஒரு இயல்புநிலை கட்டமைப்பாளரை உருவாக்குமாறு கோரியது. ஏன் என்று எனக்கு ஆச்சரியமாக இருக்கிறது. உடன் , Serializable
நாங்கள் ஒன்று இல்லாமல் செய்தோம்... :/ இங்கே நாம் மற்றொரு முக்கியமான நுணுக்கத்தை சந்தித்தோம். இடையே உள்ள வேறுபாடு Serializable
மற்றும் Externalizable
புரோகிராமரின் 'விரிவாக்கப்பட்ட' அணுகல் மற்றும் செயல்முறையை மிகவும் நெகிழ்வாகக் கட்டுப்படுத்தும் திறனில் மட்டுமல்ல, செயல்முறையிலும் உள்ளது. எல்லாவற்றிற்கும் மேலாக, டீரியலைசேஷன் பொறிமுறையில் . பயன்படுத்தும் போதுSerializable
, நினைவகம் வெறுமனே பொருளுக்கு ஒதுக்கப்படுகிறது, பின்னர் மதிப்புகள் ஸ்ட்ரீமில் இருந்து படிக்கப்பட்டு பொருளின் புலங்களை அமைக்கப் பயன்படுகிறது. நாம் பயன்படுத்தினால் Serializable
, பொருளின் கட்டமைப்பாளர் அழைக்கப்படுவதில்லை! அனைத்து வேலைகளும் பிரதிபலிப்பு மூலம் நடக்கும் (பிரதிபலிப்பு ஏபிஐ, கடந்த பாடத்தில் சுருக்கமாக குறிப்பிட்டோம்). உடன் 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 இன் பாஸ்போர்ட் தரவு' } இப்போது அது முற்றிலும் வேறுபட்டது! முதலில், மறைகுறியாக்கப்பட்ட சரம் இரகசிய தகவலுடன் கன்சோலில் காட்டப்பட்டது. பின்னர் நாம் கோப்பிலிருந்து மீட்டெடுத்த பொருள் சரமாக காட்டப்பட்டது! எனவே நாங்கள் எல்லா பிரச்சனைகளையும் வெற்றிகரமாக தீர்த்துவிட்டோம் :) தொடர் மற்றும் சீரியலைசேஷன் தலைப்பு எளிமையானதாகத் தெரிகிறது, ஆனால், நீங்கள் பார்க்கிறபடி, பாடங்கள் நீண்டவை. மேலும் நாங்கள் மறைக்காத பல உள்ளன! இந்த இடைமுகங்கள் ஒவ்வொன்றையும் பயன்படுத்தும் போது இன்னும் பல நுணுக்கங்கள் உள்ளன. ஆனால் அதிகப்படியான புதிய தகவல்களால் உங்கள் மூளை வெடிப்பதைத் தவிர்க்க, நான் இன்னும் சில முக்கியமான விஷயங்களை சுருக்கமாக பட்டியலிடுகிறேன் மற்றும் கூடுதல் வாசிப்புக்கான இணைப்புகளை உங்களுக்கு தருகிறேன். எனவே, நீங்கள் வேறு என்ன தெரிந்து கொள்ள வேண்டும்? முதலாவதாக , வரிசைப்படுத்தலின் போது (நீங்கள் பயன்படுத்துகிறீர்களா Serializable
அல்லது Externalizable
) மாறிகளுக்கு கவனம் செலுத்துங்கள் static
. நீங்கள் பயன்படுத்தும் போது Serializable
, இந்த புலங்கள் வரிசைப்படுத்தப்படுவதில்லை (அதன்படி, அவற்றின் மதிப்புகள் மாறாது, ஏனெனில் static
புலங்கள் வகுப்பைச் சார்ந்தவை, பொருளுக்கு அல்ல). ஆனால் நீங்கள் பயன்படுத்தும் போதுExternalizable
, செயல்முறையை நீங்களே கட்டுப்படுத்துகிறீர்கள், எனவே தொழில்நுட்ப ரீதியாக நீங்கள் அவற்றை வரிசைப்படுத்தலாம். ஆனால், நாங்கள் அதை பரிந்துரைக்கவில்லை, ஏனெனில் செய்வது பல நுட்பமான பிழைகளை உருவாக்கும். இரண்டாவதாக , மாற்றியமைப்புடன் மாறிகள் மீதும் நீங்கள் கவனம் செலுத்த வேண்டும் final
. நீங்கள் பயன்படுத்தும் போது Serializable
, அவை வழக்கம் போல் சீரியல் மற்றும் டீரியலைஸ் செய்யப்படுகின்றன, ஆனால் நீங்கள் பயன்படுத்தும் போது , ஒரு மாறியை Externalizable
நீக்குவது சாத்தியமில்லைfinal
! காரணம் எளிதானது: final
இயல்புநிலை கட்டமைப்பாளர் அழைக்கப்படும் போது அனைத்து புலங்களும் துவக்கப்படும் - அதன் பிறகு, அவற்றின் மதிப்பை மாற்ற முடியாது. எனவே, புலங்களைக் கொண்ட பொருட்களை வரிசைப்படுத்த final
, வழங்கிய நிலையான வரிசைப்படுத்தலைப் பயன்படுத்தவும் Serializable
. மூன்றாவதாக , நீங்கள் பரம்பரையைப் பயன்படுத்தும் போது, சிலவற்றைப் பெறுகின்ற அனைத்து சந்ததி வகுப்புகளும்Externalizable
வகுப்பில் இயல்புநிலை கட்டமைப்பாளர்களும் இருக்க வேண்டும். வரிசைப்படுத்தல் வழிமுறைகள் பற்றிய நல்ல கட்டுரைக்கான இணைப்பு இங்கே:
அடுத்த முறை வரை! :)
GO TO FULL VERSION