JavaRush /Blog Java /Random-PL /Wydano Java 11: nowe funkcje i możliwości

Wydano Java 11: nowe funkcje i możliwości

Opublikowano w grupie Random-PL
Wcześniej nowe wersje Javy pojawiały się rzadko i z opóźnieniami. Teraz Oracle z powodzeniem utrzymuje ustalony przez siebie rytm „nowej Java co sześć miesięcy”. Tak więc kilka dni temu, ściśle zgodnie z harmonogramem, otrzymaliśmy w końcu Java SE 11 i implementację JDK (Java Development Kit). Wydano Java 11: nowe funkcje i możliwości - 1Jak zawsze nowa wersja będzie kompatybilna ze starymi, a wsparcie dla Java 11 zakończy się nie wcześniej niż w grudniu 2026 roku.

Nowe funkcje w Java SE 11 (widoczne dla programistów)

Przypomnijmy, że w Javie zmiany wprowadza się poprzez wdrożenie JEP „JDK Enhancement Proposal”. JEP to propozycja ulepszenia OpenJDK, która może zostać zatwierdzona, opóźniona lub odrzucona. Oznacza to, że w istocie zbiór JEP jest strategią rozwoju OpenJDK. W nawiasach kwadratowych przed nową „funkcją” podajemy numer odpowiedniego JEP. [323] Składnia zmiennej lokalnej dla parametrów lambda - składnia var dla parametrów lambda W Javie 10 wprowadzono słowo kluczowe var, które umożliwiło brak jawnego określania typu zmiennej lokalnej. Uprościło to kod. JEP 323 rozszerza użycie tej składni o wyrażenia lambda. Prosty przykład:
list.stream ()
                 .map ((var s) -> s.toLowerCase ())
                 .collect (Collectors.toList ());
Jak pisze Simon Ritter , znany ewangelista Java, doświadczony programista Java zauważy, że użycie var w tym przypadku może być niepotrzebne, ponieważ powyższy kod można zastąpić następującym:
list.stream ()
                  .map (s -> s.toLowerCase ())
                  .collect (Collectors.toList ());
Dlaczego więc wspierać var? Jest tylko jeden szczególny przypadek — gdy chcesz dodać adnotację do parametru lambda. Nie można tego zrobić bez użycia jakiegoś typu, a aby uniknąć konieczności używania typu jawnego, możemy wszystko uprościć, używając var w następujący sposób:
list.stream ()
                 .map ((@ Notnull var s) -> s.toLowerCase ())
                 .collect (Collectors.toList ());
[330] Uruchamianie programów z kodem źródłowym składającym się z jednego pliku Ulepszanie programu uruchamiającego Java tak, aby uruchamiał program jako pojedynczy plik z kodem źródłowym Java Java jest często krytykowana za rozbudowaną składnię i wieloetapową „ceremonię” uruchamiania nawet trywialnej aplikacji. Czasami to odstrasza nowicjuszy. Aby napisać aplikację, która po prostu wypisuje „ Hello World! ” ", musisz napisać klasę z publiczną statyczną voidmetodą główną i użyć metody System.out.println. Po wykonaniu tej czynności musisz skompilować kod za pomocą javac . Na koniec można już po tym uruchomić aplikację, która wyświetli nieszczęsne powitanie (oczywiście zintegrowane środowisko programistyczne, zarówno IDEA , jak i to wbudowane w JavaRush , samodzielnie wykonuje tę „magię uruchamiania aplikacji” – przyp. ). Bądźmy szczerzy: w większości języków programowania faktyczny skrypt do uruchamiania programów wygląda znacznie prościej. JEP 330 eliminuje potrzebę kompilowania aplikacji jednoplikowej, więc teraz, jeśli używasz wiersza poleceń, po prostu wpisz
java HelloWorld.java
Program uruchamiający Java wykryje, że plik zawiera kod źródłowy Java i skompiluje kod do pliku klasy przed jego wykonaniem. Możesz umieścić parametry po lub przed nazwą pliku z kodem źródłowym. Te umieszczone po nazwie są przekazywane jako parametry podczas wykonywania aplikacji. Te umieszczone przed nazwą są przekazywane jako parametry do programu uruchamiającego Java po skompilowaniu kodu. Opcje specyficzne dla kompilatora (takie jak ścieżka klasy) zostaną również przekazane do javac w celu kompilacji. Przykład. Linia:
java -classpath / home / foo / java Hello.java Bonjour
będzie równoważne następującym liniom:
javac -classpath / home / foo / java Hello.java
java -classpath / home / foo / java Hello Bonjour
[321] Klient HTTP (Standard) - Ujednolicono obsługę API klienta HTTP.JDK 9 wprowadziło nowe API do obsługi protokołu klienta HTTP (JEP 110) . Ponieważ w pakiecie JDK 9 wprowadzono także system modułów platformy Java (JPMS) , ten interfejs API został dołączony jako moduł inkubatora (są to moduły zapewniające programistom nowe interfejsy API, które nie stały się jeszcze standardem w Java SE, podczas gdy „żywe” interfejsy API są przygotowany do usunięcia – programiści mogą wypróbować nowe interfejsy API i spróbować przekazać opinię). Po dokonaniu niezbędnych zmian (to API zostało zaktualizowane w JDK 10), API może stać się częścią standardu. Zatem interfejs API klienta HTTP jest teraz oficjalnie zawarty w Java SE 11 . Wprowadza to nowy moduł i pakiet dla JDK, java.net.http . Główne nowe typy to: HttpClient HttpRequest HttpResponse WebSocket Tego interfejsu API można używać synchronicznie lub asynchronicznie. W trybie asynchronicznym używane są CompletionFuturesi CompletionStages. [320] Usuwanie modułów Java EE i CORBA Wraz z wprowadzeniem systemu modułów platformy Java (JPMS) w dziewiątej wersji Java możliwe stało się podzielenie monolitycznego pliku rt.jar na kilka modułów. Ponadto JPMS umożliwia utworzenie środowiska uruchomieniowego Java, które zawiera tylko moduły potrzebne Twojej aplikacji, co znacznie zmniejsza jej rozmiar. Dzięki przejrzyście zdefiniowanym granicom modułów znacznie łatwiej jest usunąć przestarzałe części API Java - właśnie to robi JEP 320. Metamoduł java.se.ee zawiera sześć modułów, które nie będą częścią standardu Java SE 11 i nie zostaną uwzględnione w JDK-u:
  • korba
  • transakcja
  • aktywacja
  • xml.bind
  • xml.ws
  • adnotacja.xml.ws
Moduły te były przestarzałe w JDK 9 i nie były domyślnie uwzględniane podczas kompilacji ani wykonywania. Oznacza to, że jeśli próbowałeś skompilować lub uruchomić aplikację korzystającą z interfejsów API tych modułów w JDK 9 lub JDK 10, zakończyło się to niepowodzeniem. Jeśli w swoim kodzie używasz interfejsów API tych modułów, będziesz musiał udostępnić je jako oddzielny moduł lub bibliotekę.

Nowe interfejsy API

Duża liczba nowych API w JDK 11 pojawiła się dzięki włączeniu do standardu językowego modułów Klienta HTTP i Rejestratora Lotów . Pełną listę interfejsów API można znaleźć w poniższym kompleksowym porównaniu różnych wersji JDK , opracowanym przez Gunnara Morlinga. W tej notatce wymienimy kilka nowych metod, które nie są zawarte w modułach java.net.http , jdk.jfr i java.security . java.lang.String Prawdopodobnie jedna z najważniejszych zmian w łańcuchu w interfejsie API JDK 11. Istnieje kilka nowych, przydatnych metod.
  • boolean isBlank (): zwraca wartość true, jeśli ciąg znaków jest pusty lub zawiera tylko spacje, w przeciwnym razie zwraca wartość false.

  • Stream lines(): Zwraca strumień linii wyodrębnionych z tego ciągu, oddzielonych terminatorami linii.

  • String repeat (int): Zwraca ciąg, którego wartość jest konkatenacją tego ciągu powtarzaną int razy.

  • String strip (): Zwraca ciąg znaków, po którym usunięto wszystkie spacje przed lub po pierwszym znaku niebędącym spacją.

  • String stripLeading (): Zwraca ciąg znaków z usuniętymi wszystkimi spacjami aż do pierwszego znaku niebędącego spacją.

  • String stripTrainling (): Zwraca ciąg znaków zawierający wszystkie spacje, które występują po usunięciu ostatniego znaku innego niż spacja.
strip()Metoda już zrobiła coś podobnego trim (), ale spacje te metody oznaczają różne rzeczy. W przypadku trim()obcinane są tylko spacje, a in strip()- także znaki specjalne, takie jak tabulatory. java.lang.StringBuffer java.lang.StringBuilder Obie te klasy zawierają nową metodę compareTo (), która akceptuje StringBuffer/ StringBuilderi zwraca int. Metoda porównania leksykalnego jest podobna do nowej metody compareTo() CharSequence. Strumień java.io.ByteArrayOutput
  • void writeBytes (byte []): zapisuje wszystkie bajty parametru do strumienia wyjściowego java.io.FileReader
Istnieją tutaj dwa nowe konstruktory, które pozwalają określić Charset. java.io.FileWriter Cztery nowe konstruktory umożliwiające określenie Charset. java.io.InputStream
  • io.InputStream nullInputStream (): zwraca InputStream, który nie czyta żadnych bajtów. Jak skorzystać z tej metody? Możesz o tym pomyśleć jako o czymś w rodzaju /dev/null, aby wyrzucić niepotrzebne dane wyjściowe lub wstrzyknąć dane wejściowe, które zawsze zwracają zero bajtów.
java.io.OutputStream
  • io.OutputStream nullOutputStream ()
Java.io.Reader
  • io.Reader nullReader ()
Java.io.Writer
  • io.Writer nullWriter ()
java.lang.Znak
  • String toString (int): Jest to przeciążenie istniejącej metody, ale używa int zamiast char.
java.lang.CharSequence
  • int compare (CharSequence, CharSequence): leksykograficznie porównuje dwa wystąpienia CharSequence. Zwraca wartość ujemną, zero lub wartość dodatnią, jeśli pierwsza sekwencja jest leksykograficznie mniejsza, równa lub większa od drugiej.
Java.lang.ref.Reference
    lang.Object clone (): Ewangelista Java Simon Ritter przyznaje, że ta metoda go dezorientuje. Klasa Referencenie implementuje interfejsu Cloneablei ta metoda zawsze zgłosi wyjątek CloneNotSupportedException. Ekspert sugeruje jednak, że ta metoda przyda się do czegoś w przyszłości.
java.lang.Runtime java.lang.System Nie ma tu żadnych nowych metod. Wspomnijmy tylko, że metoda runFinalizersOnExit ()została usunięta z obu tych klas, co może powodować problemy ze zgodnością. java.lang.Thread Żadnych dodatkowych metod, nadmienimy tylko, że destroy ()zostały stop (Throwable)usunięte. Jednak stop ()metoda , która nie przyjmuje żadnych argumentów, jest nadal dostępna. Należy o tym pamiętać, ponieważ mogą wystąpić problemy ze zgodnością. java.nio.ByteBuffer java.nio.CharBuffer java.nio.DoubleBuffer java.nio.FloatBuffer java.nio.LongBuffer java.nio.ShortBuffer We wszystkich tych klasach twórcy języka dodali metodę mismatch (), która znajduje i zwraca względny indeks pierwsza niezgodność między tym buforem a danym buforem. java.nio.channels.SelectionKey
  • int interestOpsAnd (int)

  • int interestOpsOr (int)
Selektor java.nio.channels
  • int select (java.util.function.Consumer, long): Wybiera i wykonuje akcję na klawiszach, których odpowiednie kanały są gotowe do operacji we/wy. Długi parametr to limit czasu.

  • int select (java.util.function.Consumer): działa jak powyższa metoda, ale bez limitu czasu.

  • int selectNow (java.util.function.Consumer): działa jak powyższa metoda, tyle że nie blokuje.

java.nio.file.Files
  • String readString (Path): Odczytuje całą zawartość pliku do ciągu znaków, dekodując bajty na znaki przy użyciu kodowania UTF-8 .

  • String readString (Path, Charset): Działa jak powyższa metoda, ale dekoduje bajty na znaki za pomocą Charset.

  • Path writeString (Path, CharSequence, java.nio.file. OpenOption []): Jeśli zapiszesz ciąg znaków CharSequencedo pliku, znaki te zostaną zakodowane w bajtach (przy użyciu UTF-8 ).

  • Path writeString (Path, CharSequence, java.nio.file. Charset, OpenOption []): działa jak powyższa metoda, tylko znaki są kodowane w bajtach przy użyciu Charset.
ścieżka.pliku Java.nio
  • Path(String, String[]): Zwraca ścieżkę, przekształcając ciąg ścieżki lub sekwencję ciągów, które po połączeniu tworzą ciąg ścieżki.

  • Ścieżka (net.URI): Zwraca ścieżkę poprzez przekształcenie identyfikatora URI.
Kolekcja java.util
  • Object [] toArray (java.util.function.IntFunction): Zwraca tablicę zawierającą wszystkie elementy w tej kolekcji, korzystając z dostarczonej funkcji generatora w celu dystrybucji zwróconej tablicy.
java.util.concurrent.PriorityBlockingQueue java.util.PriorityQueue
  • void forEach (java.util.function.Consumer): Wykonuje określoną akcję na każdym elemencie Iterable , dopóki wszystkie elementy nie zostaną przetworzone lub akcja nie zgłosi wyjątku.

  • boolean removeAll (java.util.Collection): Usuwa wszystkie elementy tej kolekcji, które są również zawarte w określonej kolekcji (operacja opcjonalna).

  • boolean removeIf (java.util.function.Predicate): Usuwa wszystkie elementy tej kolekcji, które spełniają podany predykat.

  • boolean retainAll (java.util.Collection): Zachowuje tylko te elementy z tej kolekcji, które znajdują się w określonej kolekcji (operacja opcjonalna).
java.util.concurrent.TimeUnit
  • long convert (java.time.Duration): Przelicza podany czas na tę jednostkę.
Java.util.function.Predicate
  • Predicate not(Predicate): zwraca predykat będący negacją podanego predykatu.
Na przykład następujący kod:
lines.stream ()

.filter (s ->! s.isBlank ())
można przekonwertować na to:
lines.stream ()

.filter (Predicate.not (String :: ISBLANK))
a jeśli użyjemy importu statycznego, otrzymamy coś takiego:
lines.stream ()
.filter (not(String :: ISBLANK))
java.util.Optional java.util.OptionalInt java.util.OptionalDouble java.util.OptionalLong
  • boolean isEmpty (): Zwraca wartość true , jeśli nie ma wartości , w przeciwnym razie false .
Wzorzec java.util.regex
  • Predicate asMatchPredicate (): Ekspert Java Simon Ritter uważa, że ​​może tu być ukryty prawdziwy klejnot API JDK 11. Ta metoda tworzy predykat, który sprawdza, czy ten wzorzec pasuje do danego ciągu wejściowego.
Java.util.zip.Deflater
  • int deflate (ByteBuffer): Kompresuje dane wejściowe i wypełnia określony bufor skompresowanymi danymi.

  • int deflate (ByteBuffer, int): Kompresuje dane wejściowe i wypełnia określony bufor skompresowanymi danymi. Zwraca rzeczywistą ilość skompresowanych danych.

  • void setDictionary (ByteBuffer): Ustawia skompresowanie danego słownika do bajtów w danym buforze. Jest to przeciążenie istniejącej metody, która może teraz akceptować tablicę ByteBufferzamiast tablicy bajtów.

  • void setInput (ByteBuffer): Ustawia kompresję danych wejściowych. Jest to również przeciążenie istniejącej metody.
java.util.zip.Inflater
  • int inflate (ByteBuffer): Rozpakowuje bajty do określonego bufora. Zwraca rzeczywistą liczbę nieskompresowanych bajtów.

  • void setDictionary (ByteBuffer): Ustawia dany słownik na bajty w danym buforze. Jest przeciążoną formą istniejącej metody.

  • void setInput (ByteBuffer): Ustawia dane wejściowe do dekompresji. Przeciążona forma istniejącej metody.
javax.print.attribute.standard.DialogOwner Jest to nowa klasa w JDK 11 i jest klasą atrybutów używaną do obsługi żądań drukowania lub dostosowywania stron, które mają być wyświetlane na wierzchu wszystkich okien lub określonego okna. javax.swing.DefaultComboBoxModel javax.swing.DefaultListModel
  • void addAll (Collection): Dodaje wszystkie elementy obecne w kolekcji.

  • void addAll (int, Collection): Dodaje wszystkie elementy obecne w kolekcji, zaczynając od określonego indeksu.
javax.swing.ListSelectionModel
  • int [] getSelectedIndices (): Zwraca tablicę wszystkich wybranych indeksów w wybranym modelu w kolejności rosnącej.

  • int getSelectedItemsCount (): Zwraca liczbę wybranych elementów.
jdk.jshell.EvalException
  • shell.JShellException getCause (): Zwraca powód, który można zgłosić w kliencie wykonawczym przedstawiony przez ten wyjątek EvalException, lub wartość null, jeśli przyczyna nie istnieje lub jest nieznana.

Funkcje inne niż programistyczne Java 11

[181] Kontrola dostępu oparta na gniazdach Java i inne języki obsługują klasy zagnieżdżone poprzez klasy wewnętrzne. Aby to zadziałało, kompilator musi wykonać pewne sztuczki. Na przykład:
public class Outer {
    private int outerInt;

     class Inner {
       public void printOuterInt() {
         System.out.println("Outer int = " + outerInt);
       }
     }
   }
Kompilator modyfikuje to, aby przed kompilacją uzyskać coś takiego:
public class Outer {
      private int outerInt;

      public int access$000() {
        return outerInt;
      }

    }


    class Inner$Outer {

      Outer outer;

      public void printOuterInt() {
        System.out.println("Outer int = " + outer.access$000());
      }
    }
Chociaż logicznie rzecz biorąc, klasa wewnętrzna jest częścią tego samego kodu co klasa zewnętrzna, jest kompilowana jako osobna klasa. Dlatego ta operacja wymaga metody łączenia syntetycznego, która musi zostać utworzona przez kompilator, aby zapewnić dostęp do pola prywatnego klasy zewnętrznej. Ten JEP wprowadza koncepcję gniazd, w której dwóch członków tego samego gniazda (w naszym przykładzie Zewnętrzne i Wewnętrzne) jest kumplami w zagnieżdżaniu. Dla formatu pliku klasy zdefiniowano dwa nowe atrybuty: NestHost i NestMembers . Zmiany te są przydatne w przypadku innych języków obsługujących klasy zagnieżdżone i kod bajtowy. Ta funkcja wprowadza trzy nowe metody dla java.lang.Class : Class getNestHost () Class [] getNestMembers () boolean isNestmateOf (Class) [309] Dynamiczne stałe pliku klasy Ten JEP opisuje rozszerzenie formatu pliku klasy w celu obsługi nowego trwała pula w formie CONSTANT_Dynamic. Idea stałej dynamicznej wydaje się oksymoronem, ale zasadniczo można o niej myśleć jako o wartości końcowej w Javie 11. Wartość stałej puli nie jest ustawiana w czasie kompilacji (w przeciwieństwie do innych stałych), ale wykorzystuje bootstrap metoda określenia wartości w momencie realizacji. Dlatego wartość jest dynamiczna, ale ponieważ jej wartość jest ustawiana tylko raz, jest również stała. Ta funkcja jest skierowana przede wszystkim do osób tworzących nowe języki i kompilatory, które będą generować kody bajtowe i pliki klas jako dane wyjściowe do uruchomienia na maszynie JVM. [315] Ulepsz elementy wewnętrzne Aarch64 Ten JEP został zaproponowany przez społeczność Red Hat. JVM może teraz korzystać z bardziej wyspecjalizowanych instrukcji dostępnych w zestawie instrukcji Arm 64. W szczególności poprawia to wydajność metod , sin ()i cos ()klasy java.lang.Math . [318] Epsilon: Niedziałający moduł zbierający śmieci Podobnie jak w przypadku JEP 315 , możesz podziękować firmie Red Hat za wprowadzenie modułu zbierającego śmieci Epsilon. Epsilon jest niezwykły, ponieważ tak naprawdę nie zbiera śmieci! Tworząc nowe obiekty, w razie potrzeby przydziela pamięć, ale nie odzyskuje miejsca zajmowanego przez niezarejestrowane obiekty. " Jaki jest sens? ", - ty pytasz. Okazuje się, że to „zbieranie śmieci” ma dwa zastosowania: log ()
  1. Po pierwsze, ten moduł zbierający elementy bezużyteczne został zaprojektowany w celu zapewnienia oceny nowych algorytmów GC pod kątem ich wpływu na wydajność. Pomysł polega na uruchomieniu przykładowej aplikacji za pomocą Epsilon i wygenerowaniu zestawu metryk. Włączany jest nowy algorytm zbierania śmieci, uruchamiane są te same testy, a następnie porównywane są wyniki.

  2. W przypadku bardzo krótkich zadań (pomyśl o funkcjach bezserwerowych w chmurze), gdzie możesz zagwarantować, że nie przekroczysz pamięci przydzielonej do sterty. Może to poprawić wydajność poprzez wyeliminowanie narzutu (w tym zbierania statystyk potrzebnych do podjęcia decyzji o uruchomieniu modułu zbierającego) w kodzie aplikacji. Jeśli miejsce na stercie zostanie wyczerpane, maszyna JVM może zostać błędnie skonfigurowana na jeden z trzech sposobów:
    • Normalność nazywa się OutOfMemoryError.
    • Wykonaj reset sterty
    • Dysk twardy JVM uległ awarii i może wykonywać inne zadanie (takie jak uruchamianie debugera).
[328]: Rejestrator lotu Rejestrator lotu to środowisko gromadzenia danych niskiego poziomu dla JVM. Przed wersją JDK 11 była to funkcja komercyjna w pliku binarnym Oracle JDK. Oracle eliminuje obecnie różnice funkcjonalne pomiędzy pakietem Oracle JDK a kompilacją z OpenJDK. Oto, co robi Rejestrator lotu :
  • Zapewnia interfejs API do tworzenia i korzystania z danych jako zdarzeń
  • Zapewnia mechanizm buforowy i binarny format danych
  • Umożliwia dostosowywanie i filtrowanie zdarzeń
  • Dostarczaj zdarzenia dla bibliotek OS, JVM HotSpot i JDK
Istnieją tutaj dwa nowe moduły: jdk.jfr i jdk.management.jfr . [329] Algorytmy kryptograficzne ChaCha20 i Poly1305 Ten JEP dotyczy aktualizacji szyfrów używanych przez JDK. W tym przypadku implementowane są algorytmy szyfrowania ChaCha20 i ChaCha20-Poly1305 zgodnie z specyfikacją RFC 7539. ChaCha20 to stosunkowo nowy szyfr strumieniowy, który może zastąpić starszy, niepewny szyfr RC4 . [333] ZGC: Skalowalny moduł zbierający elementy bezużyteczne o niskim opóźnieniu Eksperymentalny, skalowalny moduł zbierający elementy bezużyteczne o niskim opóźnieniu. Zaprojektowany do użytku z aplikacjami wymagającymi dużej (wielogigabajtowej) sterty i małych opóźnień. Używa sterty pojedynczej generacji i wykonuje większość (ale nie wszystkie) operacji usuwania śmieci w tym samym czasie co aplikacja. [332] Transport Layer Security (TLS) 1.3 TLS 1.3 (RFC 8446) to główna poprawka do protokołu zabezpieczeń warstwy transportowej TLS, która zapewnia znaczną poprawę bezpieczeństwa i wydajności w porównaniu z poprzednimi wersjami. JDK obsługuje teraz tę wersję protokołu. Materiał powstał w oparciu o artykuł Simona Rittera i oficjalną dokumentację .
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION