随着Java的快速更新,为了应对新技术创新的速度,在每六个月的发布周期内,会推出新的许可证和长期支持模型。
为什么要从JDK 8升级到JDK 11?
- 下一个LTS版本(如果你拥有商业许可证)。
- Oracle不再提供JRE和Server JRE下载,因此自动更新不再可用。
- Oracle不再提供32位Windows下载。
- Java Applet、Java Web Start、Java Plugin和Java Control Panel在JDK中不再可用。请参见删除部署堆栈。
- JavaFX不再包含在JDK中。现在可以从https://openjfx.io/单独下载。
- JAXB和JAX-WS不再与JDK捆绑在一起。请参见删除Java EE和CORBA模块。
- 支持在G1上并行完整垃圾回收。
- 免费的应用程序类数据共享功能。
- 免费的低开销飞行记录仪和堆剖析器。
- 在替代内存设备上分配堆空间。
- 新的ZGC和Epsilon垃圾收集器。
- 传输层安全性(TLS)1.3。
- JShell。
- 支持“shebang”Java文件!#!/bin/java
- 库的弃用和删除
- API更新
长期支持: Open JDK和Oracle JDK都具有相同的功能。Open JDK是开源的,而Oracle JDK是Java专有许可证。在Java 10之前,可以免费使用Open JDK和Oracle JDK进行生产,但从Java 11开始,只能免费使用Open JDK进行生产,而不能使用Oracle JDK。有关LTS的几个重要点。
- 每年推出2个Java版本,直到2028年(Java 31)。
- 每3年推出一次长期支持版本。因此,在Java 8之后,下一个LTS是Java 11。
- 3年的支持承诺是最低的,而LTS仅适用于Oracle JDK。我们可以购买Java 11的支持超过3年。
- 所有Open JDK仅有6个月的支持,直到下一个重大版本。因此,要么购买LTS支持,要么每六个月切换版本。
Java 11/12的主要新功能
启动单文件源代码: 如果我要编写Java程序,我们遵循以下步骤。
public class HelloUniverse{
public static void main(String[] args) {
System.out.println("Hello Universe");
}
}Before Java 11:
Compile:$javac HelloUniverse.java
Run:$java HelloUniverse
O/p:Hello UniverseIn Java 11:
Run:$java HelloUniverse.java
O/p:Hello Universe
现在使用单个源,编译器将直接执行_.java_以输出,不会生成_.class_文件。
注意: 此功能仅限于单个源文件。
使用Java进行脚本编写: 使用shebang(“#!”),我们可以开发可执行的javascript并从命令行运行。
./listallfiles#!/usr/bin/java --source 11import java.nio.file.*;public class ListFiles {
public static void main (String ... args) throws Exception
{
Files.walk(Path.get(args[0]))
.forEaach(System.out::println);
}
}How to Run:
$chmod +x listallfiles
$./listallfiles . // Here "." is a current directory.
弃用和删除
- 从JDK中删除了Java EE和CORBA模块。
- 删除了Thread.destroy()和Thread.stop()方法。
- 删除了Applets和Java Web Start。
语言和库的改进
- HttpClient API: 在Java 11中,HTTP Client已替换为java.net.HttpURLConnection。它可以用于请求网络上的HTTP资源。它支持_HTTP/1.1_和_HTTP/2_,同时支持同步和异步编程模型,将请求和响应体处理为反应流,并遵循熟悉的构建器模式。
示例:获取响应正文并将其打印为字符串的GET请求
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://openjdk.java.net/"))
.build();
client.sendAsync(request, BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println)
.join();
- 库的改进: 在String库中添加了一些方法,例如“repeat”,isBlank(),strip,lines。
- Lambda表达式的本地变量语法: 在lambda中使用var
Java 11之前: 我们在lambda表达式中使用显式类型。
// Any local variable declaration
List<String> list = new ArrayList<String>();
Stream<String> stream = getStream()// For Lambda Expression.
(String a, String b) -> a.concat(b)
Java 11: 可以在lambda表达式中使用var,而不使用显式类型。
// Any local variable declaration.
var list = new ArrayList<String>();
var stream = getStream();// For Lambda Expression.
(var a, var b) -> a.concat(b)
- 基于嵌套的访问控制:_nests_允许将嵌套类编译为属于同一封闭类的不同类文件。然后,它们可以访问彼此的私有类,而无需使用_synthetic/bridge_方法。
性能和安全改进
- 垃圾回收器改进:Java为你管理堆内存。你在虚拟机(JVM)中运行应用程序。当需要时,JVM会为你分配空间,并在不再需要时释放它。垃圾回收器(GC)是为你执行此操作的组件。回收内存涉及具有对性能产生影响的垃圾收集“周期”。
- G1 GC是Java 9以来的默认垃圾收集器。在Java 11中,增量改进GC比以前提高了60%的性能。
- Java 11引入了Epsilon和Z垃圾收集器(ZGC),我们可以选择更适合我们应用程序的GC。
- 安全性改进:TLS 1.3:现在在JDK中实现了TLS 1.3。删除了旧的遗留算法,并且除了消息加密之外,所有握手算法都被加密。
Java 12的变化
JDK 12提供了少量的新功能和API,其中开关表达式对开发人员最为有趣。 G1的用户无疑会欣赏性能改进。
API更新
- 在Stream API中使用Collectors.teeing():一种teeing收集器作为静态方法Collectors::teeing被公开。此收集器将其输入转发到两个其他收集器,然后使用函数将它们的结果合并。
teeing(Collector,Collector,BiFunction)
接受两个收集器和一个函数来合并它们的结果。每个传递到生成的收集器的元素都由下游收集器处理,然后使用指定的合并函数将它们的结果合并为最终结果。例如,在给定的员工列表中,如果我们想找到工资最高和最低的员工,我们可以使用teeing
收集器在一个语句中完成。
public static void main(String[] args) {
List<Employee> employeeList = Arrays.asList(
new Employee(1, "A", 100),
new Employee(2, "B", 200),
new Employee(3, "C", 300),
new Employee(4, "D", 400));
HashMap<String, Employee> result = employeeList.stream().collect(
Collectors.teeing(
Collectors.maxBy(Comparator.comparing(Employee::getSalary)),
Collectors.minBy(Comparator.comparing(Employee::getSalary)),
(e1, e2) -> {
HashMap<String, Employee> map = new HashMap();
map.put("MAX", e1.get());
map.put("MIN", e2.get());
return map;
}
));
System.out.println(result);
}
- **String API变更:**新增了
String.indent()
、String.transform()
和Files.mismatch(Path, Path)
。 - Switch表达式:Java 12增强了Switch表达式的模式匹配。我们不再需要为每个case块定义
break
语句,而是可以使用箭头语法。
旧的Switch表达式:
public String getTextViaBreak(int number) {
String result = switch (number) {
case 1:
case 2:
break "one or two";
case 3:
break "three";
case 4:
case 5:
case 6:
break "four or five or six";
default:
break "unknown";
};
return result;
}
新的Switch表达式:
public String getTextViaArrow(int number) {
String result = switch (number) {
case 1, 2 -> "one or two";
case 3 -> "three";
case 4, 5, 6 -> "four or five or six";
default -> "unknown";
};
return result;
}Note: Its preview feature and not going to run in your ide directly.
Follow below steps to run.
$javac --enable-preview --release 13 SwitchExpression.java
$ java --ennable-preview SwitchExpression
- JVM变更
- 低停顿时间垃圾收集器(实验性)
RedHat启动了Shenandoah垃圾收集器,以减少GC暂停时间。其思想是与正在运行的Java线程并发运行GC。
-
即时从G1返回未使用的已提交内存:从Java 12开始,在应用程序不活动期间,G1将检查Java堆内存并将其返回给操作系统。这是一种预防措施,以节省和使用空闲内存。
-
Java微基准测试: 是_Java微基准测试工具箱_的缩写。编写基准测试可测量较大应用程序的小部分的性能。
import org.openjdk.jmh.annotations.Benchmark;public class MyBenchmark {
@Benchmark
public void testMethod() {
// This is a demo/sample template for building your JMH benchmarks. Edit as needed.
// Put your benchmark code here. int a = 1;
int b = 2;
int sum = a + b;
}
}
- 默认CDS档案: 这增强了JDK构建过程,以在64位平台上使用默认类列表生成类数据共享(CDS)存档。目标是提高启动时间。从Java 12开始,默认情况下启用CDS。
结论: 自Java 8以来发生了许多变化:我们每6个月发布一次更新;许可、更新和支持已经改变;我们获取JDK的位置可能已经改变。当然,还有新的语言特性,包括进入Java 9的主要更改。但是现在,由于Java 11已经取代Java 8成为最新的LTS,而且主要的库、框架和构建工具已经采用了最新的Java版本,现在是将应用程序迁移到Java 11或12的好时机。
你可以在这里找到示例GitHub代码。
译自:https://medium.com/testvagrant/migrate-java-8-to-java-11-12-9ab082f335e8
评论(0)