Kamusta! Sa artikulong ngayon, titingnan natin ang lumilipas na modifier sa Java. Pag-usapan natin kung bakit kailangan ang modifier na ito at kung paano ito gamitin nang tama. Go!
mga atom . Sumulat tayo ng paraan ang kahihiyan ng mga Espanyol Modifier (sa wakas)
May nalilito ba na na-save namin ang password ng user? Lalo na ang ganoong password... Oo, oo, kami mismo ang nakaisip nito, ngunit pa rin... Minsan may mga sitwasyon kung saan ang ilang mga patlang ay hindi mai-serialize, o mas mahusay na huwag gawin ito. Sa halimbawa sa itaas, gusto kong i-save ang lahat ng field maliban sa password. Paano ito makakamit? Sagot: gamitin ang modifier
Minsan ang ilang mga klase ay may mga field na kinakalkula batay sa iba pang mga field o iba pang impormasyon. Ang mga ito ay kalkulado, kaya na magsalita, sa mabilisang. Upang magbigay ng halimbawa ng ganoong larangan, isipin natin ang isang order sa isang online na tindahan o ilang serbisyo sa paghahatid ng pagkain. Ang bawat order, bukod sa iba pang impormasyon, ay binubuo ng isang listahan ng mga kalakal at isang kabuuang halaga. Ito naman ay binubuo ng kabuuang halaga ng bawat produkto. Ito ay lumalabas na ang pangwakas na gastos ay hindi dapat itakda "sa pamamagitan ng kamay": dapat itong kalkulahin sa programmatically, pagbubuod ng halaga ng lahat ng mga kalakal. Ang mga field na tulad nito na dapat kalkulahin sa programmatically ay hindi kailangang i-serialize. Samakatuwid, minarkahan namin sila ng isang modifier
Mayroon ding ilang mga klase na nag-iimbak ng pribadong impormasyon. Tiningnan namin ang isang halimbawa ng ganoong klase sa simula ng artikulo. Hindi mo dapat payagan ang naturang impormasyon na tumagas sa labas ng JVM. Samakatuwid, ang mga patlang na may ganoong data ay dapat na minarkahan ng isang modifier
Minsan ang isang klase ay naglalaman ng mga field - object ng ibang klase na hindi nagpapatupad ng interface
Well, isang huling bagay. Hindi na kailangang i-serialize ang mga field na hindi bahagi ng impormasyon ng estado ng object. Ang mga halimbawa sa itaas ay nasa ilalim ng panuntunang ito. Ngunit maaari mo ring isama dito ang lahat ng iba pang mga field na idinagdag para sa pag-debug o upang magsagawa ng ilang uri ng function ng serbisyo na hindi nagdadala ng impormasyon tungkol sa estado ng bagay.
Tandaan natin ang serialization
Ginagamit ang modifiertransient
sa proseso ng pagse-serialize at pag-deserialize ng mga bagay. Kaya't pag-usapan muna natin ito nang maikli. Ipagpalagay na mayroon kaming ilang bagay, at mayroon itong mga patlang, na ang bawat isa ay may ilang halaga. Ang lahat ng ito ay tinatawag na estado ng bagay. Ang serialization ay ang conversion ng estado ng isang object sa isang sequence ng mga byte. Ang mga byte na ito ay karaniwang nakaimbak sa ilang file. Ang deserialization ay ang kabaligtaran na proseso. Isipin natin na na-serialize natin ang isang bagay sa mga byte at iniimbak ang hanay ng mga byte na ito sa ilang file. Kapag deserializing, kailangan ng programa:
- Magbasa ng isang hanay ng mga byte mula sa isang file.
- Bumuo ng isang paunang bagay mula sa hanay ng mga byte na ito at itakda ang bawat field sa halaga na mayroon ang bagay sa oras ng serialization.
Tandaan natin ang serialization sa pagsasanay
Well, ngayon tingnan natin ang serialization sa pagsasanay. Kung gusto mong mas maunawaan ang paksa, inirerekomenda naming basahin ang materyal na Serialization at deserialization sa Java . Buweno, sa artikulong ito ay pupunta tayo sa itaas at dumiretso sa mga halimbawa. Sabihin nating mayroon tayong klaseUser
na may set ng ilang field, getter at setter, at isang paraan 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 + '\'' +
'}';
}
}
Gusto naming i-serialize ang mga bagay ng klase na ito sa hinaharap. Sumulat tayo ng isang pamamaraan na kumukuha ng isang bagay User
at isang string path
- ang landas sa file kung saan ise-save natin ang mga byte:
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();
}
}
}
Magsusulat din kami ng isang paraan para sa deserialization. Ang pamamaraan ay tumatagal ng isang string path
(ang landas patungo sa file kung saan ang bagay ay "mai-load") at nagbabalik ng isang bagay na may uri 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();
}
}
}
Ang lahat ng mga tool ay handa nang gamitin. Oras na para hatiin ang mga byte sa main
kung saan gumagawa tayo ng object ng klase User
at i-serialize ito. Pagkatapos ay ilo-load namin ito at ihahambing sa kung ano ang orihinal:
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");
}
Kung patakbuhin natin ang pamamaraan, makikita natin ang sumusunod na output:
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'}
Tulad ng nakikita mo mula sa output, ang mga bagay ay magkapareho. Ngunit may maliit ngunit... At dito mismo pumapasok transient
.
Modifier (sa wakas)transient
May nalilito ba na na-save namin ang password ng user? Lalo na ang ganoong password... Oo, oo, kami mismo ang nakaisip nito, ngunit pa rin... Minsan may mga sitwasyon kung saan ang ilang mga patlang ay hindi mai-serialize, o mas mahusay na huwag gawin ito. Sa halimbawa sa itaas, gusto kong i-save ang lahat ng field maliban sa password. Paano ito makakamit? Sagot: gamitin ang modifier transient
. transient
ay isang modifier na inilagay bago ang isang field ng klase (katulad ng iba pang mga modifier tulad ng public
, final
atbp.) upang ipahiwatig na ang field ay hindi dapat na serialized. Ang mga field na minarkahan ng keyword transient
ay hindi serialized. Ngayon, i-edit natin ang halimbawa kasama ang ating user upang itama ang isang maliit na kalituhan at hindi i-save ang password ng user. Upang gawin ito, markahan ang kaukulang field sa klase gamit ang keyword 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...
*/
}
Kung patakbuhin namin ang pamamaraan mula sa halimbawa sa itaas muli main
, makikita namin na ang password ay hindi nai-save:
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'}
Mahusay, nakamit namin ang aming layunin at hindi nag-iimbak ng kumpidensyal na impormasyon. Lalo na ang ganitong uri ng impormasyon... (sorry)
Kailan gagamitin ang transient?
Ang isang halimbawa sa isang user ay kailangan upang sumisid sa konteksto ng serialization. Ngayon, pag-usapan natin nang mas partikular kung kailan gagamitin ang modifiertransient
.
- Mga field na kinakalkula gamit ang programmatically
Minsan ang ilang mga klase ay may mga field na kinakalkula batay sa iba pang mga field o iba pang impormasyon. Ang mga ito ay kalkulado, kaya na magsalita, sa mabilisang. Upang magbigay ng halimbawa ng ganoong larangan, isipin natin ang isang order sa isang online na tindahan o ilang serbisyo sa paghahatid ng pagkain. Ang bawat order, bukod sa iba pang impormasyon, ay binubuo ng isang listahan ng mga kalakal at isang kabuuang halaga. Ito naman ay binubuo ng kabuuang halaga ng bawat produkto. Ito ay lumalabas na ang pangwakas na gastos ay hindi dapat itakda "sa pamamagitan ng kamay": dapat itong kalkulahin sa programmatically, pagbubuod ng halaga ng lahat ng mga kalakal. Ang mga field na tulad nito na dapat kalkulahin sa programmatically ay hindi kailangang i-serialize. Samakatuwid, minarkahan namin sila ng isang modifier transient
.
class Order implements Serializable {
private List- items;
private transient BigDecimal totalAmount; //вычисляется на ходу
}
- Mga field na may pribadong impormasyon
Mayroon ding ilang mga klase na nag-iimbak ng pribadong impormasyon. Tiningnan namin ang isang halimbawa ng ganoong klase sa simula ng artikulo. Hindi mo dapat payagan ang naturang impormasyon na tumagas sa labas ng JVM. Samakatuwid, ang mga patlang na may ganoong data ay dapat na minarkahan ng isang modifier transient
kung ikaw ay magse-serialize ng ganoong klase.
- Mga field na hindi nagpapatupad ng interface
Serializable
Minsan ang isang klase ay naglalaman ng mga field - object ng ibang klase na hindi nagpapatupad ng interface Serializable
Serializable
. Ang mga halimbawa ng naturang mga field ay mga logger, I/O stream, mga bagay na nag-iimbak ng mga koneksyon sa database at iba pang mga utility class. Kung susubukan mong i-serialize ang isang object na naglalaman ng mga non-serialize na field, makakatanggap ka ng error java.io.NotSerializableException
. Upang maiwasan ito, ang lahat ng mga patlang na hindi nagpapatupad ng interface Serializable
ay dapat na markahan ng isang modifier 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();
}
}
}
}
- Mga patlang na may impormasyon tungkol sa estado ng bagay
Well, isang huling bagay. Hindi na kailangang i-serialize ang mga field na hindi bahagi ng impormasyon ng estado ng object. Ang mga halimbawa sa itaas ay nasa ilalim ng panuntunang ito. Ngunit maaari mo ring isama dito ang lahat ng iba pang mga field na idinagdag para sa pag-debug o upang magsagawa ng ilang uri ng function ng serbisyo na hindi nagdadala ng impormasyon tungkol sa estado ng bagay.
transient
Atfinal
Mga resulta
Iyon lang. Ngayon ay pinag-usapan natin ang modifiertransient
:
- Naalala namin ang serialization sa teorya at kasanayan.
- Napagtanto namin na upang hindi ma-serialize ang ilang mga field ng klase, kailangan nilang markahan ng modifier
transient
. - Tinalakay namin kung anong mga sitwasyon ang dapat gamitin ng modifier na ito. Mayroong apat na ganoong sitwasyon:
- mga patlang na kinakalkula gamit ang program;
- mga patlang na naglalaman ng lihim na impormasyon;
- mga patlang na hindi nagpapatupad ng interface
Serializable
; - mga field na hindi bahagi ng estado ng object.
GO TO FULL VERSION