Java8 Lambda 表达式 让 java 也能支持简单的函数式编程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 new Thread (new Runnable () { @Override public void run () { System.out.println("The runable now is using!" ); } }).start(); new Thread (() -> System.out.println("It's a lambda function!" )).start();List<Integer> strings = Arrays.asList(1 , 2 , 3 ); Collections.sort(strings, new Comparator <Integer>() { @Override public int compare (Integer o1, Integer o2) { return o1 - o2;} }); Collections.sort(strings, (Integer o1, Integer o2) -> o1 - o2); Comparator<Integer> comperator = (Integer o1, Integer o2) -> o1 - o2; Collections.sort(strings, comperator);
Stream Stream依然不存储数据,不同的是它可以检索(Retrieve)和逻辑处理集合数据、包括筛选、排序、统计、计数等。可以想象成是 Sql 语句 。
它的源数据可以是 Collection、Array 等。由于它的方法参数都是函数式接口类型,所以一般和 Lambda 配合使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 @Test public void test () { List<String> strings = Arrays.asList("abc" , "def" , "gkh" , "abc" ); Stream<String> stringStream = strings.stream().filter(s -> "abc" .equals(s)); long count = stringStream.count(); strings.stream().forEach(System.out::println); Stream<String> limit = strings.stream().limit(1 ); String[] array = limit.toArray(String[]::new ); Stream<String> map = strings.stream().map(s -> s + "22" ); strings.stream().sorted().forEach(System.out::println); List<String> collect = strings.stream().filter(string -> "abc" .equals(string)).collect(Collectors.toList()); String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining("," )); List<Integer> number = Arrays.asList(1 , 2 , 5 , 4 ); IntSummaryStatistics statistics = number.stream().mapToInt((x) -> x).summaryStatistics(); System.out.println("列表中最大的数 : " +statistics.getMax()); System.out.println("列表中最小的数 : " +statistics.getMin()); System.out.println("平均数 : " +statistics.getAverage()); System.out.println("所有数之和 : " +statistics.getSum()); List<String> strings2 = Arrays.asList("xyz" , "jqx" ); Stream.concat(strings2.stream(),strings.stream()).count(); Stream stream = strings.stream(); stream.limit(2 ); stream.forEach(System.out::println); stream.limit(2 ).forEach(System.out::println); }
Optional表达式 主要用于解决NPE问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Zoo zoo = getZoo();if (zoo != null ){ Dog dog = zoo.getDog(); if (dog != null ){ int age = dog.getAge(); System.out.println(age); } } Optional.ofNullable(zoo).map(o -> o.getDog()).map(d -> d.getAge()).ifPresent(age -> System.out.println(age) );
Interface新增默认方法,可以用default 或 static修饰 目的:避免接口新增方法时,所有实现的类也必须跟着修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public interface InterfaceNew { static void sm () { System.out.println("interface提供的方式实现" ); } static void sm2 () { System.out.println("interface提供的方式实现" ); } default void def () { System.out.println("interface default方法" ); } default void def2 () { System.out.println("interface default2方法" ); } void f () ; }
Date-Time API 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public void newFormat () { LocalDate date = LocalDate.now(); System.out.println(String.format("date format : %s" , date)); LocalTime time = LocalTime.now().withNano(0 ); System.out.println(String.format("time format : %s" , time)); LocalDateTime dateTime = LocalDateTime.now(); DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss" ); String dateTimeStr = dateTime.format(dateTimeFormatter); System.out.println(String.format("dateTime format : %s" , dateTimeStr)); LocalDate date = LocalDate.of(2021 , 1 , 26 ); LocalDate.parse("2021-01-26" ); LocalDateTime dateTime = LocalDateTime.of(2021 , 1 , 26 , 12 , 12 , 22 ); LocalDateTime.parse("2021-01-26 12:12:22" ); LocalTime time = LocalTime.of(12 , 12 , 22 ); LocalTime.parse("12:12:22" ); }
Java9 接口私有方法 1 2 3 4 public interface MyInterface { private void methodPrivate () { } }
JShell JShell 是 Java 9 新增的一个实用工具。为 Java 提供了类似于 Python 的实时命令行交互工具。目前能想到的最大的作用就是可以用于验证一些代码中的小问题 。
1 jshell > System.out.print("HelloWorld");
集合新增of() 方法,用于快速创建集合对象 1 2 3 List.of("Java" , "C++" ); Set.of("Java" , "C++" ); Map.of("Java" , 1 , "C++" , 2 );
String由char[]数组改为byte[]数组存储 1 2 3 4 5 public final class String implements java .io.Serializable,Comparable<String>, CharSequence { @Stable private final byte [] value; }
模块化系统 可以看成是大于package小于jar的一种结构,用于代码之间更高效的调用。在每个模块中加入一个module-info.java文件,写入下列描述,用于声明暴露和依赖的模块。
1 2 3 4 5 6 7 8 9 10 module modular.demo.persistent { exports com.hanmc.example.modulardemo.persistent.domain; exports com.hanmc.example.modulardemo.persistent.dao; requires modular.demo.common; requires mybatis.plus; requires mybatis.plus.core; requires mybatis.plus.annotation; }
目录结构如下:
引入孵化器模块jdk.incubator java9开始新特性不再是一定保留,而是会在版本中进行迭代,这些新特性就放在孵化器中,如果随着迭代得以保留就会从孵化器中移出成为正式的特性,不合适的就会直接移除。这大大增强了java新特性开发的灵活性。
G1 成为默认垃圾回收器 Stream & Optional 增强 进程API Java 9 增加了 java.lang.ProcessHandle 接口来实现对原生进程进行管理,尤其适合于管理长时间运行的进程。
1 2 3 4 5 6 ProcessHandle currentProcess = ProcessHandle.current();System.out.println(currentProcess.pid()); System.out.println(currentProcess.info());
Java10 局部变量类型推断(var) var 并不会改变 Java 是一门静态类型语言的事实,编译器负责推断出类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 var id = 0 ;var codefx = new URL ("https://mp.weixin.qq.com/" );var list = new ArrayList <>();var list = List.of(1 , 2 , 3 );var map = new HashMap <String, String>();var p = Paths.of("src/test/java/Java9FeaturesTest.java" );var numbers = List.of("a" , "b" , "c" );for (var n : list) System.out.print(n+ " " ); var count=null ; var r = () -> Math.random();var array = {1 ,2 ,3 };
若干性能的提升 G1 并行 Full GC 从java9的单线程标记-清除-压缩算法转为并行算法,从而有效的减少stop-the-world的时间
AppCDS原本是商业特性,现在免费开源了。 我的理解,简单来说是将类加载器中的类生成一份共享档案文件,从而在jvm启动时直接读取内存中的对应类,可以加快jvm的启动速度。
Graal 是一种java编写的动态编译器,可实现更高的性能和拓展性。同时也是java9中介绍过的Ahead-of-Time(AOT)编译器的基础。 加入以下参数开启Graal虚拟机
1 -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler
不可变集合 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Test(expected = UnsupportedOperationException.class) public void whenModifyCopyOfList_thenThrowsException () { List<Integer> copyList = List.copyOf(someIntList); copyList.add(4 ); } @Test(expected = UnsupportedOperationException.class) public void whenModifyToUnmodifiableList_thenThrowsException () { List<Integer> evenList = someIntList.stream() .filter(i -> i % 2 == 0 ) .collect(Collectors.toUnmodifiableList()); evenList.add(4 ); }
Optional增加orElseThrow() 方法 容器意识 现在jvm能够知道自己在容器中运行,增加了几种容器中的jvm参数
1 2 3 4 5 -XX:-UseContainerSupport -XX:ActiveProcessorCount=count -XX:InitialRAMPercentage -XX:MaxRAMPercentage -XX:MinRAMPercentage
根证书 现在java的证书密钥库包含了一些根证书,可用于对若干安全协议建立可信的证书连接。此功能被oracle从商业特性改为开源特性。
基于时间发布版本 Java10开始,oracle开始周期性的发布新版本: 1.每六个月发布一个java新版本。 2.功能性的发布只会支持6个月。 3.长期支持的版本会标记为LTS。该版本会支持3年。 4.java版本号现在会包含一个时间标示。
1 2 3 4 $ java -version openjdk version "10" 2018 -03 -20 OpenJDK Runtime Environment 18.3 (build 10 +46 ) OpenJDK 64 -Bit Server VM 18.3 (build 10 +46 , mixed mode)
Java11 Java11是Java8之后第一个长期支持的版本(LTS)。同时Oracle不再提供免费的Oracle JDK版本,但是依然对免费的Open JDK提供支持。
新的String方法 新增 isBlank, lines, strip, stripLeading, stripTrailing, and repeat
1 2 3 4 5 6 7 String multilineString = "Baeldung helps \n \n developers \n explore Java." ;List<String> lines = multilineString.lines() .filter(line -> !line.isBlank()) .map(String::strip) .collect(Collectors.toList()); assertThat(lines).containsExactly("Baeldung helps" , "developers" , "explore Java." );
新的Files操作方法 Files类新增writeString和readString静态方法,现在更容易从文件中操作String。
1 2 3 Path filePath = Files.writeString(Files.createTempFile(tempDir, "demo" , ".txt" ), "Sample text" );String fileContent = Files.readString(filePath);assertThat(fileContent).isEqualTo("Sample text" );
集合到数组 java.util.Collection接口新增默认方法toArray
1 2 3 List sampleList = Arrays.asList("Java" , "Kotlin" );String[] sampleArray = sampleList.toArray(String[]::new ); assertThat(sampleArray).containsExactly("Java" , "Kotlin" );
The Not Predicate Method 1 2 3 4 5 List<String> sampleList = Arrays.asList("Java" , "\n \n" , "Kotlin" , " " ); List withoutBlanks = sampleList.stream() .filter(Predicate.not(String::isBlank)) .collect(Collectors.toList()); assertThat(withoutBlanks).containsExactly("Java" , "Kotlin" );
Lamda表达式中的本地变量语法 1 2 3 4 5 List<String> sampleList = Arrays.asList("Java" , "Kotlin" ); String resultString = sampleList.stream() .map((@Nonnull var x) -> x.toUpperCase()) .collect(Collectors.joining(", " )); assertThat(resultString).isEqualTo("JAVA, KOTLIN" );
HTTP Client 新的HTTP API全面提升了性能并且将HTTP的支持从HTTP/1.1提升到了HTTP/2
1 2 3 4 5 6 7 8 9 10 HttpClient httpClient = HttpClient.newBuilder() .version(HttpClient.Version.HTTP_2) .connectTimeout(Duration.ofSeconds(20 )) .build(); HttpRequest httpRequest = HttpRequest.newBuilder() .GET() .uri(URI.create("http://localhost:" + port)) .build(); HttpResponse httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());assertThat(httpResponse.body()).isEqualTo("Hello from the server!" );
可直接运行java文件 1 2 $ java HelloWorld.java Hello Java 11 !
Dynamic Class-File Constants 个人理解是动态常量池
新增一个消极的垃圾收集器 Epsilon 不会去进行GC,一般不用于正式的java项目,可用于测试和生命周期极短的项目。 启用方式:
1 -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC
飞行记录器 Java Flight Recorder (JFR) 现在在OpenJDK开源,使用如下命令运行监控
1 -XX:StartFlightRecording=duration=120s,settings=profile,filename=java-demo-app.jfr
会生成一个JFR文件,该文件要使用JDK Mission Control (JMC)进行分析。
Java12 File增加文件对比方法 可以通过mismatch(Path path, Path path2) 方法来比较两个文件的内容差异
1 2 3 4 5 6 7 8 9 10 @Test public void givenDifferentFiles_thenShouldFindMismatch () { Path filePath3 = Files.createTempFile("file3" , ".txt" ); Path filePath4 = Files.createTempFile("file4" , ".txt" ); Files.writeString(filePath3, "Java 12 Article" ); Files.writeString(filePath4, "Java 12 Tutorial" ); long mismatch = Files.mismatch(filePath3, filePath4); assertEquals(8 , mismatch); }
Collector新增teeing方法 这是一个数学方法,典型用法是第一个参数得出总数,第二个参数计算个数,第三个参数将取到前两个参数的值进行平均数计算。
1 2 3 4 5 6 7 8 9 10 Collector<T, ?, R> teeing(Collector<? super T, ?, R1> downstream1, Collector<? super T, ?, R2> downstream2, BiFunction<? super R1, ? super R2, R> merger) @Test public void givenSetOfNumbers_thenCalculateAverage () { double mean = Stream.of(1 , 2 , 3 , 4 , 5 ) .collect(Collectors.teeing(Collectors.summingDouble(i -> i), Collectors.counting(), (sum, count) -> sum / count)); assertEquals(3.0 , mean); }
数字格式化 可以将数字进行格式化,按照某种语言习惯进行转换,比如1000在英语中可以转为1k。
1 2 3 4 5 6 7 8 9 10 11 12 13 @Test public void givenNumber_thenCompactValues () { NumberFormat likesShort = NumberFormat.getCompactNumberInstance(new Locale ("en" , "US" ), NumberFormat.Style.SHORT); likesShort.setMaximumFractionDigits(2 ); assertEquals("2.59K" , likesShort.format(2592 )); NumberFormat likesLong = NumberFormat.getCompactNumberInstance(new Locale ("en" , "US" ), NumberFormat.Style.LONG); likesLong.setMaximumFractionDigits(2 ); assertEquals("2.59 thousand" , likesLong.format(2592 )); }
预览新特性 可以输入如下参数开启新特性的使用
1 javac -Xlint:preview --enable-preview -source 12 src/main/java/File.java
Switch 语法增强 以前的switch写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();String typeOfDay = "" ;switch (dayOfWeek) { case MONDAY: case TUESDAY: case WEDNESDAY: case THURSDAY: case FRIDAY: typeOfDay = "Working Day" ; break ; case SATURDAY: case SUNDAY: typeOfDay = "Day Off" ; }
现在的switch语法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 typeOfDay = switch (dayOfWeek) { case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "Working Day" ; case SATURDAY, SUNDAY -> "Day Off" ; } switch (dayOfWeek) { case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> System.out.println("Working Day" ); case SATURDAY, SUNDAY -> System.out.println("Day Off" ); } case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> { System.out.println("Working Day" ) }
instanceof的类型匹配 以前在instanceof中进行类型判断和使用需要像这样
1 2 3 4 5 Object obj = "Hello World!" ;if (obj instanceof String) { String s = (String) obj; int length = s.length(); }
现在
1 2 3 if (obj instanceof String s) { int length = s.length(); }
JVM的修改 Shenandoah 一个致力于暂停时间短的垃圾收集器 Microbenchmark Suite 微基准套件 Java12介绍了一组针对Java源码的约100个的微基准测试套件,这些套件可以测试Jvm的性能并帮助开发者在Jvm上进行开发。
CDS 文档变为默认功能 CDS用于减少JVM启动时间,在Java12中成为默认开启的功能,通过如下命令进行关闭
1 java -Xshare:off HelloWorld.java
Java13 新特性预览,需要手动开启 1 javac -Xlint:preview --enable-preview -source 12 src/main/java/File.java
Switch表达式增强,新增yield语法用于返回值 用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Test @SuppressWarnings("preview") public void whenSwitchingOnOperationSquareMe_thenWillReturnSquare () { var me = 4 ; var operation = "squareMe" ; var result = switch (operation) { case "doubleMe" -> { yield me * 2 ; } case "squareMe" -> { yield me * me; } default -> me; }; assertEquals(16 , result); }
多行文本块 现在可以更方便的对String进行多行文本的赋值,比如 JSON, XML, HTML 等文本。
1 2 3 4 5 6 7 8 9 10 11 12 13 String JSON_STRING = "{\r\n" + "\"name\" : \"Baeldung\",\r\n" + "\"website\" : \"https://www.%s.com/\"\r\n" + "}" ; String TEXT_BLOCK_JSON = """ { "name" : "Baeldung", "website" : "https://www.%s.com/" } """ ;assertThat(TEXT_BLOCK_JSON.contains("Baeldung" )).isTrue(); assertThat(TEXT_BLOCK_JSON.indexOf("www" )).isGreaterThan(0 ); assertThat(TEXT_BLOCK_JSON.length()).isGreaterThan(0 );
动态CDS归档 CDS从java10发布,到java12成为默认开启的功能。然而该功能的使用略显繁杂。开发者需要先试运行他们的程序以生成class列表,然后再将其转为归档文件。这之后,这些归档文件才能在虚拟机之间进行数据共享。 在Java13中,简化了归档文件的生成步骤。现在我们可以在程序创建的时候就生成共享归档文件。减少了试运行的那一步。我们需要在启动参数中加入-XX:ArchiveClassesAtExit并指定归档文件名来开启该功能。
1 java -XX:ArchiveClassesAtExit=<archive filename> -cp <app jar> AppName
然后我们就可以在运行相同应用的时候直接使用共享文档
1 java -XX:SharedArchiveFile=<archive filename> -cp <app jar> AppName
ZGC释放未使用内存 在该版本之前,ZGC虽然可以做到STW时间始终低于10ms,但是不像其他垃圾收集器会将未使用的堆内存释放。现在Java13拥有了该功能,并且该功能是默认开启的。并且ZGC现在将最大支持内存从4TB增加到了16TB。
Socket API重构 Socket API发布以来,20年未曾更改,在Java13终于进行了调整。
其他更改
java.nio – method FileSystems.newFileSystem(Path, Map<String, ?>) added
java.time – new official Japanese era name added
javax.crypto – support for MS Cryptography Next Generation (CNG)
javax.security – property jdk.sasl.disabledMechanisms added to disable SASL mechanisms
javax.xml.crypto – new String constants introduced to represent Canonical XML 1.1 URIs
javax.xml.parsers – new methods added to instantiate DOM and SAX factories with namespaces support
Unicode support upgraded to version 12.1
Support added for Kerberos principal name canonicalization and cross-realm referrals
Java14 Switch新语法和文本块语法实装 1 2 3 4 5 boolean isTodayHoliday = switch (day) { case "MONDAY" , "TUESDAY" , "WEDNESDAY" , "THURSDAY" , "FRIDAY" -> false ; case "SATURDAY" , "SUNDAY" -> true ; default -> throw new IllegalArgumentException ("What's a " + day); };
1 2 3 String multiline = """ A quick brown fox jumps over a lazy dog; \ the lazy dog howls loudly.""" ;
Records 关键字(预览特性) 可以通过定一个Records类,来减少类中多余的模版代码,Records相当于自动帮你生成了get,equals, hashCode, 构造方法和toString方法。可以看成简化版的lombok。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public record User (int id, String password) { };private User user1 = new User (0 , "UserOne" );@Test public void givenRecord_whenObjInitialized_thenValuesCanBeFetchedWithGetters () { assertEquals(0 , user1.id()); assertEquals("UserOne" , user1.password()); } @Test public void whenRecord_thenEqualsImplemented () { User user2 = user1; assertTrue(user1, user2); } @Test public void whenRecord_thenToStringImplemented () { assertTrue(user1.toString().contains("UserOne" )); }
NPE 报错增强,现在会准确提示报错在哪一行以及哪一个对象为空。 1 java.lang.NullPointerException: Cannot store to int array because "a" is null
孵化特性,这些特性放在模块jdk.incubator.中 访问外部内存的API 现在允许java程序直接访问外部内存,比如计算机本地内存。
打包工具 现在可以通过jlink工具打包,生成在windows中exe文件或者macos中的dmg文件,以实现更方便的双击运行。
ZGC现在可以在Windows和MacOS上使用-实验特性 为G1 增加 NUMA 内存收集机制 JFR 事件流,增强了JFR的监控能力,现在可以通过消费者的方式直接获取监控结果 Java15 records关键字实装 sealed,non-sealed,permits关键字 这些关键字提供了更精细的类之间的访问控制。
1 2 3 4 5 public abstract sealed class Person permits Employee, Manager { }
以上语法的效果是Person类将只能被Employee, Manager类继承。 注意:继承sealed类的子类必须用sealed, non-sealed, 或 final进行修饰,这样可以保证类层次有限,同时被JVM正确识别。
1 2 3 4 5 public final class Employee extends Person {} public non-sealed class Manager extends Person {}
隐藏类 大部分程序员在日常开发中用不到隐藏类,JVM开发者会发现它的好处。隐藏类的目的是在程序运行时创建无法被发现的类。这种类无法被引用,被反射,同时具有较短的生命周期。
模式匹配中的类型检查 该特性在java14中已经介绍过,代码如下。
1 2 3 4 5 if (person instanceof Employee) { Employee employee = (Employee) person; Date hireDate = employee.getHireDate(); }
在java15中该特性得到增强,在类型判断成功后,jvm会自动将该变量赋值为对应类型进行后续操作,如下person对象自动赋值到了employee对象中,可以进行后续的变量操作:
1 2 3 if (person instanceof Employee employee && employee.getYearsOfService() > 5 ) { }
外部内存API JAVA14中已经介绍过访问外部内存的API,在java15中增加若干功能。
A new VarHandle API, to customize memory access var handles
Support for parallel processing of a memory segment using the Spliterator interface
Enhanced support for mapped memory segments
Ability to manipulate and dereference addresses coming from things like native calls
ZGC和Shenandoah成为可进行选择配置的垃圾收集器,G1依然是默认的垃圾收集器 Java15中移除偏向锁,RMI,Solaris/SPARC Java16 动态代理现在可以反射接口的默认方法 1 2 3 4 5 6 7 8 9 10 Object proxy = Proxy.newProxyInstance(getSystemClassLoader(), new Class <?>[] { HelloWorld.class }, (prox, method, args) -> { if (method.isDefault()) { return InvocationHandler.invokeDefault(prox, method, args); } } ); Method method = proxy.getClass().getMethod("hello" );assertThat(method.invoke(proxy)).isEqualTo("world" );
日期格式的支持 通过一个标识符“B”来进行日期格式的转换。更多详细用法在此
1 2 3 LocalTime date = LocalTime.parse("15:25:08.690791" );DateTimeFormatter formatter = DateTimeFormatter.ofPattern("h B" );assertThat(date.format(formatter)).isEqualTo("3 in the afternoon" );
Stream 类增加toList方法 1 2 3 List<String> integersAsString = Arrays.asList("1" , "2" , "3" ); List<Integer> ints = integersAsString.stream().map(Integer::parseInt).collect(Collectors.toList()); List<Integer> intsEquivalent = integersAsString.stream().map(Integer::parseInt).toList();
Vector API Incubator Records关键字功能增强 instanceof模式匹配和Sealed关键字实装 Java17 浮点型计算将保证在不同的平台保持严格相同的结果 伪随机数生成器增强 java17为伪随机数生成器新增了几个接口和实现。将更容易使用不同的算法并更好的支持stream为基础的编程。
1 2 3 4 5 6 7 public IntStream getPseudoInts (String algorithm, int streamSize) { return RandomGeneratorFactory.of(algorithm) .create() .ints(streamSize, 0 ,100 ); }
Applet API 被移除 对JDK的内部类更严格的封装,比如sun.misc.Unsafe,将保证开发者无法访问到此类方法 switch中的模式匹配 之前已经介绍过的instanceOf中的模式匹配,该功能进一步增强了switch的语法能力,如下,obj的类型转换直接发生在case关键字中,减少了很多冗余代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 static record Human (String name, int age, String profession) {}public String checkObject (Object obj) { return switch (obj) { case Human h -> "Name: %s, age: %s and profession: %s" .formatted(h.name(), h.age(), h.profession()); case Circle c -> "This is a circle" ; case Shape s -> "It is just a shape" ; case null -> "It is null" ; default -> "It is an object" ; }; } public String checkShape (Shape shape) { return switch (shape) { case Triangle t && (t.getNumberOfSides() != 3 ) -> "This is a weird triangle" ; case Circle c && (c.getNumberOfSides() != 0 ) -> "This is a weird circle" ; default -> "Just a normal shape" ; }; }
RMI 功能被移除 sealed关键字 移除Ahead-Of-Time (AOT) 编译 和 Just-In-Time (JIT) 编译方式 在JDK9和10中被介绍的特性,在经历了多个版本迭代后,其维护成本过高,因此被移除。
移除 Security Manager 外部方法和外部内存的API(孵化器特性) 外部方法和的API允许开发者访问JVM虚拟机之外的代码,外部内存的API可以管理堆外内存。其设计目的是为了取代JNI API,并提示其安全性和性能。 调用C语言库:
1 2 3 4 5 6 7 8 private static final SymbolLookup libLookup;static { var path = JEP412.class.getResource("/print_name.so" ).getPath(); System.load(path); libLookup = SymbolLookup.loaderLookup(); }
Vector API(二次孵化) Vector API 处理 SIMD(单指令,多数据)类型的操作,这意味着并行执行的各种指令集。 它利用支持向量指令的专用 CPU 硬件,并允许执行流水线等指令。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public void newVectorComputation (float [] a, float [] b, float [] c) { for (var i = 0 ; i < a.length; i += SPECIES.length()) { var m = SPECIES.indexInRange(i, a.length); var va = FloatVector.fromArray(SPECIES, a, i, m); var vb = FloatVector.fromArray(SPECIES, b, i, m); var vc = va.mul(vb); vc.intoArray(c, i, m); } } public void commonVectorComputation (float [] a, float [] b, float [] c) { for (var i = 0 ; i < a.length; i ++) { c[i] = a[i] * b[i]; } }
反序列化过滤器 用于验证从不可信任来源发送来的序列化数据,这个过程发生在jvm虚拟机中,提升了安全性和健壮性。
新增一个半年周期-特性的模块 这个模块帮助开发者减轻开发一个新功能的压力,一个功能首先在该模块中进行试用,之后再发布到LTS模块中。
新增LTS模块
参考资料https://javaguide.cn/java/new-features/java8-common-new-features.html https://javaguide.cn/java/new-features/java9.html https://javaguide.cn/java/new-features/java10.html https://javaguide.cn/java/new-features/java11.html https://javaguide.cn/java/new-features/java12-13.html https://javaguide.cn/java/new-features/java14-15.html https://javaguide.cn/java/new-features/java16.html https://www.baeldung.com/java-8-new-features https://www.baeldung.com/new-java-9 https://www.baeldung.com/java-10-overview https://www.baeldung.com/java-11-new-features https://www.baeldung.com/java-12-new-features https://www.baeldung.com/java-13-new-features https://www.baeldung.com/java-14-new-features https://www.baeldung.com/java-15-new https://www.baeldung.com/java-16-new-features https://www.baeldung.com/java-17-new-features