JDK5
1.泛型 (Generics)
List<Integer> list=new ArrayList<Integer>();
2.增强循环(Enhanced for Loop)
int[] array = {1, 2, 3, 4, 5};
for (int i : array) {
System.out.println(i);
}
3.自动封箱拆箱(Autoboxing/Unboxing )
八大基本类型和它们的包装类能够自动的相互转换。
简单类型 | boolean | byte | char | short | Int | long | float | double | void |
---|---|---|---|---|---|---|---|---|---|
二进制位数 | 1 | 8 | 16 | 16 | 32 | 64 | 32 | 64 | -- |
封装器类 | Boolean | Byte | Character | Short | Integer | Long | Float | Double | Void |
4.枚举(Typesafe Enums)
ps:枚举是一种实现线程安全的单例模式的好方式。
enum TestEnum{
one,
two;
TestEnum() {
}
}
5.可变参数 (Varargs)
- 语法:(type… arguments)
可变参数本质仍然是用一个数组存储参数,只是java隐藏了这一过程。需要注意的是如果一个方法声明中含有可变参数,那必须放在最后一个位置。
/**
* 可变参数测试
*
* @param args
*/
public static void testVarargs(String... args) {
//本质就是个数组
System.out.println(args[1]);
for (String arg : args) {
System.out.println(arg);
}
}
6.静态导入(Static Import)
通过import类来使用类里的静态变量或方法(直接通过名字,不需要加上类名.),简化了代码的书写。
//单个导入
import static java.lang.Math.PI;
//批量导入
import static java.lang.Math.*;
ps:过去的版本中只能通过继承类或实现接口才能使用。
7.注解(Annotations),关键字@interface
//注释注解的注解又叫做元注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotations {
//注解内可以添加方法,也可以不添加
//注解方法的返回值只能是基本类型,String,Class类,枚举,注解,可以有默认值。
int id();
String name() default "whh";
Class classType();
TestEnum enumType();
}
8.新的线程模型和并发库(java.util.concurrent)
JDK6
1.集合框架增强
- 为了更好的支持双向访问集合。添加了许多新的类和接口。
- 新的数组拷贝方法。Arrays.copyOf和Arrays.copyOfRange
//以下为添加的新接口和类
Deque,BlockingDeque,NavigableSet,NavigableMap,ConcurrentNavigableMap,ArrayDeque, ConcurrentSkipListSet ,ConcurrentSkipListMap,ConcurrentSkipListMap ,AbstractMap.SimpleEntry ,AbstractMap.SimpleImmutableEntry
2.Scripting
可以让其他语言在java平台上运行。 java6包含了一个基于Mozilla Rhino实现的javascript脚本引擎。
3.支持JDBC4.0规范
JDK7
1.二进制前缀0b或者0B
整型(byte, short, int, long)可以直接用二进制表示。
//二进制字面值前缀0b 或0B
int i = 0b010;//10进制值为2
int j = 0B010;
2.字面常量数字的下划线
用下划线连接整数提升其可读性,自身无含义,不可用在数字的起始和末尾。
//数字间的下划线不影响实际值
int k = 1_1;//值为11
3.switch 支持String类型
4.泛型实例化类型自动推断
Map<String, List<String>> myMap = new HashMap<String, List<String>>(); // 之前
Map<String, List<String>> myMap = new HashMap<>(); // 现在
5.try-with-resources语句
/*
* 声明在try括号中的对象称为资源,在方法执行完毕后会被自动关闭,相对与之前必须在finally关闭资源,这一 *特性大大提高了代码的简洁性。
* 所有实现java.lang.AutoCloseable接口的类都作为资源被自动关闭。
*/
public static void copy(String src, String dst) {
try (InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dst)) {
byte[] buff = new byte[1024];
int n;
while ((n = in.read(buff)) >= 0) {
out.write(buff, 0, n);
}
} catch (IOException e) {
e.printStackTrace();
}
}
6.单个catch中捕获多个异常类型
(用| 分割)并通过改进的类型检查重新抛出异常
JDK8
1.lambada表达式(Lambda Expressions)
Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
2.方法引用(Method references)
方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,可以使语言的构造更紧凑简洁,减少冗余代码。
3.默认方法(Default methods)
默认方法允许将新功能添加到库的接口中,并确保兼容实现老版本接口的旧有代码。接口新增:默认方法与静态方法
4.重复注解(Repeating Annotations)
重复注解提供了在同一声明或类型中多次应用相同注解类型的能力。
5.类型注解(Type Annotation)
在任何地方都能使用注解,而不是在声明的地方。
6.类型推断增强
7.方法参数反射(Method Parameter Reflection)
8.Stream API
新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。Stream API集成到了Collections API里。
9.HashMap改进
在键值哈希冲突时能有更好表现。
10.Date Time API
加强对日期和时间的处理。
11.java.util 包下的改进
提供了几个实用的工具类。
- 并行数组排序。
- 标准的Base64编解码。
- 支持无符号运算。
12.java.util.concurrent 包下增加了新的类和方法
- java.util.concurrent.ConcurrentHashMap 类添加了新的方法以支持新的StreamApi和lambada表达式。
- java.util.concurrent.atomic 包下新增了类以支持可伸缩可更新的变量。
- java.util.concurrent.ForkJoinPool类新增了方法以支持 common pool。
- 新增了java.util.concurrent.locks.StampedLock类,为控制读/写访问提供了一个基于性能的锁,且有三种模式可供选择。
13.HotSpot
- 删除了 永久代(PermGen),取代它的是Metaspace(JEP 122)元空间
- 方法调用的字节码指令支持默认方法。
JDK9
1.java模块系统 (Java Platform Module System)。
2.新的版本号格式
MAJOR.MAJOR.MAJOR.MINOR.SECURITY.SECURITY.SECURITY.PATCH
3.java shell
JShell 工具 jShell命令 ,交互式命令行控制台
4.在private instance methods方法上可以使用@SafeVarargs注解。
5.diamond语法与匿名内部类结合使用
钻石操作符升级 可以有{}
6.下划线不能用在变量名中
7.支持私有接口方法
在接口中 jdk7 只能声明全名常量和抽象方法 jdk8 添加了静态方法和默认方法 jdk9添加了私有方法,可以使用diamond语法与匿名内部类结合使用。
8.Javadoc
- 简化Doclet API。
- 支持生成HTML5格式。
- 加入了搜索框,使用这个搜索框可以查询程序元素、标记的单词和文档中的短语。
- 支持新的模块系统。
9.JVM
- 增强了Garbage-First(G1)并用它替代Parallel GC成为默认的垃圾收集器。
- 统一了JVM 日志,为所有组件引入了同一个日志系统。
- 删除了JDK 8中弃用的GC组合。(DefNew + CMS,ParNew + SerialOld,Incremental CMS)。
10.properties文件支持UTF-8编码
之前只支持ISO-8859-1。
11.支持Unicode 8.0
在JDK8中是Unicode 6.2。
12.目录结构
13.多版本兼容jar包
14.异常处理try升级
15.String底层存储结构的变更
char数组变成byte字节数组
16.增强了Stream API
在java8基础上,新增加4个方法
17.引入httpClient api
代替原有的HttpURLConnection
Java10
1.局部变量类型推断(Local-Variable Type Inference)
//之前的代码格式
URL url = new URL("http://www.oracle.com/");
URLConnection conn = url.openConnection();
Reader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))
//java10中用var来声明变量
var url = new URL("http://www.oracle.com/");
var conn = url.openConnection();
var reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
var是一个保留类型名称,而不是关键字。所以之前使用var作为变量、方法名、包名的都没问题,但是如果作为类或接口名,那么这个类和接口就必须重命名了。
var的使用场景主要有以下四种:
- 本地变量初始化。
- 增强for循环中。
- 传统for循环中声明的索引变量。
- Try-with-resources 变量。
2.Optional类添加了新的方法orElseThrow
相比于已经存在的get方法,这个方法更推荐使用。
3.GC改进和内存管理
4.线程本地握手
5.备用内存设备上的堆分配
6.其他Unicode语言 - 标记扩展
7.基于Java的实验性JIT编译器
8.开源根证书
9.根证书颁发认证(CA)
10.将JDK生态整合单个存储库
11.删除工具javah
Java11
1.支持Unicode 10.0
在jdk10中是8.0。
2.标准化HTTP Client
3.编译器线程的延迟分配
添加了新的命令-XX:+UseDynamicNumberOfCompilerThreads动态控制编译器线程的数量。
4.新的垃圾收集器—ZGC
ZGC: A Scalable Low-Latency Garbage Collector(一种可伸缩的低延迟垃圾收集器(实验性))
5.Epsilon
一款新的实验性无操作垃圾收集器。Epsilon GC 只负责内存分配,不实现任何内存回收机制。这对于性能测试非常有用,可用于与其他GC对比成本和收益。
6.Lambda参数的局部变量语法
java10中引入的var字段得到了增强,现在可以用在lambda表达式的声明中。如果lambda表达式的其中一个形式参数使用了var,那所有的参数都必须使用var。
7.嵌套类可见性控制
8.动态文件常量
9.改进 Aarch64 Intrinsics
10.删除 Java EE 和 CORBA 模块
11.Curve25519 和 Curve448 算法的密钥协议
12.Flight Recorder(飞行记录器)
13.haCha20 和 Poly1305 加密算法支持
14.Launch Single-File Source-Code Programs(启动单一文件的源代码程序)
15.低开销的 Heap Profiling
16.TLS 1.3支持
17.弃用 Nashorn JavaScript 引擎
18.弃用 Pack200 工具和 API
jdk12
1.Switch Expressions
这是一个为开发者准备的特性,我们可以利用具体代码快速了解一下,下面是传统 statement 形式的 switch 语法:
switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
System.out.println(6);
break;
case TUESDAY:
System.out.println(7);
break;
case THURSDAY:
case SATURDAY:
System.out.println(8);
break;
case WEDNESDAY:
System.out.println(9);
break;
}
如果有编码经验,你一定知道,switch 语句如果漏写了一个 break,那么逻辑往往就跑偏了,这种方式既繁琐,又容易出错。如果换成 switch 表达式,Pattern Matching 机制能够自然地保证只有单一路径会被执行,请看下面的代码示例:
switch (day) {
case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
case TUESDAY -> System.out.println(7);
case THURSDAY, SATURDAY -> System.out.println(8);
case WEDNESDAY -> System.out.println(9);
}
更进一步,下面的表达式,为我们提供了优雅地表达特定场合计算逻辑的方式
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
};
Switch Expressions 或者说起相关的 Pattern Matching 特性,为我们提供了勾勒出了 Java 语法进化的一个趋势,将开发者从复杂繁琐的低层次抽象中逐渐解放出来,以更高层次更优雅的抽象,既降低代码量,又避免意外编程错误的出现,进而提高代码质量和开发效率。
2.Shenandoah GC
新增了一个名为 Shenandoah 的 GC 算法,通过与正在运行的 Java 线程同时进行 evacuation 工作来减少 GC 暂停时间。使用 Shenandoah 的暂停时间与堆大小无关,这意味着无论堆是 200 MB 还是 200 GB,都将具有相同的暂停时间。
JDK13
JDK13于9月17日正式发布。目前该版本包含的特性已经全部固定,主要包含以下五个:
下面来逐一介绍下这五个重要的特性。
1.Dynamic CDS Archives
这一特性是在JEP310:Application Class-Data Sharing基础上扩展而来的,Dynamic CDS Archives中的CDS指的就是Class-Data Sharing。
那么,这个JEP310是个啥东西呢?
我们知道在同一个物理机/虚拟机上启动多个JVM时,如果每个虚拟机都单独装载自己需要的所有类,启动成本和内存占用是比较高的。所以Java团队引入了CDS的概念,通过把一些核心类在每个JVM间共享,每个JVM只需要装载自己的应用类,启动时间减少了,另外核心类是共享的,所以JVM的内存占用也减少了。
CDS 只能作用于 Boot Class Loader 加载的类,不能作用于 App Class Loader 或者自定义的 Class Loader 加载的类。
在 Java 10 中,则将 CDS 扩展为 AppCDS,顾名思义,AppCDS 不止能够作用于 Boot Class Loader了,App Class Loader 和自定义的 Class Loader 也都能够起作用,大大加大了 CDS 的适用范围。也就说开发自定义的类也可以装载给多个JVM共享了。
Java 10中包含的JEP310的通过跨不同Java进程共享公共类元数据来减少了内存占用和改进了启动时间。
但是,JEP310中,使用AppCDS的过程还是比较复杂的,需要有三个步骤:
这一次的JDK 13中的JEP 350 ,在JEP310的基础上,又做了一些扩展。允许在Java应用程序执行结束时动态归档类,归档类将包括默认的基础层 CDS(class data-sharing)存档中不存在的所有已加载的应用程序类和库类。
也就是说,在Java 13中再使用AppCDS的时候,就不在需要这么复杂了。
2.ZGC: Uncommit Unused Memory
在讨论这个问题之前,想先问一个问题,JVM的GC释放的内存会还给操作系统吗?
GC后的内存如何处置,其实是取决于不同的垃圾回收器的。因为把内存还给OS,意味着要调整JVM的堆大小,这个过程是比较耗费资源的。
在JDK 11中,Java引入了ZGC,这是一款可伸缩的低延迟垃圾收集器,但是当时只是实验性的。并且,ZGC释放的内存是不会还给操作系统的。
而在Java 13中,JEP 351再次对ZGC做了增强,本次 ZGC 可以将未使用的堆内存返回给操作系统。之所以引入这个特性,是因为如今有很多场景中内存是比较昂贵的资源,在以下情况中,将内存还给操作系统还是很有必要的:
1、那些需要根据使用量付费的容器
2、应用程序可能长时间处于空闲状态并与许多其他应用程序共享或竞争资源的环境。
3、应用程序在执行期间可能有非常不同的堆空间需求。例如,启动期间所需的堆可能大于稍后在稳定状态执行期间所需的堆。
3.Reimplement the Legacy Socket API
使用易于维护和调试的更简单、更现代的实现替换 java.net.Socket 和 java.net.ServerSocket API。
java.net.Socket和java.net.ServerSocket的实现非常古老,这个JEP为它们引入了一个现代的实现。现代实现是Java 13中的默认实现,但是旧的实现还没有删除,可以通过设置系统属性jdk.net.usePlainSocketImpl来使用它们。
运行一个实例化Socket和ServerSocket的类将显示这个调试输出。这是默认的(新的).
上面输出的sun.nio.ch.NioSocketImpl就是新提供的实现。
如果使用旧的实现也是可以的(指定参数jdk.net.usePlainSocketImpl):
上面的结果中,旧的实现java.net.PlainSocketImpl被用到了。
4.Switch Expressions (Preview)
在JDK 12中引入了Switch表达式作为预览特性。JEP 354修改了这个特性,它引入了yield语句,用于返回值。这意味着,switch表达式(返回值)应该使用yield, switch语句(不返回值)应该使用break。
在以前,我们想要在switch中返回内容,还是比较麻烦的,一般语法如下:
在JDK13中使用以下语法:
或者
在这之后,switch中就多了一个关键字用于跳出switch块了,那就是yield,他用于返回一个值。和return的区别在于:return会直接跳出当前循环或者方法,而yield只会跳出当前switch块。
5.Text Blocks (Preview)
在JDK 12中引入了Raw String Literals特性,但在发布之前就放弃了。这个JEP在引入多行字符串文字(text block)在意义上是类似的。
text block,文本块,是一个多行字符串文字,它避免了对大多数转义序列的需要,以可预测的方式自动格式化字符串,并在需要时让开发人员控制格式。
我们以前从外部copy一段文本串到Java中,会被自动转义,如有一段以下字符串:
将其复制到Java的字符串中,会展示成以下内容:
使用“”“作为文本块的开始符合结束符,在其中就可以放置多行的字符串,不需要进行任何转义。看起来就十分清爽了。
如常见的SQL语句:
看起来就比较直观,清爽了。
JDK13中包含的5个特性,能够改变开发者的编码风格的主要有Text Blocks和Switch Expressions两个新特性,但是这两个特性还处于预览阶段。
而且,JDK13并不是LTS(长期支持)版本,如果你正在使用Java 8(LTS)或者Java 11(LTS),暂时可以不必升级到Java 13.