JavaRush /Java Blogu /Random-AZ /8-dən 13-ə qədər: Java versiyalarının tam icmalı. 1-ci hi...

8-dən 13-ə qədər: Java versiyalarının tam icmalı. 1-ci hissə

Qrupda dərc edilmişdir
Pişiklər, hamıya salam)) Deməli, bu gün 2020-ci ildəyik və Java 14-ün buraxılışına çox az vaxt qalıb. Siz martın 17-də hazır versiyanı gözləməlisiniz, biz orada nəyin təzə və maraqlı olduğunu faktdan sonra təhlil edəcəyik, lakin bu gün mən Java-nın əvvəlki versiyalarında yaddaşımı yeniləmək istərdim. Bizə nə yenilik gətirdilər? Gəlin nəzər salaq. Gəlin nəzərdən keçirməyə Java 8 ilə başlayaq, çünki o, hələ də kifayət qədər aktualdır və əksər layihələrdə istifadə olunur. 8-dən 13-ə qədər: Java versiyalarının tam icmalı.  1-1 hissəƏvvəllər yeni versiyalar hər 3-5 ildən bir buraxılırdı, lakin bu yaxınlarda Oracle fərqli bir yanaşma tətbiq etdi - “hər altı aydan bir yeni Java”. Beləliklə, hər altı aydan bir funksiyaların buraxıldığını görürük. Yaxşı və ya pis olsa da, hər kəs buna fərqli baxır. Məsələn, bunu çox bəyənmirəm, çünki yeni versiyalarda çoxlu yeni xüsusiyyətlər yoxdur, eyni zamanda versiyalar yağışdan sonra göbələk kimi böyüyür. Java 8 ilə bir layihədə bir neçə dəfə gözümü qırpdım və Java 16 artıq buraxıldı (lakin nadir hallarda çıxanda yeni xüsusiyyətlər toplanır və sonda bu hadisə bayram kimi çoxdan gözləniləndir: hamı bu mövzunu müzakirə edir. yeni gözəlliklər və siz onun yanından keçə bilməzsiniz). Beləliklə, başlayaq!

Java 8

Funksional interfeys

Bu nədir? Funksional interfeys bir həyata keçirilməmiş (mücərrəd) metodu ehtiva edən interfeysdir. @FunctionalInterface belə bir interfeysin üstündə yerləşdirilən isteğe bağlı annotasiyadır. Funksional interfeysin tələblərinə cavab verib-vermədiyini yoxlamaq lazımdır (yalnız bir mücərrəd metoda malikdir). Ancaq həmişə olduğu kimi, bəzi xəbərdarlıqlarımız var: defolt və statik üsullar bu tələblərə uyğun gəlmir. Buna görə də bir neçə belə üsul + bir mücərrəd ola bilər və interfeys funksional olacaqdır. O, həmçinin interfeysin funksional kimi müəyyən edilməsinə təsir etməyən Object sinifinin metodlarını ehtiva edə bilər. Defolt və statik metodlar haqqında bir neçə söz əlavə edəcəyəm:
  1. Defolt dəyişdiricisi olan üsullar mövcud tətbiqi pozmadan interfeyslərə yeni metodlar əlavə etməyə imkan verir.

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

    Bəli, bəli, həyata keçirilən metodu interfeysə əlavə edirik və bu metodu həyata keçirərkən, onu ləğv edə bilməzsiniz, ancaq irsi olaraq istifadə edin. Amma əgər sinif verilmiş metodla iki interfeys həyata keçirirsə, bizdə kompilyasiya xətası yaranacaq və əgər o, interfeysləri həyata keçirirsə və müəyyən eyni metodla sinfi miras alırsa, ana sinif metodu interfeys metodları ilə üst-üstə düşəcək və istisna işləməyəcək.

  2. interfeysdəki statik metodlar sinifdəki statik metodlarla eyni işləyir. Unutmayın: nəsil sinfindən statik metodu çağıra bilməyəcəyiniz kimi, statik metodları miras ala bilməzsiniz.

Beləliklə, funksional interfeyslər haqqında bir neçə söz və davam edək. Fİ-lərin əsas siyahıları (qalanları onların növləridir):

    Predikat - arqument kimi T dəyərini götürür, məntiqi qaytarır.

    Misal:boolean someMethod(T t);

  • İstehlakçı - T tipli arqument götürür, heç nə qaytarmır (boş).

    Misal:void someMethod(T t);

  • Təchizatçı - giriş kimi heç nə qəbul etmir, lakin T dəyərini qaytarır.

    Misal:T someMethod();

  • Funksiya - giriş kimi T tipli parametr qəbul edir, R tipli dəyəri qaytarır.

    Misal:R someMethod(T t);

  • UnaryOperator - T arqumentini götürür və T tipli dəyəri qaytarır.

    Misal:T someMethod(T t);

Axın

Axınlar məlumat strukturlarını funksional üslubda idarə etmək üçün bir yoldur. Tipik olaraq bunlar kolleksiyalardır (lakin onları başqa, daha az rast gəlinən hallarda istifadə edə bilərsiniz). Daha başa düşülən dillə desək, Stream, hər biri üçün olduğu kimi kobud güc deyil, bütün verilənlərlə eyni anda işləyirmiş kimi emal etdiyimiz məlumat axınıdır. Kiçik bir misala baxaq. Tutaq ki, süzgəcdən keçirmək (50-dən az), 5-ə artırmaq və qalanlardan ilk 4 rəqəmi konsola çıxarmaq istədiyimiz bir sıra nömrələrimiz var. Bunu əvvəllər necə edərdik:
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);

}
Görünür, çox kod yoxdur və məntiq artıq bir az qarışıqdır. Gəlin axından istifadə edərək onun necə görünəcəyinə baxaq:
Stream.of(46, 34, 24, 93, 91, 1, 34, 94)

      .filter(x -> x < 50)

      .map(x -> x + 5)

      .limit(4)

      .forEach(System.out::print);
Axınlar kodun miqdarını azaltmaqla və onu daha oxunaqlı etməklə həyatı xeyli sadələşdirir. Bu mövzunu daha ətraflı araşdırmaq istəyənlər üçün bu mövzuda yaxşı (hətta əla deyərdim) məqalə var .

Lambda

Bəlkə də ən vacib və çoxdan gözlənilən xüsusiyyət lambdaların görünüşüdür. lambda nədir? Bu, müxtəlif yerlərə ötürülə bilən kod blokudur ki, sonra lazım olan qədər dəfələrlə icra olunsun. Olduqca çaşqın səslənir, elə deyilmi? Sadəcə olaraq, lambdalardan istifadə edərək, funksional interfeys metodunu həyata keçirə bilərsiniz (bir növ anonim sinfin həyata keçirilməsi):
Runnable runnable = () -> { System.out.println("I'm running !");};

new Thread(runnable).start();
Biz run() metodunu tez və lazımsız büruzəsiz tətbiq etdik. Və bəli: Runnable funksional interfeysdir. Mən axınlarla işləyərkən lambdalardan da istifadə edirəm (yuxarıdakı axınlarla nümunələrdə olduğu kimi). Çox dərinə getməyəcəyik, çünki kifayət qədər dərinə dala bilirik, mən bir neçə keçid buraxacağam ki, hələ də qəlbində qazma işi olan uşaqlar daha dərin qaza bilsinlər:

foreach

Java 8-də axın kimi məlumat axını ilə işləyən yeni foreach var. Budur bir nümunə:
List<Integer> someList = Arrays.asList(1, 3, 5, 7, 9);

someList.forEach(x -> System.out.println(x));
(analoqu someList.stream().foreach(…))

Metod arayışı

İstinad metodları Java siniflərinin və ya obyektlərinin mövcud metodlarına və ya konstruktorlarına :: vasitəsilə istinad etmək üçün nəzərdə tutulmuş yeni, faydalı sintaksisdir: Metod istinadları dörd növdə olur:
  1. Dizaynerlə əlaqə:

    SomeObject obj = SomeObject::new

  2. Statik metod istinadı:

    SomeObject::someStaticMethod

  3. Müəyyən bir növ obyektin qeyri-statik metoduna istinad:

    SomeObject::someMethod

  4. Müəyyən bir obyektin müntəzəm (qeyri-statik) metoduna istinad

    obj::someMethod

Çox vaxt lambdalar əvəzinə axınlarda metod istinadları istifadə olunur (istinad üsulları lambdalardan daha sürətlidir, lakin oxunuş baxımından aşağıdır).
someList.stream()

        .map(String::toUpperCase)

      .forEach(System.out::println);
İstinad üsulları haqqında daha çox məlumat almaq istəyənlər üçün:

API vaxtı

Tarixlər və vaxtlarla işləmək üçün yeni kitabxana var - java.time. 8-dən 13-ə qədər: Java versiyalarının tam icmalı.  1-2 hissəYeni API istənilən Joda-Time-ə bənzəyir. Bu API-nin ən əhəmiyyətli bölmələri bunlardır:
  • LocalDate konkret bir tarixdir, misal olaraq - 01-09-2010;
  • LocalTime - saat qurşağı nəzərə alınmaqla vaxt - 19:45:55 (LocalDate analoqu);
  • LocalDateTime - birləşmiş LocalDate + LocalTime - 2020-01-04 15:37:47;
  • ZoneId - saat qurşaqlarını təmsil edir;
  • Saat - bu növdən istifadə edərək cari vaxt və tarixə daxil ola bilərsiniz.
Bu mövzuda həqiqətən maraqlı bir neçə məqalə var:

Könüllü

Bu java.util paketində yeni bir sinifdir , onun hiyləsi odur ki, o, təhlükəsiz şəkildə null ehtiva edə bilər . İsteğe bağlı qəbul: Optional.ofOptional<String> someOptional = Optional.of("Something"); -da null keçirsək , sevimli NullPointerException alacağıq . Belə hallarda onlar istifadə edirlər: - bu üsulda siz sıfırdan qorxmaq lazım deyil. Sonra, əvvəlcə boş olanı yaradın Könüllü: Boş olub olmadığını yoxlamaq üçün istifadə edin: bizə doğru və ya yalanı qaytaracaq. Dəyər varsa müəyyən hərəkəti yerinə yetirin və dəyər yoxdursa heç nə etməyin: Könüllü boşdursa, ötürülən dəyəri qaytaran tərs metod (bir növ ehtiyat plan): Siz çox, çox uzun müddət davam edə bilərsiniz ( xoşbəxtlikdən, Opsiyonel hər iki səxavətli əllə üsullar əlavə etdi), lakin biz bunun üzərində dayanmayacağıq. Başlayanlar üçün bir neçə link buraxmaq daha yaxşıdır: 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")); Java 8-də ən məşhur yenilikləri nəzərdən keçirdik - bu, hamısı deyil. Daha çox bilmək istəyirsinizsə, bunu sizin üçün buraxdım:

Java 9

Beləliklə, 21 sentyabr 2017-ci ildə dünya JDK 9-u gördü. Bu Java 9 zəngin xüsusiyyətlər dəsti ilə gəlir. Yeni dil anlayışları olmasa da, yeni API-lər və diaqnostik əmrlər mütləq tərtibatçılar üçün maraqlı olacaq. 8-dən 13-ə qədər: Java versiyalarının tam icmalı.  1-4 hissə

JShell (REPL - oxumaq-qiymətləndirmə-çap dövrü)

Bu, funksionallığı yoxlamaq və konsolda interfeyslər, siniflər, nömrələr, operatorlar və s. kimi müxtəlif konstruksiyalardan istifadə etmək üçün istifadə olunan interaktiv konsolun Java tətbiqidir. JShell-i işə salmaq üçün terminalda jshell yazmağınız kifayətdir. O zaman biz təsəvvürümüzün imkan verdiyini yaza bilərik: 8-dən 13-ə qədər: Java versiyalarının tam icmalı.  1-5 hissəJShell-dən istifadə edərək, siz yüksək səviyyəli metodlar yarada və eyni seansda istifadə edə bilərsiniz. Metodlar statik metodlar kimi işləyəcək, ancaq statik açar söz buraxıla bilər.Daha ətraflı Java 9 REPL (JShell) təlimatında oxuyun .

Şəxsi

Java-nın 9-cu versiyasından başlayaraq, interfeyslərdə şəxsi metodlardan istifadə etmək imkanımız var (defolt və statik metodlar, çünki qeyri-kafi girişə görə başqalarını sadəcə olaraq ləğv edə bilmirik). private static void someMethod(){} try-with-resources Resurslarla Sınaq istisnalarını idarə etmək qabiliyyəti təkmilləşdirildi:
BufferedReader reader = new BufferedReader(new FileReader("....."));
  try (reader2) {
  ....
}

Modulluq ( Yapboz )

Modul yeni modul deskriptor faylı ilə birlikdə əlaqəli paketlər və resurslar qrupudur. Bu yanaşma kodun birləşməsini boşaltmaq üçün istifadə olunur. Boş birləşmə kodun davamlılığı və genişlənməsi üçün əsas amildir. Modulluq müxtəlif səviyyələrdə həyata keçirilir:
  1. Proqramlaşdırma dili.
  2. Virtual maşın.
  3. Standart java API.
JDK 9 92 modulla gəlir: biz onlardan istifadə edə və ya özümüzü yarada bilərik. Daha dərindən baxmaq üçün burada bir neçə keçid var:

Dəyişməz Kolleksiya

Java 9-da kolleksiya yaratmaq və onu dəyişməz etməklə bərabər bir sətirlə doldurmaq mümkün oldu (əvvəllər dəyişməz kolleksiya yaratmaq üçün kolleksiya yaratmaq, onu verilənlərlə doldurmaq və metodu çağırmaq lazım idi, məsələn, Collections.unmodifiableList). Belə bir yaradılış nümunəsi: List someList = List.of("first","second","third");

Digər yeniliklər:

  • genişləndirilmiş Könüllü (yeni üsullar əlavə edildi);
  • əməliyyat sisteminin hərəkətlərini idarə etmək üçün ProcessHandle və ProcessHandle interfeysləri meydana çıxdı;
  • G1 - standart zibil toplayıcı;
  • HTTP/2 protokolları və WebSocket dəstəyi ilə HTTP müştərisi;
  • genişləndirilmiş axın;
  • əlavə edilmiş Reactive Streams API çərçivəsi (reaktiv proqramlaşdırma üçün);
Java 9-a daha dolğun şəkildə daxil olmaq üçün sizə oxumağı məsləhət görürəm:

Java 10

Beləliklə, Java 9-un buraxılmasından altı ay sonra, 2018-ci ilin martında (dünən kimi xatırlayıram) Java 10 səhnəyə çıxdı. 8-dən 13-ə qədər: Java versiyalarının tam icmalı.  1-6 hissə

var

İndi bir məlumat növü təqdim etməli deyilik. Mesajı var olaraq qeyd edirik və tərtibçi mesajın növünü sağda mövcud olan başlatıcının növü ilə müəyyən edir. Bu funksiya yalnız başlatıcısı olan yerli dəyişənlər üçün əlçatandır: o, metod arqumentləri, qaytarma növləri və s. üçün istifadə edilə bilməz, çünki növü müəyyən etmək üçün başlatıcı yoxdur. Nümunə var (String növü üçün):
var message = "Some message…..";
System.out.println(message);
var açar söz deyil: int kimi mahiyyət etibarı ilə qorunan tip adıdır . Varın faydası böyükdür: tip bəyannamələri heç bir fayda gətirmədən çox diqqət çəkir və bu xüsusiyyət vaxta qənaət edəcək. Ancaq eyni zamanda, əgər dəyişən uzun bir üsul zəncirindən əldə edilərsə, kod daha az oxunaqlı olur, çünki orada hansı obyektin olduğu dərhal aydın deyil. Bu funksiya ilə daha yaxından tanış olmaq istəyənlərə həsr olunub:

JIT tərtibçisi (GraalVM)

Sözü uzatmadan xatırlatmaq istərdim ki, javac əmrini işlətdiyiniz zaman Java proqramı Java kodundan proqramın ikili təsviri olan JVM bayt koduna yığılır. Lakin adi kompüter prosessoru sadəcə JVM bayt kodunu icra edə bilməz. JVM proqramınızın işləməsi üçün prosessorun artıq istifadə edə bildiyi maşın koduna çevrilən bu bayt kodu üçün başqa kompilyator lazımdır. Javac ilə müqayisədə bu kompilyator daha mürəkkəbdir, eyni zamanda daha yüksək keyfiyyətli maşın kodu istehsal edir. Hazırda OpenJDK öz növbəsində iki əsas JIT kompilyatoruna malik olan HotSpot virtual maşınına malikdir. Birincisi, C1 ( müştəri tərtibçisi ), daha yüksək sürətli əməliyyat üçün nəzərdə tutulmuşdur, lakin kodun optimallaşdırılması əziyyət çəkir. İkincisi C2 (server kompilyatoru). İcra sürəti əziyyət çəkir, lakin kod daha optimallaşdırılıb. Hansı nə vaxt istifadə olunur? C1 uzun JIT fasilələrinin arzuolunmaz olduğu masa üstü proqramlar üçün əladır və C2 tərtibata daha çox vaxt sərf etməyin dözümlü olduğu uzunmüddətli server proqramları üçün əladır. Çoxsəviyyəli kompilyasiya , tərtibin ilk olaraq C1-dən, nəticənin isə C2-dən keçməsidir (daha çox optimallaşdırma üçün istifadə olunur). GraalVM HotSpot-u tamamilə əvəz etmək üçün yaradılmış bir layihədir. Graal-ı bir neçə əlaqəli layihə kimi düşünə bilərik: HotSpot üçün yeni JIT kompilyatoru və yeni poliqlot virtual maşın. Bu JIT kompilyatorunun özəlliyi onun Java dilində yazılmasıdır. Graal kompilyatorunun üstünlüyü təhlükəsizlikdir, yəni qəzalar deyil, istisnalar, yaddaş sızması deyil. Həm də yaxşı IDE dəstəyimiz olacaq və biz sazlayıcılardan, profilləyicilərdən və ya digər rahat alətlərdən istifadə edə biləcəyik. Bundan əlavə, kompilyator HotSpot-dan tamamilə müstəqil ola bilər və o, özünün daha sürətli JIT tərtib edilmiş versiyasını yarada biləcək. Qazanlar üçün:

Paralel G1

G1 zibil kollektoru, şübhəsiz ki, sərindir, lakin onun zəif tərəfi də var: o, tək yivli tam GC dövrü həyata keçirir. İstifadə edilməmiş obyektləri tapmaq üçün toplaya biləcəyiniz bütün avadanlıq gücünə ehtiyacınız olduğu bir vaxtda biz tək bir iplə məhdudlaşırıq. Bu, Java 10-da düzəldildi. İndi GC ona əlavə etdiyimiz bütün resurslarla işləyir (yəni çox yivli olur). Buna nail olmaq üçün dil tərtibatçıları əsas mənbələrin GC-dən təcrid olunmasını təkmilləşdirərək GC üçün gözəl təmiz interfeys yaradıblar. Bu şirinliyin tərtibatçıları, OpenJDK, nəinki mümkün qədər yeni GC-lərin yaradılmasını asanlaşdırmaq, həm də lazımsız GC-ləri montajdan tez bir zamanda söndürmək üçün koddakı zibilxananı xüsusi olaraq təmizləməli idi. Müvəffəqiyyətin əsas meyarlarından biri bütün bu təkmilləşdirmələrdən sonra əməliyyat sürətində azalmanın olmamasıdır. Gəlin də baxaq: Digər yeniliklər:
  1. Təmiz Zibil Kollektoru İnterfeysi təqdim olunur. Bu, mənbə kodunun müxtəlif zibil kollektorlarından izolyasiyasını yaxşılaşdırır, alternativ kollektorları tez və ağrısız şəkildə inteqrasiya etməyə imkan verir;
  2. JDK mənbələrinin bir depoda birləşdirilməsi;
  3. Kolleksiyalar bu kolleksiyanın dəyişməz surətini qaytaran yeni üsul - copyOf (Kolleksiya) aldı;
  4. Könüllü (və onun variantları) yeni metoda malikdir .orElseThrow() ;
  5. Bundan sonra JVM-lər Docker konteynerində işlədiklərini bilirlər və əməliyyat sisteminin özünə sorğu verməkdənsə, konteynerə xas konfiqurasiya əldə edəcəklər.
Java 10-a daha müfəssəl giriş üçün burada daha bir neçə material var: Əvvəllər Java-nın bəzi versiyalarının 1.x adlandırılması məni çox çaşdırırdı. Mən aydın olmaq istərdim: 9-dan əvvəlki Java versiyaları sadəcə olaraq fərqli adlandırma sxeminə malik idi. Məsələn, Java 8-i də 1.8 , Java 5 - 1.5 və s adlandırmaq olar. İndi biz görürük ki, Java 9-dan buraxılışlara keçidlə adlandırma sxemi də dəyişib və Java versiyalarında artıq 1.x prefiksi yoxdur. . Bu, birinci hissənin sonu: java 8-10-un yeni maraqlı xüsusiyyətlərini nəzərdən keçirdik. Ən son ilə tanışlığımızı növbəti postda davam etdirək .
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION