JavaRush /Java blogi /Random-UZ /Java-da yakuniy, doimiy va o'zgarmas

Java-da yakuniy, doimiy va o'zgarmas

Guruhda nashr etilgan
Salom! "Modifikator" so'zi sizga allaqachon tanish. Hech bo'lmaganda siz kirish modifikatorlari (ommaviy, shaxsiy) va statik modifikatorga duch keldingiz. Bugun biz maxsus yakuniy modifikator haqida gaplashamiz . Aytish mumkinki, dasturimizning doimiy, aniq va o'zgarmas xulq-atvorga muhtoj bo'lgan sohalarini "tsementlash". U bizning dasturimizning uchta sohasida qo'llanilishi mumkin: sinflar, usullar va o'zgaruvchilar. Java-da o'zgarmas: final, konstantalar va o'zgarmas - 2 Keling, ularni birma-bir ko'rib chiqaylik. Agar sinf deklaratsiyasi yakuniy modifikatorni o'z ichiga olsa , bu siz ushbu sinfdan meros bo'lolmaysiz degan ma'noni anglatadi. Oldingi ma'ruzalarda biz merosning oddiy misolini ko'rdik: bizda ota-onalar sinfi Animalva ikkita bolalar sinfi bor edi - CatvaDog
public class Animal {
}

public class Cat extends Animal {
   //..поля и методы класса Cat
}

public class Dog extends Animal {

   //..поля и методы класса Dog
}
Biroq, agar biz sinf uchun Animalmodifikatorni belgilasak, sinflar ham undan finalmeros bo'la olmaydi . CatDog
public final class Animal {

}

public class Cat extends Animal {

   //ошибка! Cannot inherit from final Animal
}
Kompilyator darhol xatoga yo'l qo'yadi. Java-da allaqachon amalga oshirilgan ko'plab sinflar mavjud final. Siz doimo foydalanadigan eng mashhuri String. Bundan tashqari, agar sinf deb e'lon qilinsa final, uning barcha usullari ham ga aylanadi final. Bu nima degani? Agar usul uchun modifikator belgilangan bo'lsa final, bu usulni bekor qilib bo'lmaydi. AnimalMisol uchun, bizda metodni belgilaydigan sinf mavjud voice(). Biroq, itlar va mushuklar boshqacha tarzda "gapirishadi". Shuning uchun, har bir sinfda - Catva Dog- biz usul yaratamiz voice(), lekin biz uni boshqacha amalga oshiramiz.
public class Animal {

   public void voice() {
       System.out.println("Voice!");
   }
}

public class Cat extends Animal {

   @Override
   public void voice() {
       System.out.println("Meow!");
   }
}

public class Dog extends Animal {

   @Override
   public void voice() {
       System.out.println("Woof!");
   }
}
Sinflarda Catva Dogbiz ota-ona sinfining usulini bekor qildik. Endi hayvon qaysi sinf ob'ektiga qarab ovoz chiqaradi:
public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       Dog dog = new Dog();

       cat.voice();
       dog.voice();
   }
}
Xulosa: Miyav! Voy! Biroq, agar biz sinfdagi Animalusulni deb e'lon qilsak , uni boshqa sinflarda qayta belgilash mumkin bo'lmaydi: voice()final
public class Animal {

   public final void voice() {
       System.out.println("Voice!");
   }
}


public class Cat extends Animal {

   @Override
   public void voice() {//ошибка! final-метод не может быть переопределен!
       System.out.println("Meow!");
   }
}
voice()Keyin bizning ob'ektlarimiz ota-sinfda belgilangan usuldan foydalanishga majbur bo'ladi :
public static void main(String[] args) {

   Cat cat = new Cat();
   Dog dog = new Dog();

   cat.voice();
   dog.voice();
}
Xulosa: Ovoz! Ovoz! Endi final-o'zgaruvchilar haqida. Aks holda ular doimiylar deb ataladi . Birinchidan (va eng muhimi), doimiyga tayinlangan birinchi qiymatni o'zgartirib bo'lmaydi. U bir marta va abadiy tayinlanadi.
public class Main {

   private static final int CONSTANT_EXAMPLE = 333;

   public static void main(String[] args) {

       CONSTANT_EXAMPLE = 999;//ошибка! Нельзя присвоить новое meaning final-переменной!
   }
}
Konstantani darhol ishga tushirish kerak emas. Buni keyinroq qilish mumkin. Lekin birinchi tayinlangan qiymat abadiy qoladi.
public static void main(String[] args) {

   final int CONSTANT_EXAMPLE;

   CONSTANT_EXAMPLE = 999;//так делать можно
}
Ikkinchidan, o'zgaruvchimiz nomiga e'tibor bering. Java konstantalarida boshqa nomlash konventsiyasi mavjud. Bu biz o'rganib qolgan tuya qutisi emas. Muntazam o'zgaruvchi bo'lsa, biz uni doimiyMisol deb atagan bo'lardik, lekin doimiylarning nomlari bosh harflar bilan yoziladi va so'zlar orasida (agar ular bir nechta bo'lsa) pastki chiziq qo'yiladi - "CONSTANT_EXAMPLE". Nima uchun doimiylar kerak? Misol uchun, agar siz doimiy ravishda dasturda doimiy qiymatdan foydalansangiz, ular foydali bo'ladi. Aytaylik, siz tarixga kirishga va yolg'iz "The Witcher 4" o'yinini yozishga qaror qildingiz. O'yin doimiy ravishda bosh qahramonning nomini ishlatadi - "Riviya Geralti". Ushbu qatorni va boshqa qahramonlarning ismlarini doimiyga ajratish yaxshiroqdir: sizga kerak bo'lgan qiymat bir joyda saqlanadi va siz uni millioninchi marta yozishda xato qilmaysiz.
public class TheWitcher4 {

   private static final String GERALT_NAME = "Геральт из Ривии";
   private static final String YENNEFER_NAME = "Йеннифэр из Венгерберга";
   private static final String TRISS_NAME = "Трисс Меригольд";

   public static void main(String[] args) {

       System.out.println("Ведьмак 4");
       System.out.println("Это уже четвертая часть Ведьмака, а " + GERALT_NAME + " ниHow не определится кто ему" +
               " нравится больше: " + YENNEFER_NAME + " or " + TRISS_NAME);

       System.out.println("Но если вы никогда не играли в Ведьмака - начнем сначала.");
       System.out.println("Главного героя зовут " + GERALT_NAME);
       System.out.println(GERALT_NAME + " - ведьмак, охотник на чудовищ");
   }
}
Xulosa:
Ведьмак 4
Это уже четвертая часть Ведьмака, а Геральт из Ривии ниHow не определится, кто ему нравится больше: Йеннифэр из Венгерберга or Трисс Меригольд.
Но если вы никогда не играли в Ведьмака — начнем сначала.
Главного героя зовут Геральт из Ривии
Геральт из Ривии — ведьмак, охотник на чудовищ
Biz belgilar nomini doimiylarga ajratdik va endi biz ularni albatta noto'g'ri yozmaymiz va ularni har safar qo'lda yozishga hojat qolmaydi. Yana bir ortiqcha: agar oxir-oqibat dastur davomida o'zgaruvchining qiymatini o'zgartirishimiz kerak bo'lsa, uni butun kod bo'ylab qo'lda takrorlash o'rniga, uni bir joyda qilish kifoya :)

O'zgarmas turlar

Java-da ishlagan vaqtingizda, ehtimol, dasturchi barcha ob'ektlarning holatini deyarli to'liq nazorat qilishiga o'rganib qolgandirsiz. Wanted - yaratilgan ob'ekt Cat. Agar xohlasam, nomini o'zgartirdim. Agar xohlasa, yoshini o'zgartirdi, yoki boshqa narsa. Ammo Java-da maxsus holatga ega bo'lgan bir nechta ma'lumotlar turlari mavjud. Ular o'zgarmas yoki o'zgarmasdir . Bu shuni anglatadiki, agar sinf o'zgarmas bo'lsa, uning ob'ektlarining holatini o'zgartirib bo'lmaydi. Misollar? Siz hayron bo'lishingiz mumkin, lekin Immutable sinfining eng mashhur namunasi String! Biz satr qiymatini o'zgartira olmayotganga o'xshaymizmi? Kel urinib ko'ramiz:
public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;//обе переменные-ссылки указывают на одну строку.
   System.out.println(str2);

   str1 = "I love Python";//но поведение str1 ниHow не влияет на str2
   System.out.println(str2);//str2 продолжает указывать на строку "I love Java", хотя str1 уже указывает на другой an object
}
Xulosa: Men Java-ni yaxshi ko'raman Men Java-ni yaxshi ko'raman, biz yozganimizdan keyin:
str1 = "I love Python";
"I love Java" qatorli ob'ekt o'zgarmadi va hech qaerga ketmadi. U xavfsiz tarzda mavjud va ichida avvalgidek xuddi shunday matn mavjud. Kod:
str1 = "I love Python";
faqat boshqa ob'ekt yaratdi va endi o'zgaruvchi str1unga ishora qiladi. Ammo biz "Men Java-ni yaxshi ko'raman" ob'ektiga hech qanday ta'sir qila olmaymiz. Mayli, keling, boshqacha qilib ko'raylik! Sinf Stringusullar bilan to'la va ularning ba'zilari qator holatini o'zgartirganga o'xshaydi! Misol uchun, bir usul mavjud replace(). Keling, qatorimizdagi “Java” so‘zini “Python” so‘ziga almashtiraylik!
public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;//обе переменные-ссылки указывают на одну строку.
   System.out.println(str2);

   str1.replace("Java", "Python");//попробуем изменить состояние str1, заменив слово "Java" на “Python”
   System.out.println(str2);
}
Xulosa: Men Java-ni yaxshi ko'raman Men Java-ni yaxshi ko'raman, yana ishlamadi! Ehtimol, egri chiziq usuli ishlamaydi? Keling, boshqasini sinab ko'raylik. Masalan, substring(). Uzatilgan belgilar raqamlari asosida satrni kesadi. Keling, o'zimiznikini dastlabki 10 ta belgiga qisqartiramiz:
public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;//обе переменные-ссылки указывают на одну строку.
   System.out.println(str2);

   str1.substring(10);//обрезаем исходную строку
   System.out.println(str2);
}
Xulosa: Men Java-ni yaxshi ko'raman Men Java-ni yaxshi ko'raman Java-da o'zgarmas: final, konstantalar va o'zgarmas - 3 Hech narsa o'zgarmadi. Va bo'lmasligi kerak. Aytganimizdek, ob'ektlar Stringo'zgarmasdir. Xo'sh, bu sinf usullari nima String? Ular chiziqni kesishi, undagi belgilarni o'zgartirishi va hokazo. Hech narsa bo'lmasa, ular nima uchun kerak? Ularning qo'lidan keladi! Lekin ular har safar yangi string ob'ektini qaytaradilar. Yozishdan foyda yo'q:
str1.replace("Java", "Python");
- siz asl ob'ektni o'zgartirmaysiz. Ammo agar siz usul natijasini yangi mos yozuvlar o'zgaruvchisiga yozsangiz, darhol farqni ko'rasiz!
public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;//обе переменные-ссылки указывают на одну строку.
   System.out.println(str2);

   String str1AfterReplacement =  str1.replace("Java", "Python");
   System.out.println(str2);

   System.out.println(str1AfterReplacement);
}
Bu usullarning barchasi faqat shu tarzda Stringishlaydi. “I love Java” obyekti bilan hech narsa qila olmaysiz . Shunchaki yangi ob'ekt yarating va yozing: "Yangi ob'ekt = "Men Java-ni yaxshi ko'raman" ob'ekti bilan ba'zi manipulyatsiyalar natijasi ." Yana qanday turlar o'zgarmasdir? Siz aniq eslab qolishingiz kerak bo'lgan narsadan - ibtidoiy turlarga nisbatan barcha o'rash sinflari o'zgarmasdir. Integer, Byte, Character, Short, Boolean, Long, Double, Float- bu sinflarning barchasi O'zgarmas ob'ektlarni yaratadi. Bunga katta sonlarni yaratish uchun ishlatiladigan sinflar ham kiradi - BigIntegerva BigDecimal. Biz yaqinda istisnolardan o'tdik va ularga tegdik StackTrace. Shunday qilib: java.lang.StackTraceElement sinfining ob'ektlari ham o'zgarmasdir. Bu mantiqan to'g'ri: agar kimdir bizning stekimizdagi ma'lumotlarni o'zgartira olsa, u bilan barcha ishlarni bekor qilishi mumkin. Tasavvur qiling, kimdir StackTrace- ga kirib , OutOfMemoryError- ni FileNotFoundException- ga o'zgartiradi . Va siz ushbu stek bilan ishlashingiz va xatoning sababini izlashingiz kerak. Va dastur fayllardan umuman foydalanmaydi :) Shuning uchun, xavfsiz tomonda bo'lish uchun bu ob'ektlar o'zgarmas qilib qo'yilgan. Xo'sh, StackTraceElement bilan bu ko'proq yoki kamroq aniq. Nima uchun kimdir satrlarni o'zgarmas qilishni xohlaydi? Agar ularning qadriyatlarini o'zgartirish mumkin bo'lsa, qanday muammo bo'lar edi. Ehtimol, bu yanada qulayroq bo'lar edi :/ Buning bir qancha sabablari bor. Birinchidan, xotirani tejash. O'zgarmas satrlarni joylashtirish mumkin String Poolva har safar yangilarini yaratish o'rniga bir xillardan foydalanish mumkin. Ikkinchidan, xavfsizlik. Misol uchun, har qanday dasturdagi login va parollarning aksariyati qatorlardir. Ularni o'zgartirish imkoniyati avtorizatsiya bilan bog'liq muammolarga olib kelishi mumkin. Boshqa sabablar ham bor, lekin biz hali Java tilini o'rganishda ularga erisha olmadik - keyinroq qaytamiz.
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION