JavaRush /Java blogi /Random-UZ /8 dan 13 gacha: Java versiyalarining to'liq ko'rinishi. 1...

8 dan 13 gacha: Java versiyalarining to'liq ko'rinishi. 1-qism

Guruhda nashr etilgan
Mushukchalar, hammaga salom)) Demak, bugun biz 2020-yildamiz va Java 14 chiqishiga juda oz vaqt qoldi. Yakunlangan versiyani 17-mart kuni kutishingiz kerak, biz u erda nima yangi va qiziqarli ekanligini tahlil qilamiz, ammo bugun men Java-ning oldingi versiyalarida xotiramni yangilamoqchiman. Ular bizga qanday yangilik keltirdilar? Keling, ko'rib chiqaylik. Keling, ko'rib chiqishni Java 8 bilan boshlaylik, chunki u hali ham juda dolzarb va ko'pgina loyihalarda qo'llaniladi. 8 dan 13 gacha: Java versiyalarining to'liq ko'rinishi.  1-1-qismIlgari yangi versiyalar har 3-5 yilda bir marta chiqarilar edi, ammo yaqinda Oracle boshqacha yondashuvni qo'lladi - "har olti oyda yangi Java". Shunday qilib, har olti oyda biz xususiyatlarning chiqarilishini ko'ramiz. Bu yaxshi yoki yomonmi, har kim buni har xil ko'radi. Masalan, menga bu unchalik yoqmaydi, chunki yangi versiyalarda yangi xususiyatlar ko'p emas, lekin shu bilan birga versiyalar yomg'irdan keyin qo'ziqorin kabi o'sib bormoqda. Men Java 8 bilan loyihada bir necha marta miltilladim va Java 16 allaqachon chiqarilgan edi (lekin u kamdan-kam hollarda paydo bo'lganda, yangi xususiyatlar to'planadi va oxirida bu voqea bayram kabi uzoq kutiladi: hamma uni muhokama qilmoqda. yangi sovg'alar va siz undan o'tib ketolmaysiz). Shunday ekan, boshlaylik!

Java 8

Funktsional interfeys

Nima bu? Funktsional interfeys - bu bitta bajarilmagan (mavhum) usulni o'z ichiga olgan interfeys. @FunctionalInterface - bunday interfeys ustida joylashgan ixtiyoriy izoh. Funktsional interfeys talablariga javob berishini tekshirish uchun kerak (faqat bitta mavhum usulga ega). Lekin har doimgidek, bizda ba'zi ogohlantirishlar bor: standart va statik usullar bu talablarga kirmaydi. Shuning uchun bunday usullar bir nechta bo'lishi mumkin + bitta mavhum va interfeys funktsional bo'ladi. Shuningdek, u Object sinfining interfeysning funktsional sifatida ta'rifiga ta'sir qilmaydigan usullarini o'z ichiga olishi mumkin. Standart va statik usullar haqida bir necha so'z qo'shaman:
  1. Standart modifikatorga ega bo'lgan usullar interfeyslarga mavjud ilovalarni buzmasdan yangi usullarni qo'shish imkonini beradi.

    public interface Something {
      default void someMethod {
          System.out.println("Some text......");
      }
    }

    Ha, ha, biz amalga oshirilgan usulni interfeysga qo'shamiz va bu usulni amalga oshirayotganda siz uni bekor qila olmaysiz, lekin uni meros qilib olingan usul sifatida ishlating. Ammo agar sinf berilgan usul bilan ikkita interfeysni amalga oshirsa, bizda kompilyatsiya xatosi bo'ladi va agar u interfeyslarni amalga oshirsa va ma'lum bir o'xshash usulga ega sinfni meros qilib olsa, ota-klass usuli interfeys usullari bilan bir-biriga yopishadi va istisno ishlamaydi.

  2. interfeysdagi statik usullar sinfdagi statik usullar bilan bir xil ishlaydi. Unutmang: siz statik usullarni meros qilib olmaysiz, xuddi avlod sinfidan statik usulni chaqira olmaganingizdek.

Shunday qilib, funktsional interfeyslar haqida yana bir necha so'z va keling, davom etamiz. Mana FIning asosiy ro'yxati (qolganlari ularning navlari):

    Predikat - argument sifatida T qiymatini oladi, mantiqiy qiymatni qaytaradi.

    Misol:boolean someMethod(T t);

  • Iste'molchi - T tipidagi argumentni oladi, hech narsa qaytarmaydi (yaroqsiz).

    Misol:void someMethod(T t);

  • Yetkazib beruvchi - kirish sifatida hech narsani qabul qilmaydi, lekin T qiymatini qaytaradi.

    Misol:T someMethod();

  • Funktsiya - kirish sifatida T tipidagi parametrni oladi, R tipidagi qiymatni qaytaradi.

    Misol:R someMethod(T t);

  • UnaryOperator - T argumentini oladi va T tipidagi qiymatni qaytaradi.

    Misol:T someMethod(T t);

Oqim

Streams - bu ma'lumotlar tuzilmalarini funktsional uslubda boshqarish usuli. Odatda bu to'plamlar (lekin siz ularni boshqa, kamroq tarqalgan holatlarda ishlatishingiz mumkin). Tushunarliroq tilda aytganda, Stream - bu har birida bo'lgani kabi qo'pol kuch emas, balki bir vaqtning o'zida barcha ma'lumotlar bilan ishlaydigandek ishlov beradigan ma'lumotlar oqimi. Keling, kichik bir misolni ko'rib chiqaylik. Aytaylik, bizda filtrlash (50 dan kam), 5 ga oshirish va qolgan raqamlardan birinchi 4 ta raqamni konsolga chiqarishni istagan raqamlar to'plami bor. Biz buni avvalroq qanday qilgan bo'lardik:
List<Integer> list = Arrays.asList(46, 34, 24, 93, 91, 1, 34, 94);

int count = 0;

for (int x : list) {

  if (x >= 50) continue;

  x += 5;

  count++;

  if (count > 4) break;

  System.out.print(x);

}
Ko'p kod yo'qdek tuyuladi va mantiq allaqachon biroz chalkash. Keling, oqim yordamida qanday ko'rinishini ko'rib chiqaylik:
Stream.of(46, 34, 24, 93, 91, 1, 34, 94)

      .filter(x -> x < 50)

      .map(x -> x + 5)

      .limit(4)

      .forEach(System.out::print);
Oqimlar kod miqdorini kamaytirish va uni yanada o'qilishi mumkin qilish orqali hayotni sezilarli darajada soddalashtiradi. Ushbu mavzuni batafsilroq o'rganmoqchi bo'lganlar uchun bu mavzu bo'yicha yaxshi (hatto juda zo'r deb aytaman) maqola .

Lambda

Ehtimol, eng muhim va uzoq kutilgan xususiyat - lambdalarning paydo bo'lishi. Lambda nima? Bu turli joylarga uzatilishi mumkin bo'lgan kod blokidir, shuning uchun uni keyinchalik kerak bo'lganda ko'p marta bajarish mumkin. Juda chalkash tuyuladi, shunday emasmi? Oddiy qilib aytganda, lambdalardan foydalanib, siz funktsional interfeys usulini (anonim sinfni amalga oshirish turini) amalga oshirishingiz mumkin:
Runnable runnable = () -> { System.out.println("I'm running !");};

new Thread(runnable).start();
Biz run() usulini tez va keraksiz qog'ozlarsiz amalga oshirdik. Va ha: Runnable - bu funktsional interfeys. Oqimlar bilan ishlashda men ham lambdalardan foydalanaman (yuqoridagi oqimlar misollarida bo'lgani kabi). Biz juda chuqur tushmaymiz, chunki siz juda chuqur sho'ng'ishingiz mumkin, men bir nechta havolalarni qoldiraman, shunda hali ham yuragida qazuvchi bo'lgan yigitlar chuqurroq qazishlari mumkin:

har biriga

Java 8-da oqim kabi ma'lumotlar oqimi bilan ishlaydigan yangi fore mavjud. Mana bir misol:
List<Integer> someList = Arrays.asList(1, 3, 5, 7, 9);

someList.forEach(x -> System.out.println(x));
(someList.stream().foreach(…) ga o'xshash)

Usul ma'lumotnomasi

Yo'naltiruvchi usullar - bu Java sinflari yoki ob'ektlarining mavjud usullari yoki konstruktorlariga :: orqali murojaat qilish uchun mo'ljallangan yangi, foydali sintaksisdir.
  1. Dizaynerga havola:

    SomeObject obj = SomeObject::new

  2. Statik usulga havola:

    SomeObject::someStaticMethod

  3. Muayyan turdagi ob'ektning statik bo'lmagan usuliga havola:

    SomeObject::someMethod

  4. Muayyan ob'ektning muntazam (statik bo'lmagan) usuliga havola

    obj::someMethod

Ko'pincha lambdalar o'rniga oqimlarda usul havolalari qo'llaniladi (mos yozuvlar usullari lambdalarga qaraganda tezroq, lekin o'qish qobiliyatidan past).
someList.stream()

        .map(String::toUpperCase)

      .forEach(System.out::println);
Malumot usullari haqida ko'proq ma'lumot olishni istaganlar uchun:

API vaqti

Sanalar va vaqtlar bilan ishlash uchun yangi kutubxona mavjud - java.time. 8 dan 13 gacha: Java versiyalarining to'liq ko'rinishi.  1-2 qismYangi API har qanday Joda-Time-ga o'xshaydi. Ushbu API ning eng muhim bo'limlari:
  • LocalDate - aniq sana, misol sifatida - 2010-01-09;
  • LocalTime - vaqt mintaqasini hisobga olgan holda vaqt - 19:45:55 (LocalDate ga o'xshash);
  • LocalDateTime - kombinatsiyalangan LocalDate + LocalTime - 2020-01-04 15:37:47;
  • ZoneId - vaqt zonalarini ifodalaydi;
  • Soat - bu turdan foydalanib, joriy vaqt va sanaga kirishingiz mumkin.
Mana, ushbu mavzu bo'yicha bir nechta qiziqarli maqolalar:

Ixtiyoriy

Bu java.util to'plamidagi yangi sinf bo'lib , qiymat o'rami bo'lib, uning hiylasi shuki, u xavfsiz tarzda null ni ham o'z ichiga olishi mumkin . Ixtiyoriy qabul qilish: Agar biz Optional.ofOptional<String> someOptional = Optional.of("Something"); da null qiymatini o'tkazsak, biz sevimli NullPointerException ni olamiz . Bunday hollarda ular quyidagilardan foydalanadilar: - bu usulda siz nulldan qo'rqishingiz shart emas. Keyin, dastlab boʻsh boʻlgan ixtiyoriy: boʻsh yoki yoʻqligini tekshirish uchun: “ toʻgʻri” yoki “yolgʻon” qiymatini qaytaradi. Agar qiymat mavjud bo'lsa, ma'lum bir amalni bajaring va qiymat bo'lmasa, hech narsa qilmang: Agar ixtiyoriy bo'sh bo'lsa, o'tkazilgan qiymatni qaytaradigan teskari usul (zaxira rejasi turi): Siz juda va juda uzoq vaqt davom etishingiz mumkin ( Yaxshiyamki, ixtiyoriy ikkala saxiy qo'llar bilan usullarni qo'shdi), lekin biz bu haqda to'xtalmaymiz. Yangi boshlanuvchilar uchun bir nechta havolalarni qoldirganim ma'qul: Optional<String> someOptional = Optional.ofNullable("Something");Optional<String> someOptional = Optional.empty();someOptional.isPresent();someOptional.ifPresent(System.out::println);System.out.println(someOptional.orElse("Some default content")); Biz Java 8-dagi eng mashhur yangiliklarni ko'rib chiqdik - bu hammasi emas. Agar siz ko'proq bilmoqchi bo'lsangiz, men buni siz uchun qoldirdim:

Java 9

Shunday qilib, 2017-yil 21-sentabrda dunyo JDK 9-ni ko‘rdi. Ushbu Java 9 boy funksiyalar to‘plamiga ega. Yangi til tushunchalari mavjud bo'lmasa-da, yangi API va diagnostika buyruqlari albatta ishlab chiquvchilarni qiziqtiradi. 8 dan 13 gacha: Java versiyalarining to'liq ko'rinishi.  1-4 qism

JShell (REPL - o'qish-baholash-bosib chiqarish tsikli)

Bu interaktiv konsolning Java dasturi bo'lib, u funksionallikni sinab ko'rish va konsolda interfeyslar, sinflar, enumlar, operatorlar va boshqalar kabi turli konstruksiyalardan foydalanish uchun ishlatiladi. JShellni ishga tushirish uchun terminalda jshell yozish kifoya. Keyin biz tasavvurimiz imkon beradigan narsani yozishimiz mumkin: 8 dan 13 gacha: Java versiyalarining to'liq ko'rinishi.  1-5 qismJShell-dan foydalanib, siz yuqori darajadagi usullarni yaratishingiz va ularni bir seansda ishlatishingiz mumkin. Usullar xuddi statik usullar kabi ishlaydi, faqat statik kalit so'zni o'tkazib yuborish mumkin. Batafsilroq Java 9 REPL (JShell) qo'llanmasida o'qing .

Shaxsiy

Java-ning 9-versiyasidan boshlab biz interfeyslarda shaxsiy usullardan foydalanish imkoniyatiga egamiz (standart va statik usullar, chunki biz kirishning etarli emasligi sababli boshqalarni bekor qila olmaymiz). private static void someMethod(){} try-with-resources Resurslar bilan sinab ko'rish istisnolarini boshqarish qobiliyati yangilandi:
BufferedReader reader = new BufferedReader(new FileReader("....."));
  try (reader2) {
  ....
}

Modullik ( jigsaw )

Modul - bu yangi modul identifikatori fayli bilan birga tegishli paketlar va resurslar guruhi. Ushbu yondashuv kodning ulanishini bo'shatish uchun ishlatiladi. Bo'shashmasdan ulanish kodning barqarorligi va kengaytirilishi uchun asosiy omil hisoblanadi. Modullik turli darajalarda amalga oshiriladi:
  1. Dasturlash tili.
  2. Virtual mashina.
  3. Standart java API.
JDK 9 92 modul bilan birga keladi: biz ulardan foydalanishimiz yoki o'zimizni yaratishimiz mumkin. Bu erda chuqurroq ko'rish uchun bir nechta havolalar:

O'zgarmas to'plam

Java 9 da to'plamni bir qator bilan to'ldirish va uni o'zgarmas qilish imkoniyati paydo bo'ldi (ilgari o'zgarmas to'plam yaratish uchun biz kollektsiya yaratishimiz, uni ma'lumotlar bilan to'ldirishimiz va usulni chaqirishimiz kerak edi, masalan, Collections.unmodifiableList). Bunday yaratilishga misol: List someList = List.of("first","second","third");

Boshqa innovatsiyalar:

  • kengaytirilgan Majburiy emas (yangi usullar qo'shilgan);
  • operatsion tizimning harakatlarini boshqarish uchun ProcessHandle va ProcessHandle interfeyslari paydo bo'ldi;
  • G1 - standart axlat yig'uvchi;
  • HTTP/2 protokollari va WebSocket-ni qo'llab-quvvatlaydigan HTTP mijozi;
  • kengaytirilgan oqim;
  • qo'shilgan Reactive Streams API ramkasi (reaktiv dasturlash uchun);
Java 9-ga to'liqroq kirish uchun men sizga o'qishni maslahat beraman:

Java 10

Shunday qilib, Java 9 chiqarilganidan olti oy o'tgach, 2018 yil mart oyida (men buni kechagidek eslayman), Java 10 sahnaga chiqdi. 8 dan 13 gacha: Java versiyalarining to'liq ko'rinishi.  1-6 qism

var

Endi biz ma'lumotlar turini taqdim etishimiz shart emas. Biz xabarni var sifatida belgilaymiz va kompilyator o'ng tomonda mavjud bo'lgan initsializator turiga qarab xabar turini aniqlaydi. Bu xususiyat faqat initsializatorga ega mahalliy o'zgaruvchilar uchun mavjud: uni usul argumentlari, qaytarish turlari va boshqalar uchun ishlatib bo'lmaydi, chunki turni aniqlash uchun boshlang'ich mavjud emas. Misol var (String turi uchun):
var message = "Some message…..";
System.out.println(message);
var kalit so'z emas: u aslida int kabi ajratilgan turdagi nomdir . Varning foydasi katta: turdagi deklaratsiyalar hech qanday foyda keltirmasdan katta e'tiborni oladi va bu xususiyat vaqtni tejaydi. Ammo shu bilan birga, agar o'zgaruvchi uzoq usullar zanjiridan olingan bo'lsa, kod kamroq o'qilishi mumkin bo'ladi, chunki u erda qanday ob'ekt mavjudligi darhol noma'lum. Ushbu funksiya bilan ko'proq tanishishni istaganlar uchun mo'ljallangan:

JIT kompilyatori (GraalVM)

Yana bir bor eslatib o'tmoqchimanki, javac buyrug'ini ishga tushirganingizda Java ilovasi Java kodidan JVM baytkodiga kompilyatsiya qilinadi, bu ilovaning ikkilik ko'rinishidir. Ammo oddiy kompyuter protsessori JVM bayt kodini oddiygina bajara olmaydi. JVM dasturingiz ishlashi uchun protsessor allaqachon foydalanishi mumkin bo'lgan mashina kodiga aylantirilgan ushbu bayt-kod uchun boshqa kompilyator kerak. Javac bilan solishtirganda, bu kompilyator ancha murakkab, lekin ayni paytda yuqori sifatli mashina kodini ishlab chiqaradi. Hozirgi vaqtda OpenJDK HotSpot virtual mashinasini o'z ichiga oladi, u o'z navbatida ikkita asosiy JIT kompilyatoriga ega. Birinchisi, C1 ( mijoz kompilyatori ) yuqori tezlikda ishlash uchun mo'ljallangan, ammo kodni optimallashtirish zarar ko'radi. Ikkinchisi C2 (server kompilyatori). Amalga oshirish tezligi yomonlashadi, lekin kod yanada optimallashtirilgan. Qaysi biri qachon ishlatiladi? C1 uzoq JIT pauzalarini istamaydigan ish stoli ilovalari uchun, C2 esa kompilyatsiyaga ko'proq vaqt sarflashga chidash mumkin bo'lgan uzoq muddatli server dasturlari uchun juda mos keladi. Ko'p darajali kompilyatsiya - bu kompilyatsiya birinchi marta C1 orqali o'tadi va natija C2 orqali o'tadi (kattaroq optimallashtirish uchun ishlatiladi). GraalVM - bu HotSpotni to'liq almashtirish uchun yaratilgan loyiha. Biz Graalni bir nechta tegishli loyihalar sifatida tasavvur qilishimiz mumkin: HotSpot uchun yangi JIT kompilyatori va yangi poliglot virtual mashinasi. Ushbu JIT kompilyatorining o'ziga xosligi shundaki, u Java tilida yozilgan. Graal kompilyatorining afzalligi - bu xavfsizlik, ya'ni buzilishlar emas, balki istisnolar, xotiraning oqishi emas. Shuningdek, bizda yaxshi IDE yordami bo'ladi va biz tuzatuvchilar, profilerlar yoki boshqa qulay vositalardan foydalana olamiz. Bundan tashqari, kompilyator HotSpot-dan mustaqil bo'lishi mumkin va u o'zining tezroq JIT kompilyatsiya qilingan versiyasini yaratishi mumkin. Qazuvchilar uchun:

Parallel G1

G1 axlat yig'uvchisi, albatta, ajoyib, bunga shubha yo'q, lekin u ham zaif nuqtaga ega: u bir tishli to'liq GC tsiklini bajaradi. Foydalanilmayotgan ob'ektlarni topish uchun sizga barcha jihozlar kerak bo'lganda, biz bitta ip bilan cheklanamiz. Java 10 buni tuzatdi.Endi GC biz unga qo'shgan barcha resurslar bilan ishlaydi (ya'ni u ko'p tarmoqli bo'ladi). Bunga erishish uchun til ishlab chiquvchilari GC dan asosiy manbalarning izolyatsiyasini yaxshiladilar va GC uchun chiroyli toza interfeys yaratdilar. Ushbu yoqimlilikni ishlab chiquvchilari, OpenJDK, nafaqat yangi GC-larni yaratishni iloji boricha soddalashtirish, balki yig'ilishdan keraksiz GC-larni tezda o'chirib qo'yish uchun koddagi axlatni tozalashlari kerak edi. Muvaffaqiyatning asosiy mezonlaridan biri bu barcha yaxshilanishlardan keyin ish tezligida pasayishning yo'qligi. Keling, shuningdek, qaraylik: Boshqa innovatsiyalar:
  1. Toza axlat yig'uvchi interfeysi joriy etildi. Bu turli xil axlat yig'uvchilardan manba kodining izolyatsiyasini yaxshilaydi, bu muqobil kollektorlarni tez va og'riqsiz birlashtirish imkonini beradi;
  2. JDK manbalarini bitta omborga birlashtirish;
  3. To'plamlar yangi usulni oldi - copyOf (Collection) , bu to'plamning o'zgarmas nusxasini qaytaradi;
  4. Ixtiyoriy (va uning variantlari) yangi usulga ega .orElseThrow() ;
  5. Bundan buyon JVM'lar Docker konteynerida ishlayotganligini bilishadi va operatsion tizimning o'ziga so'rov o'tkazishdan ko'ra konteynerga xos konfiguratsiyani olishadi.
Java 10 bilan batafsilroq tanishish uchun yana bir qancha materiallar: Ilgari Java-ning ba'zi versiyalari 1.x deb nomlanganligi meni juda chalkashtirib yubordi. Men aniq bo'lishni xohlayman: 9-dan oldingi Java versiyalari shunchaki boshqa nomlash sxemasiga ega edi. Masalan, Java 8 ni 1.8 , Java 5 - 1.5 va hokazo deb ham atash mumkin. Endi biz Java 9 dan relizlarga oʻtish bilan nomlash sxemasi ham oʻzgarganini va Java versiyalarida endi 1.x prefiksi qoʻyilmaganini koʻramiz. . Bu birinchi qismning oxiri: biz java 8-10 ning yangi qiziqarli xususiyatlarini ko'rib chiqdik. Keling, tanishuvimizni keyingi postda davom ettiramiz .
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION