Спешите увидеть Java11, иначе вас не будет!

Java
Спешите увидеть Java11, иначе вас не будет!

предисловие

Спешите увидеть Java11, иначе вас не будет!Это ссылка на оригинальный пост в блоге. Слишком быстро обновляется Java, и я не могу ее изучить, недавно узнал о некоторых фичах после Java 8. Надеюсь, она будет всем полезна.

Почему стоит выбрать Java11

  • Поддержка контейнерной среды, улучшения в таких областях, как GC.
  • Он был уменьшен, стал более легким, а установочный пакет стал меньше по размеру.
  • JDK11 — это выпуск с долгосрочной поддержкой.

Введение в функцию

Поскольку это напрямую от Java8 на Java11, введение функции введет некоторые функции Java9-Java11 вместе. Друзья, которые хотят понять функции Java8, могут пойти в мой блог, чтобы найти «серии Java8».

Jshell @since 9

Jshell был предложен в Java9, вы можете писать Java-программы прямо на терминале и нажимать Enter для выполнения. Jshell по умолчанию импортирует некоторые из следующих пакетов, поэтому содержимое этих пакетов доступно в среде Jshell.

import java.lang.*;
import java.io.*;
import java.math.*;
import java.net.*;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.*;
import java.util.prefs.*;
import java.util.regex.*;
import java.util.stream.*;
1. Что такое Jshell?

Jshell был представлен в Java 9. Он предоставляет интерактивную оболочку для быстрого создания прототипов, отладки, изучения Java и API Java, и все это без необходимости использования общедоступного метода static void main или компиляции кода перед выполнением.

2. Использование Jshell

Откройте терминал, введите jshell, чтобы войти в среду jshell, а затем введите /help intro, чтобы просмотреть введение в Jshell.

 lixiaoshuang@localhost  ~  jshell
|  欢迎使用 JShell -- 版本 11.0.2
|  要大致了解该版本, 请键入: /help intro

jshell> /help intro
|
|                                   intro
|                                   =====
|
|  使用 jshell 工具可以执行 Java 代码,从而立即获取结果。
|  您可以输入 Java 定义(变量、方法、类等等),例如:int x = 8
|  或 Java 表达式,例如:x + x
|  或 Java 语句或导入。
|  这些小块的 Java 代码称为“片段”。
|
|  这些 jshell 工具命令还可以让您了解和
|  控制您正在执行的操作,例如:/list
|
|  有关命令的列表,请执行:/help

jshell>

Jshell действительно очень полезный инструмент, я не буду вдаваться в подробности, приведу пример, а остальное вы испытаете сами. Например, теперь мы хотим случайным образом сгенерировать UUID, что раньше делалось:

  • Создание класса.
  • Создайте основной метод.
  • Затем напишите логику для генерации UUID и выполните ее.

Теперь просто нужно зайти в открытый терминал и ввести jshell, затем войти напрямуюvar uuid = UUID.randomUUID()Входить.就可以看到uuid的回显,这样我们就得到了一个uuid。并不需要public static void main(String[] args);

 lixiaoshuang@localhost  ~  jshell
|  欢迎使用 JShell -- 版本 11.0.2
|  要大致了解该版本, 请键入: /help intro

jshell> var uuid = UUID.randomUUID();
 uuid ==> 9dac239e-c572-494f-b06d-84576212e012
jshell>
3. Как выйти из Jshell?

Введите в среде Jshell/exitвыходить.

 lixiaoshuang@localhost  ~ 
 lixiaoshuang@localhost  ~  jshell
|  欢迎使用 JShell -- 版本 11.0.2
|  要大致了解该版本, 请键入: /help intro

jshell> var uuid = UUID.randomUUID();
uuid ==> 9dac239e-c572-494f-b06d-84576212e012

jshell> /exit
|  再见
 lixiaoshuang@localhost  ~ 

Модуль @с 9

1. Что такое модульность?

Модульность — это добавление агрегации более высокого уровня, которая представляет собой инкапсуляцию Package. Пакет — это соглашение для некоторых имен путей к классам, а модуль — это инкапсуляция одного или нескольких пакетов.

До java9: пакет => класс/интерфейс.

После java9: модуль => пакет => класс/интерфейс.

Так какие модули были сплит JDK? Откройте терминал и выполнитьjava --list-modulesПроверять.

lixiaoshuang@localhost  ~ java --list-modules
java.base@11.0.2
java.compiler@11.0.2
java.datatransfer@11.0.2
java.desktop@11.0.2
java.instrument@11.0.2
java.logging@11.0.2
java.management@11.0.2
java.management.rmi@11.0.2
java.naming@11.0.2
java.net.http@11.0.2
java.prefs@11.0.2
java.rmi@11.0.2
java.scripting@11.0.2
java.se@11.0.2
java.security.jgss@11.0.2
java.security.sasl@11.0.2
java.smartcardio@11.0.2
java.sql@11.0.2
java.sql.rowset@11.0.2
java.transaction.xa@11.0.2
java.xml@11.0.2
java.xml.crypto@11.0.2
jdk.accessibility@11.0.2
jdk.aot@11.0.2
jdk.attach@11.0.2
jdk.charsets@11.0.2
jdk.compiler@11.0.2
jdk.crypto.cryptoki@11.0.2
jdk.crypto.ec@11.0.2
jdk.dynalink@11.0.2
jdk.editpad@11.0.2
jdk.hotspot.agent@11.0.2
jdk.httpserver@11.0.2
jdk.internal.ed@11.0.2
jdk.internal.jvmstat@11.0.2
jdk.internal.le@11.0.2
jdk.internal.opt@11.0.2
jdk.internal.vm.ci@11.0.2
jdk.internal.vm.compiler@11.0.2
jdk.internal.vm.compiler.management@11.0.2
jdk.jartool@11.0.2
jdk.javadoc@11.0.2
jdk.jcmd@11.0.2
jdk.jconsole@11.0.2
jdk.jdeps@11.0.2
jdk.jdi@11.0.2
jdk.jdwp.agent@11.0.2
jdk.jfr@11.0.2
jdk.jlink@11.0.2
jdk.jshell@11.0.2
jdk.jsobject@11.0.2
jdk.jstatd@11.0.2
jdk.localedata@11.0.2
jdk.management@11.0.2
jdk.management.agent@11.0.2
jdk.management.jfr@11.0.2
jdk.naming.dns@11.0.2
jdk.naming.rmi@11.0.2
jdk.net@11.0.2
jdk.pack@11.0.2
jdk.rmic@11.0.2
jdk.scripting.nashorn@11.0.2
jdk.scripting.nashorn.shell@11.0.2
jdk.sctp@11.0.2
jdk.security.auth@11.0.2
jdk.security.jgss@11.0.2
jdk.unsupported@11.0.2
jdk.unsupported.desktop@11.0.2
jdk.xml.dom@11.0.2
jdk.zipfs@11.0.2
2. Почему вы это делаете?

Всем известно, что в JRE есть супербольшой rt.jar (более 60 Мб), а tools.jar тоже имеет десятки мегабайт, раньше для hello world требовались сотни мегабайт среды.

  • Делает программы Java SE более простыми и легкими в развертывании.
  • Мощные возможности упаковки.
  • Улучшите управление зависимостями между компонентами и внедрять модули с большим зернистостью, чем банки.
  • Улучшить производительность и безопасность.
3. Как определить модуль?

Модуль определяется в файле module-info.java, и после компиляции и упаковки он становится сущностью модуля. Давайте взглянем на простейшее определение модуля.

4. Ключевые слова модуля
  • open

    Используется для указания открытых модулей, все пакеты открытых модулей являются общедоступными, на общедоступные можно напрямую ссылаться и использовать, а другие типы можно получить посредством отражения.

    open module module.one {
        //导入日志包
       requires java.logging;
    
    }
    
  • opens

    opens используется для указания открытых пакетов, в которых общедоступные типы могут быть доступны напрямую, а другие типы могут быть получены посредством отражения.

    module module.one {
    
        opens <package>;
    }
    
  • exports

    Которые экспортируют указанные модули пакетов могут быть доступен другими модулями.

    module module.one {
        
        exports <package>;
        
        exports <package> to <module1>, <module2>...;
    }
    
  • requires

    Это ключевое слово объявляет зависимость текущего модуля от другого модуля.

    module module.one {
    
        requires <package>;
    
    }
    
  • использует, обеспечивает... с...

    В операторе uses используется имя интерфейса службы, и текущий модуль найдет его и использует класс java.util.ServiceLoader для его загрузки, который должен быть в этом модуле, а не в других модулях. Его класс реализации может быть предоставлен другие модули.

    module module.one {
    
        //对外提供的接口服务 ,下面指定的接口以及提供服务的impl,如果有多个实现类,用用逗号隔开
        uses <接口名>;
    
        provides <接口名> with <接口实现类>,<接口实现类>;
    
    }
    

var ключевое слово @с 10

1.Что такое вар?

var — это новый вывод переменной локального типа в Java 10. Он делает вывод о типе переменной на основе следующего значения, поэтому переменная var должна быть инициализирована.

пример:

var a;       ❌
var a = 1;   ✅
2. пример использования var
  • var определяет локальную переменную

    var a = 1; 
    等于
    int a = 1;
    
  • var, когда метод-получатель возвращает значение

    var result = this.getResult();
    等于
    String result = this.getResult();
    
  • Определение локальной переменной в цикле var

    for (var i = 0; i < 5; i++) {
       System.out.println(i);
    }
    等于
    for (int i = 0; i < 5; i++) {
       System.out.println(i);
    }
    
  • var в сочетании с дженериками

    var list1 = new ArrayList<String>();  //在<>中指定了list类型为String
    等于
    List<String> list1 = new ArrayList<>();
    
    var list2 = new ArrayList<>();        //<>里默认会是Object
    
  • var используется в Lambda (доступно только в java11)

    Consumer<String> Consumer = (var i) -> System.out.println(i);
    等于
    Consumer<String> Consumer = (String i) -> System.out.println(i);
    
3.var больше нельзя использовать?
  • Тип переменного члена класса.
  • Тип возвращаемого значения метода.
  • Lambda не может использовать var в Java10, но может использоваться в Java11.

расширенный API

1. Улучшение строк с 11 лет
// 判断字符串是否为空白
" ".isBlank();                     // true

// 去除首尾空格
" Hello Java11 ".strip();          // "Hello Java11"

// 去除尾部空格 
" Hello Java11 ".stripTrailing();  // " Hello Java11"

// 去除首部空格 
" Hello Java11 ".stripLeading();   // "Hello Java11 "

// 复制字符串
"Java11".repeat(3);                // "Java11Java11Java11"

// 行数统计
"A\nB\nC".lines().count();         // 3
2. Расширение коллекции

Начиная с Java 9, в JDK добавлены методы OF и COPYOF для коллекции (List, SET, MAP). Они используются для создания непеременной коллекции.

  • of() @since 9
  • copyOf() @since 10

Пример первый:

        var list = List.of("Java", "Python", "C"); //不可变集合
        var copy = List.copyOf(list);         //copyOf判断是否是不可变集合类型,如果是直接返回
        System.out.println(list == copy);    // true

        var list = new ArrayList<String>();  // 这里返回正常的集合
        var copy = List.copyOf(list);        // 这里返回一个不可变集合
        System.out.println(list == copy);    // false

Пример второй:

        var set = Set.of("Java", "Python", "C");
        var copy = Set.copyOf(set);
        System.out.println(set == copy);     // true

        var set1 = new HashSet<String>();
        var copy1 = List.copyOf(set1);
        System.out.println(set1 == copy1);   // false

Пример третий:

        var map = Map.of("Java", 1, "Python", 2, "C", 3);
        var copy = Map.copyOf(map);
        System.out.println(map == copy);     // true

        var map1 = new HashMap<String, Integer>();
        var copy1 = Map.copyOf(map1);
        System.out.println(map1 == copy1);   // false

注意:使用 of 和 copyOf 创建的集合为不可变集合,不能进行添加、删除、替换、排序等操作,不然会报java.lang.UnsupportedOperationException异常,使用Set.of()不能出现重复元素、Map.of()不能出现重复key,否则回报java.lang.IllegalArgumentException。.

3. Улучшение потоковой передачи с 9 лет

Stream — это функция Java 8, а в Java 9 к нему добавлено 4 метода:

  • ofNullable(T t)

    Этот метод может принимать NULL для создания пустого потока

    以前
    Stream.of(null);  //报错
    现在
    Stream.ofNullable(null);
    
  • takeWhile(Predicate<? super T> predicate)

    Этот метод судит в соответствии с интерфейсом предиката, если это правда取出Чтобы сгенерировать новый поток, если он встретит false, он завершится, независимо от того, удовлетворяют ли следующие элементы условиям.

            Stream<Integer> integerStream = Stream.of(6, 10, 11, 15, 20);
            Stream<Integer> takeWhile = integerStream.takeWhile(t -> t % 2 == 0);
            takeWhile.forEach(System.out::println);   // 6,10
    
  • dropWhile(Predicate<? super T> predicate)

    Этот метод судит в соответствии с интерфейсом Predicate, если он верен.丢弃Чтобы сгенерировать новый поток, если он встретит false, он завершится, независимо от того, удовлетворяют ли следующие элементы условиям.

            Stream<Integer> integerStream = Stream.of(6, 10, 11, 15, 20);
            Stream<Integer> takeWhile = integerStream.dropWhile(t -> t % 2 == 0);
            takeWhile.forEach(System.out::println);  //11,15,20
    
  • повторять перегрузку

    Раньше при использовании метода iterate для создания бесконечного потока необходимо было усекать ограничение

            Stream<Integer> limit = Stream.iterate(1, i -> i + 1).limit(5);
            limit.forEach(System.out::println);   //1,2,3,4,5
    

    Теперь после перегрузки этот метод добавляет параметр оценки

            Stream<Integer> iterate = Stream.iterate(1, i -> i <= 5, i -> i + 1);
            iterate.forEach(System.out::println);  //1,2,3,4,5
    
4. Дополнительное улучшение с 9 лет
  • stream()

    Возвращает пустой поток, если он пуст, и преобразует значение Optional в поток, если он не пуст.

            //返回Optional值的流
            Stream<String> stream = Optional.of("Java 11").stream();
            stream.forEach(System.out::println);    // Java 11
            
            //返回空流
            Stream<Object> stream = Optional.ofNullable(null).stream();
            stream.forEach(System.out::println);    // 
    
  • ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)

    Лично я считаю, что этот метод является усовершенствованием Else в сочетании с isPresent(). Цель метода ifPresentOrElse заключается в том, что если необязательное значение содержит значение, действие функции вызывается для содержащегося значения, то есть action.accept( value), что согласуется с ifPresent; и отличие от метода ifPresent заключается в том, что ifPresentOrElse имеет второй параметр emptyAction — если Optional не содержит значения, тогда ifPresentOrElse вызывает emptyAction, который является emptyAction.run().

            Optional<Integer> optional = Optional.of(1);
            optional.ifPresentOrElse( x -> System.out.println("Value: " + x),() ->
                    System.out.println("Not Present."));    //Value: 1
            
            optional = Optional.empty();
            optional.ifPresentOrElse( x -> System.out.println("Value: " + x),() ->
                    System.out.println("Not Present."));    //Not Present.
    
  • or(Supplier<? extends Optional<? extends T>> supplier)

        Optional<String> optional1 = Optional.of("Java");
        Supplier<Optional<String>> supplierString = () -> Optional.of("Not Present");
        optional1 = optional1.or( supplierString);
        optional1.ifPresent( x -> System.out.println("Value: " + x));  //Value: Java

        optional1 = Optional.empty();
        optional1 = optional1.or( supplierString);
        optional1.ifPresent( x -> System.out.println("Value: " + x)); //Value: Not Present
5. Улучшение InputStream @ с 9
        String lxs = "java";
        try (var inputStream = new ByteArrayInputStream(lxs.getBytes());
             var outputStream = new ByteArrayOutputStream()) {
            inputStream.transferTo(outputStream);
            System.out.println(outputStream);    //java
        }

HTTP Client API

Измените API, чтобы он поддерживал как синхронные, так и асинхронные методы. Ниже приведены примеры двух методов:

        var request = HttpRequest.newBuilder()
                .uri(URI.create("https://www.baidu.com/"))
                .build();
        var client = HttpClient.newHttpClient();
        // 同步
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println(response.body());

        // 异步
        CompletableFuture<HttpResponse<String>> sendAsync = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
        //这里会阻塞
        HttpResponse<String> response1 = sendAsync.get();
        System.out.println(response1.body());

Запуск java-файлов напрямую

Мы все знаем, что для запуска файла .java раньше мы должны сначала компилировать Javac в файл .class, а затем выполнить его в Java:

//编译
javac Java11.java
//运行
java Java11

В java11 это можно сделать всего одной командой java

java Java11.java

удалить содержимое

  • ком.вс..ну вопрос.. А ВТ утилиты.
  • sun.misc.Unsafe.defineClass Вместо этого используйте java.lang.invoke.MethodHandles.Lookup.defineClass.
  • Методы Thread.destroy() и Thread.stop(Throwable).
  • Свойство sun.nio.ch.disableSystemWideOverlappingFileLockCheck.
  • свойство sun.locale.formata по умолчанию.
  • jdk snmp-модуль.
  • javafx, openjdk был удален из версии java10, oracle java10 еще не удалил javafx, а версия java11 также удалила javafx.
  • Java Mission Control после удаления из JDK необходимо загружать отдельно.
  • Корневые сертификаты: Baltimore Cybertrust Code Signing CA, SECOM, AOL и Swisscom.
  • Удалены модули Java EE и CORBA, помеченные java9 как устаревшие в java11.

Полная поддержка контейнеров Linux (включая докер)

Многие приложения, работающие на виртуальной машине Java, включая службы данных, такие как Apache Spark и Kafka, а также традиционные корпоративные приложения, могут работать в контейнерах Docker. Но запуск приложения Java в контейнере Docker всегда был проблемой, то есть запуск программы JVM в контейнере приведет к снижению производительности приложения после установки размера памяти и использования ЦП. Это связано с тем, что приложение Java не знает, что оно работает в контейнере. С выпуском Java 10 эта проблема наконец была решена, и теперь JVM может распознавать ограничения, установленные группами управления контейнерами (cgroups). Приложениями Java можно управлять непосредственно в контейнерах, используя ограничения памяти и ЦП, в том числе:

  • Соблюдайте лимит памяти, установленный в контейнере
  • Установите доступный ЦП в контейнере
  • Установка ограничений ЦП в контейнере

Java 10的这个改进在Docker for Mac、Docker for Windows以及Docker Enterprise Edition等环境均有效。

Суммировать

Java版本特性.png

Ссылаться на

сегмент fault.com/ah/119000001…

Спасибо за просмотр, и я надеюсь увидеть больше. Если есть ошибка, пожалуйста, поправьте меня.