Java SE 10 新增特性
Java SE 10 新增特性
作者:Grey
原文地址:Java SE 10 新增特性
源码
镜像仓库: GitCode:java_new_features
类型推断
无需定义变量类型,通过var关键字结合初始化的值,可以推测出变量类型
package git.snippets.jdk10;
/**
* 类型推断
*
* @author <a href="mailto:410486047@qq.com">Grey</a>
* @date 2022/8/17
* @since 10
*/
public class TypeRefEnhance {
public static void main(String[] args) {
var a = 2; // a表示int
System.out.println(a);
var b = "hello"; // b 表示String
System.out.println(b);
var date = new java.util.Date();
System.out.println(date);
var obj = new Customer("Grey"); // 自定义对象
System.out.println(obj);
var sum = new TypeRefEnhance().add(1, 23);
System.out.println(sum);
var var = 3;
System.out.println(var);
}
public int add(int a, int b) {
return a + b;
}
static class Customer {
String name;
public Customer(String n) {
name = n;
}
@Override
public String toString() {
return "Customer{" +
"name=" + name +
'}';
}
}
}
var 看似好用,但是请谨慎使用,比如
var x = someFunction()
是因为如果不追踪someFunction()方法的返回类型,读者就不可能知道x的类型。多年来,人们对动态类型语言提出了类似的抱怨。
所以,记住我们的目标是编写可读的代码。
在Java中,var是一个特殊的新类型,你仍然可以在你的代码的其他地方使用var,比如作为一个变量或类名。这使得Java能够与Java 10之前的代码保持向后兼容,所以如下定义是没问题的
var var = 3;
不可变集合 API
如下代码
package git.snippets.jdk10;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 集合API增强
*
* @author <a href="mailto:410486047@qq.com">Grey</a>
* @date 2021/11/29
* @since 10
*/
public class CollectionEnhance {
public static void main(String[] args) {
var vegetables = new ArrayList<>(List.of("Brocolli", "Celery", "Carrot"));
var unmodifiable = Collections.unmodifiableList(vegetables);
vegetables.set(0, "Radish");
var v = unmodifiable.get(0);
// 以下这行会报错
unmodifiable.set(0, "XXX");
System.out.println(v);
System.out.println(unmodifiable);
}
}
根据Java 10中Collections的最新定义,unmodifiableList返回一个不可修改的视图集合。所以unmodifiable.set(0, "XXX");会直接报错
Exception in thread "main" java.lang.UnsupportedOperationException
at java.base/java.util.Collections$UnmodifiableList.set(Collections.java:1308)
at git.snippets.jdk10.CollectionEnhance.main(CollectionEnhance.java:22)
Java 10增加了两个新的API来实现这一点,也就是说,创建完全不能修改的集合。
第一个API是copyOf,用来制作集合的不可修改的副本。
static void copyOfTest() {
var list = List.of("a", "b", "c");
var copyList = List.copyOf(list);
list.add("d");
// 由于copyList是副本, 所以copyList不会受到list的影响,打印出[a,b,c]
System.out.println(copyList);
System.out.println(list);
// 由于是不可变集合,所以这里会报错
copyList.add("d");
}
这与用Collections.unmodifiableList包装一个列表是不同的。 copyOf是创建副本(源集合改变不会影响副本集合),而Collections.unmodifiableList是生成视图(源集合改变会影响视图)。
第二个API为Stream包中的Collectors类增加的三个新方法。现在你可以使用toUnmodifiableList、toUnmodifiableSet和toUnmodifiableMap在生成一个不可修改的集合。代码如下
static void unmodifiedTest() {
List<String> list = List.of("b", "a", "b", "c");
List<String> c1 = list.stream().collect(Collectors.toUnmodifiableList());
System.out.println(c1);
// 会报错
// c1.add("c");
// System.out.println(c1);
Set<String> c2 = list.stream().collect(Collectors.toUnmodifiableSet());
System.out.println(c2);
// 会报错
// c2.add("a");
// System.out.println(c2);
// 会报错
// c2.add("e");
// System.out.println(c2);
}
注意,虽然这些方法的名字可能会让你想起Collections.unmodifiableList等,但这些新方法产生的是真正的不可修改的列表,而Collections.unmodifiableList则返回一个不可修改的视图。
Unicode 语言标签扩展
Java SE 10实现了最新的LDML 规范中指定的更多的扩展。
主要增加了下面几个扩展方法。
java.time.temporal.WeekFields::of
java.util.Calendar::{getFirstDayOfWeek,getMinimalDaysInWeek}
java.util.Currency::getInstance
java.util.Locale::getDisplayName
java.util.spi.LocaleNameProvider
java.text.DateFormat::get*Instance
java.text.DateFormatSymbols::getInstance
java.text.DecimalFormatSymbols::getInstance
java.text.NumberFormat::get*Instance
java.time.format.DateTimeFormatter::localizedBy
java.time.format.DateTimeFormatterBuilder::getLocalizedDateTimePattern
java.time.format.DecimalStyle::of
尝试一下。
package git.snippets.jdk10;
import java.util.Calendar;
import java.util.Currency;
import java.util.Locale;
/**
* unicode扩展
* @since 10
*/
public class UnicodeTest {
public static void main(String[] args) {
Currency chinaCurrency = Currency.getInstance(Locale.CHINA);
Currency usCurrency = Currency.getInstance(Locale.US);
System.out.println("本地货币:" + chinaCurrency);
System.out.println("US.货币:" + usCurrency);
String displayName = Locale.getDefault().getDisplayName();
String displayLanguage = Locale.getDefault().getDisplayLanguage();
String displayCountry = Locale.getDefault().getDisplayCountry();
System.out.println("本地名称:" + displayName);
System.out.println("本地语言:" + displayLanguage);
System.out.println("本地国家:" + displayCountry);
int firstDayOfWeek = Calendar.getInstance().getFirstDayOfWeek();
System.out.println("本地每周第一天:" + firstDayOfWeek);
}
}
输出结果。
本地货币:CNY
US.货币:USD
本地名称:中文 (中国)
本地语言:中文
本地国家:中国
本地每周第一天:1
G1 性能增强
早在 Java 9 时就已经引入了 G1 垃圾收集器,G1 的优点很多。而在 Java 10 中还是做了小小调整,当 G1 的并发收集线程不能快速的完成全 GC 时,就会自动切换到并行收集,这可以减少在最坏情况下的 GC 速度。
类数据共享
Java SE 5引入了类数据共享(CDS),以改善小型Java应用程序的启动时间。
当JVM第一次启动时,由引导类加载器加载的任何东西都被序列化并存储在磁盘上的一个文件中,可以在JVM的未来启动中重新加载。这意味着JVM的多个实例共享类元数据,因此它不必每次都加载它们。
共享数据缓存意味着小型应用程序的启动时间有了很大的改善,因为在这种情况下,核心类的相对大小要大于应用程序本身。
Java SE 10将此扩展到包括系统类加载器和平台类加载器。为了利用这一点,你只需要添加以下参数
-XX:+UseAppCDS
Java SE 10还允许你把你自己的应用程序特定的类也存储到类-数据共享缓存中,可能会减少你的启动时间。
基本上,这是一个三步走的过程。第一步是创建应该被归档的类的列表,用适当的标志启动你的应用程序,并指出你希望列表被存储的位置。
java -Xshare:off -XX:+UseAppCDS -XX:DumpLoadedClassList=myapp.lst \
-cp $CLASSPATH $MAIN_CLASS
然后,用这个清单,你将创建一个CDS档案
java -Xshare:dump -XX:+UseAppCDS -XX:SharedClassListFile=myapp.lst \
-XX:SharedArchiveFile=myapp.jsa \
-cp $CLASSPATH
最后,运行你的应用程序,使用该存档
java -Xshare:on -XX:+UseAppCDS -XX:SharedArchiveFile=hello.jsa \
-cp $CLASSPATH $MAIN_CLASS
更多内容参考:JEP 310: Application Class-Data Sharing
新的即时编译器Graal
即时编译器(JIT)是Java的一部分,它在运行时将Java字节码转换为机器代码。最初的JIT编译器是用C++编写的,现在被认为相当难以修改。
Java SE 9引入了一个新的实验性接口,称为JVM编译器接口或JVMCI。新接口的设计使得用纯Java重写JIT编译器成为可能。Graal是由此产生的JIT编译器,完全用Java编写。
Graal目前是一个实验性的JIT编译器。在未来的Java版本之前,只有Linux/x64机器可以使用它。要启用Graal,请在启动应用程序时在命令行参数中添加这些标志。
-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler
更多内容参考:graalvm
Thread-Local Handshakes
在服务性操作中,比如为所有线程收集堆栈跟踪或执行垃圾回收,当JVM需要暂停一个线程时,它需要停止所有线程。有时,这些被称为 "stop-the-world"的暂停。这是由于JVM想要创建一个全局安全点,一旦JVM完成工作,所有应用线程都可以从这个安全点重新开始。
但在Java SE 10中,JVM可以将任意数量的线程放入安全点,并且线程在执行规定的 "握手"后可以继续运行。这导致JVM一次只需暂停一个线程,而以前则必须暂停所有线程。
更多参考:JEP 312: Thread-Local Handshakes
容器感知
JVM现在知道它何时在Docker容器内运行。这意味着应用程序现在拥有关于docker容器分配给内存、CPU和其他系统资源的准确信息。
以前,JVM会查询主机操作系统来获得这些信息,这就造成了一个问题。
例如,假设你想创建一个基于Java的docker镜像,其中运行的JVM被分配了容器所指定的25%的可用内存。在一个拥有2G内存的盒子上,运行一个配置为0.5G内存的容器,Java SE 9和更早的版本会错误地根据2G的数字而不是0.5G来计算Java进程的堆大小。
但是,现在,在Java SE 10中,JVM能够从容器控制组(cgroups)中查找这些信息。
有一些命令行选项可以指定Docker容器内的JVM如何分配内部内存。例如,为了将内存堆设置为容器组的大小,并限制处理器的数量,你可以传入这些参数
-XX:+UseCGroupMemoryLimitForHeap -XX:ActiveProcessorCount=2
随着容器成为部署服务的标准方式,这意味着开发者现在有一种基于容器的方式来控制他们的Java应用如何使用资源。
指定替代的内存分配
通过允许用户指定替代的内存设备来分配堆,Java正朝着更加异构的内存系统发展。
一个直接的用例是能够在非易失性DIMM(NVDIMM)模块上分配堆,这在大数据应用中是常用的。
另一个用例是在同一台机器上运行许多JVM进程。在这种情况下,让那些需要较低读取延迟的进程映射到DRAM上,其余的进程映射到NVDIMM上。
可以在你的启动参数中添加如下标志
-XX:AllocateHeapAt=<path>
这里的path通常是一个内存映射的目录。
更多
参考资料
Java 10 Features (with Examples)
Java 10 Features and Enhancements
JEP 310: Application Class-Data Sharing
Java SE 10 新增特性的更多相关文章
- Java SE 8 新增特性
Java SE 8 新增特性 作者:Grey 原文地址: Java SE 8 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new_ ...
- Java SE 9 新增特性
Java SE 9 新增特性 作者:Grey 原文地址: Java SE 9 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new_ ...
- Java SE 11 新增特性
Java SE 11 新增特性 作者:Grey 原文地址:Java SE 11 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...
- Java SE 12 新增特性
Java SE 12 新增特性 作者:Grey 原文地址:Java SE 12 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...
- Java SE 13 新增特性
Java SE 13 新增特性 作者:Grey 原文地址:Java SE 13 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...
- Java SE 17 新增特性
Java SE 17 新增特性 作者:Grey 原文地址:Java SE 17 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...
- Java SE 19 新增特性
Java SE 19 新增特性 作者:Grey 原文地址: 博客园:Java SE 19 新增特性 CSDN:Java SE 19 新增特性 源码 源仓库: Github:java_new_featu ...
- Java SE 14 新增特性
Java SE 14 新增特性 作者:Grey 原文地址:Java SE 14 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...
- Java SE 15 新增特性
Java SE 15 新增特性 作者:Grey 原文地址:Java SE 15 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...
随机推荐
- 『忘了再学』Shell基础 — 22、主要的环境变量配置文件说明
目录 1.source命令 2.Linux系统中环境变量配置文件 (1)登录时生效的环境变量配置文件 (2)/etc/profile环境变量配置文件 (3)/etc/profile.d/*.sh环境变 ...
- go-zero 微服务实战系列(一、开篇)
前言 在社区中经常看到有人问有没有基于 go-zero 的比较完整的项目参考,该类问题本质上是想知道基于 go-zero 的项目的最佳实践.完整的项目应该是一个完整的产品功能,包含产品需求.架构设计. ...
- 李呈祥:bilibili在湖仓一体查询加速上的实践与探索
导读: 本文主要介绍哔哩哔哩在数据湖与数据仓库一体架构下,探索查询加速以及索引增强的一些实践.主要内容包括: 什么是湖仓一体架构 哔哩哔哩目前的湖仓一体架构 湖仓一体架构下,数据的排序组织优化 湖仓一 ...
- JVM 输出 GC 日志导致 JVM 卡住,我 TM 人傻了
本系列是 我TM人傻了 系列第七期[捂脸],往期精彩回顾: 升级到Spring 5.3.x之后,GC次数急剧增加,我TM人傻了:https://zhuanlan.zhihu.com/p/3970425 ...
- redis相关知识点
redis 的相关知识点 启动 启动代码 redis-cli -a 密码 通用命令 expire: 设置有效期 expire name 10 key key * 相关数据类型 String set:添 ...
- 飞鱼CRM
直接放干货吧,今日头条飞鱼CRM的PHP调用方法,点我跳转. 很简单的两个方法,加密时重要的是有一个空格,必须要有,这个也是坑了我很长时间的一个坑. 接下来具体说一下飞鱼CRM系统接口加密的方法. & ...
- Linux系列之查找命令
前言 Linux 有四个常用的查找命令:locate.whereis.which 和 find.本文介绍它们的区别和简单用法. locate命令 这个命令将检查你的整个文件系统,并找到该关键词的每一次 ...
- ClickHouse(04)如何搭建ClickHouse集群
ClickHouse集群的搭建和部署和单机的部署是类似的,主要在于配置的不一致,如果需要了解ClickHouse单机的安装设部署,可以看看这篇文章,ClickHouse(03)ClickHouse怎么 ...
- 快来体验快速通道,netty中epoll传输协议详解
目录 简介 epoll的详细使用 EpollEventLoopGroup EpollEventLoop EpollServerSocketChannel EpollSocketChannel 总结 简 ...
- APISpace万券齐发,API采购大放价
Eolink APISpace 是 Eolink 旗下专业的API 数据交易平台,上面拥有海量的API,开发者可以根据需求自由选择. 环境天气 全国天气预报,支持全国以及全球多个城市的天气查询,包含国 ...