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 ...
随机推荐
- 【原创】渗透神器CoblatStrike实践(1)
渗透神器CoblatStrike实践(1) 前言 正常的渗透测试: 寻找漏洞,利用漏洞,拿到一定的权限 后渗透(CS为代表的): 提升权限,内网渗透,权限维持 工具地址(非官方取到后门多,建议 ...
- cuda在ubuntu的安装使用分享
前言 之前给大家分享过opencv在jetson nano 2gb和ubuntu设备中使用并且展示了一些人脸识别等的小demo.但是对于图像处理,使用gpu加速是很常见 .(以下概念介绍内容来自百科和 ...
- wsl2环境搭建
序言 我电脑配置不高,开虚拟机跑linux总觉得太卡.最近才了解到windows早就上了wsl2--一款较为轻量的虚拟机软件.所以本篇博客偏笔记向,存粹记录以便多次使用. 环境 宿主机windows1 ...
- Jetpack架构组件学习(3)——Activity Results API使用
原文地址:Jetpack架构组件学习(3)--Activity Results API使用 - Stars-One的杂货小窝 技术与时俱进,页面跳转传值一直使用的是startActivityForRe ...
- Camunda如何适配国产数据库达梦
前言 camunda流程引擎官方支持的数据库有:MySQL .MariaDB .Oracle .DB2 .PostgreSQL .SQL Server.H2.对于其他类型的数据库如何支持,尤其是国产数 ...
- ShardingSphere 异构迁移最佳实践:将3.5亿量级的顾客系统 RTO 减少60倍
Apache ShardingSphere 助力当当 3.5 亿用户量级顾客系统重构,由 PHP+SQL Server 技术栈无缝转型为 Java+ShardingSphere+MySQL,性能.可用 ...
- Conda 虚拟环境移植
这时候你应该位于具有待移植的环境的服务器: 1 进入你要移植的环境 conda activate your_env 2 导出当前conda环境到某个文件(文件名字可以自定义) conda env ex ...
- 论文解读(KP-GNN)《How Powerful are K-hop Message Passing Graph Neural Networks》
论文信息 论文标题:How Powerful are K-hop Message Passing Graph Neural Networks论文作者:Jiarui Feng, Yixin Chen, ...
- Vue2自定义插件的写法-Vue.use()
最近在用vue2完善一个项目,顺便温习下vue2的基础知识点! 有些知识点恰好没用到时间一长就会淡忘,这样对自己是一种损失. 定义一个对象 对象里可以有任何内容 但install的函数是必不可少的,因 ...
- java基础知识点梳理
前言 在别人追问我以下几个问题,自己在问题回答上不够全面和准确,对此自己把专门针对这几个问题进行总结! java相关问题 1.Java中构造方法跟普通方法的区别? 构造方法与普通方法的调用时机不同. ...