JAVA8 之后的版本履历
静态方法引用
使用方式:Class::staticMethod
test.operate(1,?2,?Test::add);
对象的实例方法引用
使用方式:instance::method
test.operate(1,?2,?test::sub);
类的实例方法引用
使用方式:Class::method
test.test(Test::testM);
其实上面三种方法引用都好理解,最后类的实例方法引用,有两个条件:
首先要满足实例方法,而不是静态方法
Lambda 表达式的第一个参数会成为调用实例方法的对象
根据这两点我们看上面的例子,test 方法接受一个 TestInt 实例,用 Lambda 表达式表示就是 (Test t1, Test t2) -> res,而我们调用 test 方法时传入的方法引用是 Test::testM,其参数也是一个 Test 实例,最终 test.test(Test::testM) 的调用效果就是 t1.testM(t2)
2.1.3?接口默认方法和静态方法
Java 8 新增了接口的默认实现,通过 default 关键字表示。同时也可以提供静态默认方法。
public?interface?TestInterface?{
String?test();
//?接口默认方法
default?String?defaultTest()?{
return?"default";
}
static?String?staticTest()?{
return?"static";
}
}
2.1.4?重复注解
Java 8 支持了重复注解。在 Java 8 之前想实现重复注解,需要用一些方法来绕过限制。比如下面的代码。
@interface?Author?{
String?name();
}
@interface?Authors?{
Author[]?value();
}
@Authors({@Author(name="a"),?@Author(name?=?"b")})
class?Article?{
}
而在 Java 8 中,可以直接用下面的方式。
@Repeatable(Authors.class)
@interface?Author?{
String?name();
}
@interface?Authors?{
Author[]?value();
}
@Author(name?=?"a")
@Author(name?=?"b")
class?Article?{
}
在解析注解的时候,Java 8 也提供了新的 API。
AnnotatedElement.getAnnotationsByType(Class<T>)
2.1.5. 类型注解
Java 8 之前注解只能用在声明中,在 Java 8 中,注解可以使用在 任何地方。
@Author(name="a")
private?Object?name?=?"";
private?String?author?=?(@Author(name="a")String)?name;
2.1.6. 更好的类型推断
Java 8 对于类型推断做了改进。
比如在 Java 7 中下面的写法:
List<String>?stringList?=?new?ArrayList<>();
stringList.add("A");
stringList.addAll(Arrays.<String>asList());
在 Java 8 中改进后的写法,可以自动做类型推断。
List<String>?stringList?=?new?ArrayList<>();
stringList.add("A");
stringList.addAll(Arrays.asList());
2.1.7. Optional
Java 8 中新增了 Optional 类用来解决空指针异常。Optional 是一个可以保存 null 的容器对象。通过 isPresent() 方法检测值是否存在,通过 get() 方法返回对象。
除此之外,Optional 还提供了很多其他有用的方法,具体可以查看文档。下面是一些示例代码。
//?创建一个?String?类型的容器
Optional<String>?str?=?Optional.of("str");
//?值是否存在
boolean?pre?=?str.isPresent();
//?值如果存在就调用?println?方法,这里传入的是?println?的方法引用
str.ifPresent(System.out::println);
//?获取值
String?res?=?str.get();
//?传入空值
str?=?Optional.ofNullable(null);
//?如果值存在,返回值,否则返回传入的参数
res?=?str.orElse("aa");
str?=?Optional.of("str");
//?如果有值,对其调用映射函数得到返回值,对返回值进行?Optional?包装并返回
res?=?str.map(s?->?"aa"?+?s).get();
//?返回一个带有映射函数的?Optional?对象
res?=?str.flatMap(s?->?Optional.of(s?+?"bb")).flatMap(s?->?Optional.of(s?+?"cc")).get();
2.1.8. Stream
Java 8 中新增的 Stream 类提供了一种新的数据处理方式。这种方式将元素集合看做一种流,在管道中传输,经过一系列处理节点,最终输出结果。
关于 Stream 提供的具体方法,可以参照 API。下面是一些示例代码。
List<String>?list?=?Arrays.asList("maa",?"a",?"ab",?"c");
list.stream()
.filter(s?->?s.contains("a"))
.map(s?->?s?+?"aa")
.sorted()
.forEach(System.out::println);
System.out.println("####");
list.parallelStream().forEach(System.out::println);
List<Integer>?numbers?=?Arrays.asList(1,?2,?3,?4,?5,?6,?7,?8);
int?res?=?numbers.stream().map(i?->?i?+?1).mapToInt(i?->?i).summaryStatistics().getMax();
System.out.println(res);
2.1.9. 日期时间 API
Java 8 中新增了日期时间 API 用来加强对日期时间的处理,其中包括了 LocalDate,LocalTime,LocalDateTime,ZonedDateTime 等等,关于 API 可以参照官方文档以及这篇博客,写的很详细。
https://www.cnblogs.com/muscleape/p/9956754.html
下面是示例代码。
LocalDate?now?=?LocalDate.now();
System.out.println(now);
System.out.println(now.getYear());
System.out.println(now.getMonth());
System.out.println(now.getDayOfMonth());
LocalTime?localTime?=?LocalTime.now();
System.out.println(localTime);
LocalDateTime?localDateTime?=?now.atTime(localTime);
System.out.println(localDateTime);
2.1.10. Base64 支持
Java 8 标准库中提供了对 Base 64 编码的支持。具体 API 见可参照文档。下面是示例代码。
String?base64?=?Base64.getEncoder().encodeToString("aaa".getBytes());
System.out.println(base64);
byte[]?bytes?=?Base64.getDecoder().decode(base64);
System.out.println(new?String(bytes));
2.1.11. 并行数组 ParallelSort
Java 8 中提供了对数组的并行操作,包括 parallelSort 等等,具体可参照 API。
Arrays.parallelSort(new?int[]?{1,?2,?3,?4,?5});
2.1.12. 其他新特性
对并发的增强
在 java.util.concurrent.atomic 包中还增加了下面这些类:
DoubleAccumulator
DoubleAdder
LongAccumulator
LongAdder
提供了新的 Nashorn javascript 引擎
提供了 jjs,是一个给予 Nashorn 的命令行工具,可以用来执行 JavaScript 源码
提供了新的类依赖分析工具 jdeps
JVM 的新特性
JVM 内存永久区已经被 metaspace 替换(JEP 122)。JVM 参数 -XX:PermSize 和 –XX:MaxPermSize 被 XX:MetaSpaceSize 和 -XX:MaxMetaspaceSize 代替。
可以看到,Java 8 整体上的改进是很大的,最重要的是引入 Lambda 表达式,简化代码。
其他一些改进可参照:
https://www.oracle.com/technetwork/java/javase/8-whats-new-2157071.html
《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》开源 2 Java 9
参考资料
https://www.runoob.com/java/java9-new-features.html
https://www.twle.cn/c/yufei/java9/java9-basic-process-manage-api.html
https://docs.oracle.com/javase/9/whatsnew/toc.htm
2.2.1?Jigsaw 模块 Java 开源项目【ali1024.coding.net/public/P7/Java/git】 系统
在 Java 9 以前,打包和依赖都是基于 JAR 包进行的。JRE 中包含了 rt.jar,将近 63M,也就是说要运行一个简单的 Hello World,也需要依赖这么大的 jar 包。在 Java 9 中提出的模块化系统,对这点进行了改善。
关于模块化系统具体可以看看这篇文章。
https://zhuanlan.zhihu.com/p/24800180
2.2.2?JShell REPL
Java 9 提供了交互式解释器。有了 JShell 以后,Java 终于可以像 Python,Node.js 一样在 Shell 中运行一些代码并直接得出结果了。
2.2.3. 私有接口方法,接口中使用私有方法
Java 9 中可以在接口中定义私有方法。示例代码如下:
public?interface?TestInterface?{
String?test();
//?接口默认方法
default?String?defaultTest()?{
pmethod();
return?"default";
}
private?String?pmethod()?{
System.out.println("private?method?in?interface");
return?"private";
}
}
2.2.4. 集合不可变实例工厂方法
在以前,我们想要创建一个不可变的集合,需要先创建一个可变集合,然后使用 unmodifiableSet 创建不可变集合。代码如下:
Set<String>?set?=?new?HashSet<>();
set.add("A");
set.add("B");
set.add("C");
set?=?Collections.unmodifiableSet(set);
System.out.println(set);
Java 9 中提供了新的 API 用来创建不可变集合。
List<String>?list?=?List.of("A",?"B",?"C");
Set<String>?set?=?Set.of("A",?"B",?"C");
Map<String,?String>?map?=?Map.of("KA",?"VA",?"KB",?"VB");
2.2.5. 改进 try-with-resources
Java 9 中不需要在 try 中额外定义一个变量。Java 9 之前需要这样使用 try-with-resources:
InputStream?inputStream?=?new?StringBufferInputStream("a");
try?(InputStream?in?=?inputStream)?{
in.read();
}?catch?(IOException?e)?{
e.printStackTrace();
}
在 Java 9 中可以直接使用 inputStream 变量,不需要再额外定义新的变量了。
InputStream?inputStream?=?new?StringBufferInputStream("a");
try?(inputStream)?{
inputStream.read();
}?catch?(IOException?e)?{
e.printStackTrace();
}
2.2.6. 多版本兼容 jar 包
Java 9 中支持在同一个 JAR 中维护不同版本的 Java 类和资源。
2.2.7. 增强了 Stream,Optional,Process API
2.2.8. 新增 HTTP2 Client
2.2.9. 增强 Javadoc,增加了 HTML 5 文档的输出,并且增加了搜索功能
2.2.10. 增强 @Deprecated
对 Deprecated 新增了 since 和 forRemoval 属性
2.2.11. 增强了钻石操作符 "<>",可以在 匿名内部类中使用了。
在 Java 9 之前,内部匿名类需要指定泛型类型,如下:
Handler<??extends?Number>?intHandler1?=?new?Handler<Number>(2)?{
}
而在 Java 9 中,可以自动做类型推导,如下:
Handler<??extends?Number>?intHandler1?=?new?Handler<>(2)?{
}
2.2.12. 多分辨率图像 API:定义多分辨率图像 API,开发者可以很容易的操作和展示不同分辨率的图像了。
2.2.13. 改进的 CompletableFuture API
CompletableFuture 类的异步机制可以在 ProcessHandle.onExit 方法退出时执行操作。
其他一些改进可参照:
https://docs.oracle.com/javase/9/whatsnew/toc.htm
2.3 Java 10
参考资料
https://baijiahao.baidu.com/s?id=1594437679552808575&wfr=spider&for=pc
https://blog.csdn.net/visant/article/details/79778967
https://www.oracle.com/technetwork/java/javase/10-relnote-issues-4108729.html
2.3.1. 局部变量类型推断
局部变量类型推断可以说是 Java 10 中最值得注意的特性,这是 Java 语言开发人员为了简化 Java 应用程序的编写而采取的又一步,如下图所示。
这个新功能将为 Java 增加一些语法糖 - 简化它并改善开发者体验。新的语法将减少与编写 Java 相关的冗长度,同时保持对静态类型安全性的承诺。
局部变量类型推断将引入"var"关键字,也就是你可以随意定义变量而不必指定变量的类型,如:
将被下面这个新语法所取代:
看完是不是有点 JS 的即视感???越来越像 JS 了吗?!虽然类型推断在 Java 中不是一个新概念,但在局部变量中确是很大的一个改进。
说到类型推断,从 JDK 5 引进泛型,到 JDK 7 的"<>"操作符允许不绑定类型而初始化 List,再到 JDK 8 的 Lambda 表达式,再到现在 JDK 10 的局部变量类型推断,Java 类型推断正大刀阔斧的向前发展。
局部变量类型推荐仅限于如下使用场景:
局部变量初始化
for 循环内部索引变量
传统的 for 循环声明变量
Java 官方表示,它不能用于以下几个地方:
方法参数
构造函数参数
方法返回类型
字段捕获表达式(或任何其他类型的变量声明)
2.3.2. GC 改进和内存管理
JDK 10 中有 2 个 JEP 专门用于改进当前的垃圾收集元素。
第一个垃圾收集器接口是(JEP 304),它将引入一个纯净的垃圾收集器接口,以帮助改进不同垃圾收集器的源代码隔离。
预定用于 Java 10 的第二个 JEP 是针对 G1 的并行完全 GC(JEP 307),其重点在于通过完全 GC 并行来改善 G1 最坏情况的等待时间。G1 是 Java 9 中的默认 GC,并且此 JEP 的目标是使 G1 平行。
**2.3.**3. 线程本地握手(JEP 312)
JDK 10 将引入一种在线程上执行回调的新方法,因此这将会很方便能停止单个线程而不是停止全部线程或者一个都不停。
**2.3.**4. 备用内存设备上的堆分配(JEP 316)
允许 HotSpot VM 在备用内存设备上分配 Java 对象堆内存,该内存设备将由用户指定。
**2.3.**5. 其他 Unicode 语言 - 标记扩展(JEP 314)
目标是增强 java.util.Locale 及其相关的 API,以便实现语言标记语法的其他 Unicode 扩展(BCP 47)。
**2.3.**6. 基于 Java 的实验性 JIT 编译器
Oracle 希望将其 Java JIT 编译器 Graal 用作 Linux / x64 平台上的实验性 JIT 编译器。
**2.3.**7. 根证书(JEP 319)
这个的目标是在 Oracle 的 Java SE 中开源根证书。
**2.3.**8. 根证书颁发认证
这将使 OpenJDK 对开发人员更具吸引力,它还旨在减少 OpenJDK 和 Oracle JDK 构建之间的差异。
**2.3.**9. 将 JDK 生态整合单个存储库(JEP 296)
此 JEP 的主要目标是执行一些内存管理,并将 JDK 生态的众多存储库组合到一个存储库中。
**2.3.**10. 删除工具 javah(JEP 313)
从 JDK 中移除了 javah 工具,这个很简单并且很重要。
其他可参考:
https://www.oracle.com/technetwork/java/javase/10-relnote-issues-4108729.html#NewFeature
2.4 Java 11
参考资料
[https://blog.csdn.net/weixin_38055381/article/details/82865385](()
https://openjdk.java.net/projects/jdk/11/
2.4.1 本地变量类型推断
什么是局部变量类型推断?
var javastack = "javastack";
System.out.println(javastack);
大家看出来了,局部变量类型推断就是左边的类型直接使用 var 定义,而不用写具体的类型,编译器能根据右边的表达式自动推断类型,如上面的 String 。
var javastack = "javastack";
就等于:
String javastack = "javastack";
2.4.2 字符串加强
Java 11 增加了一系列的字符串处理方法,如以下所示。
// 判断字符串是否为空白
" ".isBlank(); // true
// 去除首尾空格
" Javastack ".strip(); // "Javastack"
// 去除尾部空格
" Javastack ".stripTrailing(); // " Javastack"
// 去除首部空格
" Javastack ".stripLeading(); // "Javastack "
// 复制字符串
"Java".repeat(3);// "JavaJavaJava"
// 行数统计
"A\nB\nC".lines().count(); // 3
2.4.3 集合加强
自 Java 9 开始,Jdk 里面为集合(List/ Set/ Map)都添加了 of 和 copyOf 方法,它们两个都用来创建不可变的集合,来看下它们的使用和区别。
示例 1:
var list = List.of("Java", "Python", "C");
var copy = List.copyOf(list);
System.out.println(list == copy); // true
示例 2:
var list = new ArrayList<String>();
var copy = List.copyOf(list);
System.out.println(list == copy); // false
示例 1 和 2 代码差不多,为什么一个为 true,一个为 false?
来看下它们的源码:
static <E> List<E> of(E... elements) {
switch (elements.length) { // implicit null check of elements
case 0:
return ImmutableCollections.emptyList();
case 1:
return new ImmutableCollections.List12<>(elements[0]);
case 2:
return new ImmutableCollections.List12<>(elements[0], elements[1]);
default:
return new ImmutableCollections.ListN<>(elements);
}
}
static <E> List<E> copyOf(Collection<? extends E> coll) {
return ImmutableCollections.listCopy(coll);
}
static <E> List<E> listCopy(Collection<? extends E> coll) {
if (coll instanceof AbstractImmutableList && coll.getClass() != SubList.class) {
return (List<E>)coll;
} else {
评论