Java程序员必备基础:JDK 5-15都有哪些经典新特性
阅读原文时间:2020年09月21日阅读:4

前言

JDK 15发布啦~ 我们一起回顾JDK 5-15 的新特性吧,大家一起学习哈~

本文已经收录到github

https://github.com/whx123/JavaHome

「公众号:捡田螺的小男孩」

Java 5 新特性

1. 泛型

泛型本质是参数化类型,解决不确定具体对象类型的问题。

&nbsp;List<String>&nbsp;strList=new&nbsp;ArrayList<String>();

2. 增强循环(for-each)

for-each循环简化了集合的遍历。

String&nbsp;[]&nbsp;str&nbsp;=&nbsp;{"关注","公众号","捡田螺的小男孩"};for&nbsp;(String&nbsp;temp:str)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(temp);}

3. 自动封箱拆箱

  • 自动装箱: 就是将基本数据类型自动转换成对应的包装类。

  • 自动拆箱:就是将包装类自动转换成对应的基本数据类型。

包装类型有:Integer,Double,Float,Long,Short,Character和Boolean

Integer&nbsp;i&nbsp;=666;&nbsp;&nbsp;//自动装箱int&nbsp;a=&nbsp;i;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//自动拆箱

4. 枚举

关键字enum可以将一组具名的值的有限集合创建为一种新的类型,而这些具名的值可以作为常规的程序组件使用,这就是枚举类型。

enum&nbsp;SeasonEnum&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;SPRING,SUMMER,FALL,WINTER;}

5. 可变参数

我们在定义方法参数的时候不确定定义多少个,就可以定义为「可变参数」,它本质上是一个「数组」

public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;[]&nbsp;str&nbsp;=&nbsp;{"关注","公众号","捡田螺的小男孩"};&nbsp;&nbsp;&nbsp;&nbsp;testVarargs(str);&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;str1&nbsp;=&nbsp;"关注公众号,捡田螺的小男孩";&nbsp;&nbsp;&nbsp;&nbsp;testVarargs(str1);}//可变参数String...&nbsp;argsprivate&nbsp;static&nbsp;void&nbsp;testVarargs(String...&nbsp;args)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(String&nbsp;arg&nbsp;:&nbsp;args)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(arg);&nbsp;&nbsp;&nbsp;&nbsp;}}

6. 注解

可以把注解理解为代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。

@Target(ElementType.METHOD)@Retention(RetentionPolicy.SOURCE)public&nbsp;@interface&nbsp;Override&nbsp;{}

7.静态导入

通过import static类,就可以使用类里的静态变量或方法。看一下例子哈~

import&nbsp;static&nbsp;java.lang.System.out;&nbsp;//静态导入System类的静态变量outpublic&nbsp;class&nbsp;Test&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;str1&nbsp;=&nbsp;"关注公众号,捡田螺的小男孩";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(str1);&nbsp;//常规写法&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.println(str1);&nbsp;&nbsp;//静态导入,可以直接使用out输出&nbsp;&nbsp;&nbsp;&nbsp;}}

8. 线程并发库(JUC)

JDK5 丰富了线程处理功能,java.util.concurrent包提供了以下的类、接口:

  • 线程池:ExecutorService接口

  • 线程护斥:Lock 类

  • 线程通信:Condition接口

  • 同步队列:ArrayBlockingQueue类

  • 同步集合:ConcurrentHashMap类

Java 6 新特性

1.Desktop类和SystemTray类

JDK 6在java.awt包下,新增了两个类:Desktop类和SystemTray类

  • 「Desktop类」: 用来打开系统默认浏览器浏览指定的URL,打开系统默认邮件客户端发邮件等

  • 「SystemTray类」:用来在系统托盘区创建一个托盘程序,如果在微软的Windows上,它被称为“任务栏”状态区域。

//获取Desktop实例Desktop&nbsp;desktop&nbsp;=&nbsp;Desktop.getDesktop();desktop.browse(URI.create("https://www.baidu.com"));

2. 使用JAXB2来实现对象与XML之间的映射

JAXB,即Java Architecture for XML Binding,可以实现对象与XML之间的映射,常用注解如下:

  • @XmlRootElement:注解在类上面,对应xml的跟元素,使用name属性定义根节点的名称。

  • @XmlElement:指定一个字段或get/set方法映射到xml的节点,使用name属性定义这个根节点的名称。

  • @XmlAttribute:将JavaBean对象的属性映射为xml的属性,使用name属性为生成的xml属性指定别名。

  • @XmlAccessorType:定义映射这个类中的何种类型都需要映射到xml。

  • @XmlSchema: 将包映射到XML名称空间

「看个例子吧~」

public&nbsp;class&nbsp;JAXB2XmlTest&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;throws&nbsp;JAXBException,&nbsp;IOException&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List<Singer>&nbsp;list&nbsp;=&nbsp;new&nbsp;ArrayList<>();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(new&nbsp;Singer("jay",&nbsp;8));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(new&nbsp;Singer("eason",&nbsp;10));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SingerList&nbsp;singerList&nbsp;=&nbsp;new&nbsp;SingerList();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;singerList.setSingers(list);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;str&nbsp;=&nbsp;JAXB2XmlTest.beanToXml(singerList,&nbsp;SingerList.class);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;path&nbsp;=&nbsp;"C:\\jay.txt";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BufferedWriter&nbsp;bfw&nbsp;=&nbsp;new&nbsp;BufferedWriter(new&nbsp;FileWriter(new&nbsp;File(path)));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bfw.write(str);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bfw.close();&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;String&nbsp;beanToXml(Object&nbsp;obj,&nbsp;Class<?>&nbsp;load)&nbsp;throws&nbsp;JAXBException&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JAXBContext&nbsp;context&nbsp;=&nbsp;JAXBContext.newInstance(load);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Marshaller&nbsp;marshaller&nbsp;=&nbsp;context.createMarshaller();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,&nbsp;true);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;marshaller.setProperty(Marshaller.JAXB_ENCODING,&nbsp;"GBK");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringWriter&nbsp;writer&nbsp;=&nbsp;new&nbsp;StringWriter();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;marshaller.marshal(obj,writer);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;writer.toString();&nbsp;&nbsp;&nbsp;&nbsp;}}public&nbsp;class&nbsp;Singer&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;String&nbsp;name;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;int&nbsp;age;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Singer(String&nbsp;name,&nbsp;int&nbsp;age)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.name&nbsp;=&nbsp;name;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.age&nbsp;=&nbsp;age;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;@XmlAttribute(name="name")&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;String&nbsp;getName()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;name;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;setName(String&nbsp;name)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.name&nbsp;=&nbsp;name;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;@XmlAttribute(name="age")&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;int&nbsp;getAge()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;age;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;setAge(int&nbsp;age)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.age&nbsp;=&nbsp;age;&nbsp;&nbsp;&nbsp;&nbsp;}}@XmlRootElement(name="list")public&nbsp;class&nbsp;SingerList&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;List<Singer>&nbsp;singers;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@XmlElement(name="singer")&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;List<Singer>&nbsp;getSingers()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;singers;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;setSingers(List<Singer>&nbsp;singers)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.singers&nbsp;=&nbsp;singers;&nbsp;&nbsp;&nbsp;&nbsp;}}

「运行效果:」

<?xml&nbsp;version="1.0"&nbsp;encoding="GBK"&nbsp;standalone="yes"?><list>&nbsp;&nbsp;&nbsp;&nbsp;<singer&nbsp;age="8"&nbsp;name="jay"/>&nbsp;&nbsp;&nbsp;&nbsp;<singer&nbsp;age="10"&nbsp;name="eason"/></list>

3.轻量级 Http Server API

JDK 6中提供了简单的Http Server API,可以构建嵌入式Http服务器,同时支持Http和Https协议。HttpServer会调用HttpHandler实现类的回调方法来处理客户端请求,这里用户只需实现HttpHandler接口就可以了。

/**&nbsp;*&nbsp;根据Java提供的API实现Http服务器&nbsp;*/public&nbsp;class&nbsp;MyHttpServer&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;args&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@throws&nbsp;IOException&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;throws&nbsp;IOException&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//创建HttpServer服务器&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServer&nbsp;httpServer&nbsp;=&nbsp;HttpServer.create(new&nbsp;InetSocketAddress(8080),&nbsp;10);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//将&nbsp;/jay请求交给MyHandler处理器处理&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;httpServer.createContext("/",&nbsp;new&nbsp;MyHandler());&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;httpServer.start();&nbsp;&nbsp;&nbsp;&nbsp;}}public&nbsp;class&nbsp;MyHandler&nbsp;implements&nbsp;HttpHandler&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;handle(HttpExchange&nbsp;httpExchange)&nbsp;throws&nbsp;IOException&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//请求头&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Headers&nbsp;headers&nbsp;=&nbsp;httpExchange.getRequestHeaders();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set<Map.Entry<String,&nbsp;List<String>>>&nbsp;entries&nbsp;=&nbsp;headers.entrySet();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringBuffer&nbsp;response&nbsp;=&nbsp;new&nbsp;StringBuffer();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(Map.Entry<String,&nbsp;List<String>>&nbsp;entry&nbsp;:&nbsp;entries){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response.append(entry.toString()&nbsp;+&nbsp;"\n");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//设置响应头属性及响应信息的长度&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;httpExchange.sendResponseHeaders(200,&nbsp;response.length());&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//获得输出流&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OutputStream&nbsp;os&nbsp;=&nbsp;httpExchange.getResponseBody();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;os.write(response.toString().getBytes());&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;os.close();&nbsp;&nbsp;&nbsp;&nbsp;}}

4. 插入式注解处理API

JDK 6提供了插入式注解处理API,可以让我们定义的注解在编译期而不是运行期生效,从而可以在编译期修改字节码。lombok框架就是使用该特性来实现的,Lombok通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString等方法,大大简化了代码的开发。

5. STAX

STAX,是JDK6中一种处理XML文档的API。

public&nbsp;class&nbsp;STAXTest&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;XMLInputFactory&nbsp;xmlInputFactory&nbsp;=&nbsp;XMLInputFactory.newInstance();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;XMLEventReader&nbsp;xmlEventReader&nbsp;=&nbsp;xmlInputFactory.createXMLEventReader(new&nbsp;FileInputStream("C:\\jay.xml"));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;XMLEvent&nbsp;event&nbsp;=&nbsp;null;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringBuffer&nbsp;stringBuffer&nbsp;=&nbsp;new&nbsp;StringBuffer();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;(xmlEventReader.hasNext())&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;event&nbsp;=&nbsp;xmlEventReader.nextEvent();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stringBuffer.append(event.toString());&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("xml文档解析结果:");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(stringBuffer);&nbsp;&nbsp;&nbsp;&nbsp;}}

「运行结果:」

xml文档解析结果:<?xml&nbsp;version="1.0"&nbsp;encoding='GBK'&nbsp;standalone='yes'?><list>&nbsp;&nbsp;&nbsp;&nbsp;<singer&nbsp;name='jay'&nbsp;age='8'></singer>&nbsp;&nbsp;&nbsp;&nbsp;<singer&nbsp;name='eason'&nbsp;age='10'></singer></list>ENDDOCUMENT

6. Common Annotations

Common annotations原本是Java EE 5.0(JSR 244)规范的一部分,现在SUN把它的一部分放到了Java SE 6.0中。随着Annotation元数据功能加入到Java SE 5.0里面,很多Java 技术都会用Annotation部分代替XML文件来配置运行参数。

以下列举Common Annotations 1.0里面的几个Annotations:

  • @Generated:用于标注生成的源代码

  • @Resource: 用于标注所依赖的资源,容器据此注入外部资源依赖,有基于字段的注入和基于setter方法的注入两种方式 。

  • @Resources:同时标注多个外部依赖,容器会把所有这些外部依赖注入

  • @PostConstruct:标注当容器注入所有依赖之后运行的方法,用来进行依赖注入后的初始化工作,只有一个方法可以标注为PostConstruct 。

  • @PreDestroy:当对象实例将要被从容器当中删掉之前,要执行的回调方法要标注为PreDestroy

7. Compiler API

javac编译器可以把.java的源文件编译为.class文件,JDK 6的新特性Compiler API(JSR 199)也可以动态编译Java源文件。

public&nbsp;class&nbsp;CompilerApiTest&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JavaCompiler&nbsp;javaCompiler&nbsp;=&nbsp;ToolProvider.getSystemJavaCompiler();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StandardJavaFileManager&nbsp;standardJavaFileManager&nbsp;=&nbsp;javaCompiler.getStandardFileManager(null,null,null);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterable<?&nbsp;extends&nbsp;JavaFileObject>&nbsp;javaFileObjects&nbsp;=&nbsp;standardJavaFileManager.getJavaFileObjects("C:\\Singer.java");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;javaCompiler.getTask(null,&nbsp;standardJavaFileManager,&nbsp;null,&nbsp;null,&nbsp;null,&nbsp;javaFileObjects).call();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;standardJavaFileManager.close();&nbsp;&nbsp;&nbsp;&nbsp;}}

运行结果:会在C目录生成Singer.class文件

8. 对脚本语言的支持(如: ruby, groovy, javascript)

JDK6增加了对脚本语言的支持(JSR 223),原理是将脚本语言编译成字节码,这样脚本语言也能享用Java平台的诸多优势,包括可移植性,安全等。JDK6实现包含了一个基于Mozilla Rhino的 脚本语言引擎,因此可以支持javascript,当然JDK也支持ruby等其他语言

public&nbsp;class&nbsp;JavaScriptTest&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;throws&nbsp;Exception&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ScriptEngineManager&nbsp;factory&nbsp;=&nbsp;new&nbsp;ScriptEngineManager();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ScriptEngine&nbsp;engine&nbsp;=&nbsp;factory.getEngineByName("JavaScript");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;script;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;script&nbsp;=&nbsp;"print('Hello')";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;engine.eval(script);//&nbsp;执行脚本&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}catch&nbsp;(Exception&nbsp;e)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;}}//outputHello

Java 7 新特性

1.switch 支持String字符串类型。

String&nbsp;singer&nbsp;=&nbsp;"jay";switch&nbsp;(singer)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;"jay"&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("周杰伦");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;"eason"&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("陈奕迅");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break&nbsp;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default&nbsp;:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("其他");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break&nbsp;;&nbsp;&nbsp;&nbsp;}

2.try-with-resources,资源自动关闭

JDK 7 之前:

BufferedReader&nbsp;br&nbsp;=&nbsp;new&nbsp;BufferedReader(new&nbsp;FileReader("d:七里香.txt"));try&nbsp;{&nbsp;&nbsp;&nbsp;return&nbsp;br.readLine();}&nbsp;finally&nbsp;{&nbsp;&nbsp;&nbsp;br.close();}

JDK 7 之后:

/*&nbsp;*&nbsp;声明在try括号中的对象称为资源,在方法执行完毕后会被自动关闭&nbsp;*/try&nbsp;(BufferedReader&nbsp;br&nbsp;=&nbsp;new&nbsp;BufferedReader(new&nbsp;FileReader("d:七里香.txt"))&nbsp;{&nbsp;&nbsp;&nbsp;return&nbsp;br.readLine();}

3. 整数类型如(byte,short,int,long)能够用二进制来表示

//0b或者0B表示二进制int&nbsp;a&nbsp;=&nbsp;0b010;int&nbsp;b&nbsp;=&nbsp;0B010;

4. 数字常量支持下划线

int&nbsp;a&nbsp;=&nbsp;11_11;//a的值为1111,下划线不影响实际值,提升可读性

5. 泛型实例化类型自动推断,即”<>”

JDK 7 之前:

Map<String,&nbsp;List<String>>&nbsp;map&nbsp;=&nbsp;new&nbsp;HashMap<String,&nbsp;List<String>>();

JDK 7之后:

//不须声明类型,自动根据前面<>推断其类型Map<String,&nbsp;List<String>>&nbsp;map&nbsp;=&nbsp;new&nbsp;HashMap<>();

6.一个catch中捕获多个异常类型,用(|)分隔开

JDK 7之前

try{&nbsp;&nbsp;&nbsp;//do&nbsp;something}&nbsp;catch&nbsp;(FirstException&nbsp;e)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.error(e);}&nbsp;catch&nbsp;(SecondException&nbsp;e)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.error(ex);}

JDk 7之后

try{&nbsp;&nbsp;&nbsp;//do&nbsp;something}&nbsp;catch&nbsp;(FirstException&nbsp;|&nbsp;SecondException&nbsp;e)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.error(e);}

7. 增强的文件系统

Java7 提供了全新的NIO2.0 API,方便文件管理的编码。如,可以在java.nio.file包下使用Path、Paths、Files、WatchService等常用类型。

Path&nbsp;path&nbsp;=&nbsp;Paths.get("C:\\jay\\七里香.txt");&nbsp;//创建Path对象byte[]&nbsp;bytes=&nbsp;Files.readAllBytes(path);&nbsp;&nbsp;//读取文件System.out.println(path.getFileName());&nbsp;//获取当前文件名称System.out.println(path.toAbsolutePath());&nbsp;//&nbsp;获取文件绝对路径System.out.println(new&nbsp;String(bytes,&nbsp;"utf-8"));

8. Fork/join 框架

Java7提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。

Fork/join计算1-1000累加值:

public&nbsp;class&nbsp;ForkJoinPoolTest&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;final&nbsp;Integer&nbsp;DURATION_VALUE&nbsp;=&nbsp;100;&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;class&nbsp;ForkJoinSubTask&nbsp;extends&nbsp;RecursiveTask<Integer>{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;子任务开始计算的值&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;Integer&nbsp;startValue;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;子任务结束计算的值&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;Integer&nbsp;endValue;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;ForkJoinSubTask(Integer&nbsp;startValue&nbsp;,&nbsp;Integer&nbsp;endValue)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.startValue&nbsp;=&nbsp;startValue;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.endValue&nbsp;=&nbsp;endValue;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;Integer&nbsp;compute()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//小于一定值DURATION,才开始计算&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(endValue&nbsp;-&nbsp;startValue&nbsp;<&nbsp;DURATION_VALUE)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("执行子任务计算:开始值&nbsp;=&nbsp;"&nbsp;+&nbsp;startValue&nbsp;+&nbsp;";结束值&nbsp;=&nbsp;"&nbsp;+&nbsp;endValue);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Integer&nbsp;totalValue&nbsp;=&nbsp;0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(int&nbsp;index&nbsp;=&nbsp;this.startValue;&nbsp;index&nbsp;<=&nbsp;this.endValue;&nbsp;index++)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;totalValue&nbsp;+=&nbsp;index;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;totalValue;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;将任务拆分,拆分成两个任务&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ForkJoinSubTask&nbsp;subTask1&nbsp;=&nbsp;new&nbsp;ForkJoinSubTask(startValue,&nbsp;(startValue&nbsp;+&nbsp;endValue)&nbsp;/&nbsp;2);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;subTask1.fork();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ForkJoinSubTask&nbsp;subTask2&nbsp;=&nbsp;new&nbsp;ForkJoinSubTask((startValue&nbsp;+&nbsp;endValue)&nbsp;/&nbsp;2&nbsp;+&nbsp;1&nbsp;,&nbsp;endValue);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;subTask2.fork();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;subTask1.join()&nbsp;+&nbsp;subTask2.join();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;throws&nbsp;ExecutionException,&nbsp;InterruptedException&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Fork/Join框架的线程池&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ForkJoinPool&nbsp;pool&nbsp;=&nbsp;new&nbsp;ForkJoinPool();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ForkJoinTask<Integer>&nbsp;taskFuture&nbsp;=&nbsp;&nbsp;pool.submit(new&nbsp;ForkJoinSubTask(1,1000));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Integer&nbsp;result&nbsp;=&nbsp;taskFuture.get();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("累加结果是:"&nbsp;+&nbsp;result);&nbsp;&nbsp;&nbsp;&nbsp;}}

运行结果:

...执行子任务计算:开始值&nbsp;=&nbsp;189;结束值&nbsp;=&nbsp;250执行子任务计算:开始值&nbsp;=&nbsp;251;结束值&nbsp;=&nbsp;313执行子任务计算:开始值&nbsp;=&nbsp;314;结束值&nbsp;=&nbsp;375执行子任务计算:开始值&nbsp;=&nbsp;376;结束值&nbsp;=&nbsp;438执行子任务计算:开始值&nbsp;=&nbsp;439;结束值&nbsp;=&nbsp;500执行子任务计算:开始值&nbsp;=&nbsp;501;结束值&nbsp;=&nbsp;563执行子任务计算:开始值&nbsp;=&nbsp;564;结束值&nbsp;=&nbsp;625执行子任务计算:开始值&nbsp;=&nbsp;626;结束值&nbsp;=&nbsp;688执行子任务计算:开始值&nbsp;=&nbsp;689;结束值&nbsp;=&nbsp;750执行子任务计算:开始值&nbsp;=&nbsp;751;结束值&nbsp;=&nbsp;813执行子任务计算:开始值&nbsp;=&nbsp;814;结束值&nbsp;=&nbsp;875执行子任务计算:开始值&nbsp;=&nbsp;876;结束值&nbsp;=&nbsp;938执行子任务计算:开始值&nbsp;=&nbsp;939;结束值&nbsp;=&nbsp;1000累加结果是:500500

Java 8 新特性

1.lambada表达式

Lambda 允许把函数作为一个方法的参数,传递到方法中

语法格式:

(parameters)&nbsp;->&nbsp;expression&nbsp;或&nbsp;(parameters)&nbsp;->{&nbsp;statements;&nbsp;}

代码示例:

Arrays.asList("jay",&nbsp;"Eason",&nbsp;"SHE").forEach(&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(&nbsp;String&nbsp;singer&nbsp;)&nbsp;->&nbsp;System.out.print(&nbsp;singer&nbsp;+&nbsp;",")&nbsp;);

2. 函数式接口

Lambda的设计者为了让现有的功能与Lambda表达式很好兼容,设计出函数式接口。

  • 函数式接口是指只有一个函数的接口,可以隐式转换为lambada表达式。

  • Java 8 提供了注解@FunctionalInterface,显示声明一个函数式接口。

  • java.lang.Runnable和java.util.concurrent.Callable是函数式接口的例子~

    @FunctionalInterfacepublic interface Runnable {    public abstract void run();}

3. 方法引用

方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。它与Lambda表达式配合使用,可以减少冗余代码,使代码更加简洁。

//利用函数式接口Consumer的accept方法实现打印,Lambda表达式如下Consumer<String>&nbsp;consumer&nbsp;=&nbsp;x&nbsp;->&nbsp;System.out.println(x);consumer.accept("jay");//引用PrintStream类(也就是System.out的类型)的println方法,这就是方法引用consumer&nbsp;=&nbsp;System.out::println;consumer.accept("关注公众号捡田螺的小男孩");

4. 默认方法

默认方法就是一个在接口里面有了一个实现的方法。它允许将新方法添加到接口,但不强制实现了该接口的类必须实现新的方法。

public&nbsp;interface&nbsp;ISingerService&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;默认方法&nbsp;&nbsp;&nbsp;&nbsp;default&nbsp;void&nbsp;sing(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("唱歌");&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;writeSong();}//JaySingerServiceImpl&nbsp;不用强制实现ISingerService的默认sing()方法public&nbsp;class&nbsp;JaySingerServiceImpl&nbsp;implements&nbsp;ISingerService&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;@Override&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;writeSong()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("写了一首七里香");&nbsp;&nbsp;&nbsp;&nbsp;}}

5.Stream API

Stream API,支持对元素流进行函数式操作,它集成在Collections API 中,可以对集合进行批量操作。常用API:

  • filter 筛选

  • map流映射

  • reduce 将流中的元素组合起来

  • collect 返回集合

  • sorted 排序

  • flatMap 流转换

  • limit返回指定流个数

  • distinct去除重复元素

    public class Singer {    private String name;    private Integer songNum;    private Integer age;    …}List singerList = new ArrayList();singerList.add(new Singer("jay", 11, 36));singerList.add(new Singer("eason", 8, 31));singerList.add(new Singer("JJ", 6, 29));List singerNameList = singerList.stream()                .filter(singer -> singer.getAge() > 30)  //筛选年龄大于30                .sorted(Comparator.comparing(Singer::getSongNum))  //根据歌曲数量排序                .map(Singer::getName)  //提取歌手名字                .collect(Collectors.toList()); //转换为List

6. Optional

Java 8引入Optional类,用来解决NullPointerException。Optional代替if…else解决空指针问题,使代码更加简洁。

if…else 判空

Singer&nbsp;singer&nbsp;=&nbsp;getSingerById("666");if&nbsp;(singer&nbsp;!=&nbsp;null)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;name&nbsp;&nbsp;=&nbsp;singer.getName();&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(name);}

Optional的判空

Optional<Singer>&nbsp;singer&nbsp;=&nbsp;Optional.ofNullable(getSingerById("666"));singer.ifPresent(s&nbsp;->&nbsp;System.out.println(s.getName()));

7. Date Time API

JDK 8之前的日期API处理存在非线程安全、时区处理麻烦等问题。Java 8 在 java.time包下提供了新的日期API,简化了日期的处理~

LocalDate&nbsp;today&nbsp;=&nbsp;LocalDate.now();int&nbsp;year&nbsp;=&nbsp;today.getYear();System.out.println("今年是"&nbsp;+&nbsp;year);//是否闰年System.out.println("今年是不是闰年:"&nbsp;+&nbsp;today.isLeapYear());LocalDateTime&nbsp;todayTime&nbsp;=&nbsp;LocalDateTime.now();System.out.println("当前时间"&nbsp;+&nbsp;todayTime);//时区指定System.out.println("美国时间:"&nbsp;+&nbsp;ZonedDateTime.of(todayTime,ZoneId.of("America/Los_Angeles")));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LocalDate&nbsp;specailDate&nbsp;=&nbsp;LocalDate.of(2020,&nbsp;6,&nbsp;20);LocalDate&nbsp;expectDate&nbsp;=&nbsp;specailDate.plus(100,&nbsp;ChronoUnit.DAYS);System.out.println("比较特别的一天"&nbsp;+&nbsp;specailDate);System.out.println("特殊日期的100天"&nbsp;+&nbsp;expectDate);

8. 重复注解

重复注解,即一个注解可以在一个类、属性或者方法上同时使用多次;用@Repeatable定义重复注解

@Repeatable(ScheduleTimes.class)public&nbsp;@interface&nbsp;ScheduleTime&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;value();}public&nbsp;@interface&nbsp;ScheduleTimes&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;ScheduleTime[]&nbsp;value();}public&nbsp;class&nbsp;ScheduleTimeTask&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;@ScheduleTime("10")&nbsp;&nbsp;&nbsp;&nbsp;@ScheduleTime("12")&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;doSomething()&nbsp;{&nbsp;}}

9. Base64

Java 8把Base64编码的支持加入到官方库中~

String&nbsp;str&nbsp;=&nbsp;"公众号:捡田螺的小男孩";String&nbsp;encoded&nbsp;=&nbsp;Base64.getEncoder().encodeToString(str.getBytes(&nbsp;StandardCharsets.UTF_8));String&nbsp;decoded&nbsp;=&nbsp;new&nbsp;String(Base64.getDecoder().decode(encoded),&nbsp;StandardCharsets.UTF_8);

10. JVM的新特性

使用元空间Metaspace代替持久代(PermGen space),JVM参数使用-XX:MetaSpaceSize和-XX:MaxMetaspaceSize设置大小。

Java 9 新特性

1. java模块系统

什么是模块化?

一个大型系统,比如一个商城网站,它会包含很多模块的,如:订单模块,用户信息模块,商品信息模块,广告位模块等等。各个模块之间会相互调用。如果每个模块单独运行都会带动其他所有模块,性能非常低效。但是,如果某一模块运行时,只会启动它所依赖的模块,性能大大提升。这就是JDK 9模块化的思想。

什么是JDK 9模块化?

Java 平台模块系统,即Project Jigsaw,把模块化开发实践引入到了Java平台中。在引入了模块系统之后,JDK 被重新组织成94个模块。Java 应用可以通过新增的jlink 工具,创建出只包含所依赖的JDK模块的自定义运行时镜像。这样可以极大的减少Java运行时环境的大小。

Java 9 模块的重要特征:

  • 在其工件(artifact)的根目录中包含了一个描述模块的 module-info.class 文 件。

  • 工件的格式可以是传统的 JAR 文件或是 Java 9 新增的 JMOD 文件。

  • 这个文件由根目录中的源代码文件 module-info.java 编译而来。

  • 该模块声明文件可以描述模块的不同特征。

在 module-info.java 文件中,我们可以用新的关键词module来声明一个模块,如下所示。下面给出了一个模块com.mycompany.mymodule的最基本的模块声明

module&nbsp;com.jay.sample&nbsp;{&nbsp;&nbsp;&nbsp;//关键词module来声明一个模块&nbsp;&nbsp;&nbsp;&nbsp;exports&nbsp;com.jay.sample;&nbsp;//使用&nbsp;exports可以声明模块对其他模块所导出的包。&nbsp;&nbsp;&nbsp;&nbsp;requires&nbsp;com.jay.common;&nbsp;//使用requires可以声明模块对其他模块的依赖关系。}

2. 不可变集合工厂方法

为了创建不可变集合,JDK9之前酱紫的:

List<String>&nbsp;stringList&nbsp;=&nbsp;new&nbsp;ArrayList<>();stringList.add("关注公众号:");stringList.add("捡田螺的小男孩");List<String>&nbsp;unmodifiableList&nbsp;=&nbsp;Collections.unmodifiableList(stringList);

JDK 9 提供了List.of()、Set.of()、Map.of()和Map.ofEntries()等工厂方法来创建不可变集合:

List<String>&nbsp;unmodifiableList&nbsp;=&nbsp;List.of("关注公众号:","捡田螺的小男孩");

3. 接口支持私有方法

JDK 8支持在接口实现默认方法和静态方法,但是不能在接口中创建私有方法,为了避免了代码冗余和提高阅读性,JDK 9在接口中支持私有方法。

public&nbsp;interface&nbsp;IPrivateInterfaceTest&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;//JDK&nbsp;7&nbsp;之前&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;a&nbsp;=&nbsp;"jay";&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;method7();&nbsp;&nbsp;&nbsp;&nbsp;//JDK&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;default&nbsp;void&nbsp;methodDefault8(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("JDK&nbsp;8新特性默认方法");&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;void&nbsp;methodStatic8()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("JDk&nbsp;8新特性静态方法");&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//Java&nbsp;9&nbsp;接口支持私有方法&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;void&nbsp;method9(){}}

4. 钻石操作符升级

  • 钻石操作符是在 java 7 中引入的,可以让代码更易读,但它不能用于匿名的内部类。

  • 在 java 9 中, 它可以与匿名的内部类一起使用,从而提高代码的可读性。

    //JDK 5,6Map map56 = new HashMap();//JDk 7,8Map map78 = new HashMap<>();//JDK 9 结合匿名内部类的实现Map map9 = new HashMap<>(){};

5. Optional 类改进

java 9 中,java.util.Optional 添加了很多新的有用方法,如:

  • stream()

  • ifPresentOrElse()

  • or()

ifPresentOrElse 方法的改进就是有了 else,接受两个参数 Consumer 和 Runnable。

import&nbsp;java.util.Optional;&nbsp;public&nbsp;class&nbsp;OptionalTest&nbsp;{&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Optional<Integer>&nbsp;optional&nbsp;=&nbsp;Optional.of(1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional.ifPresentOrElse(&nbsp;x&nbsp;->&nbsp;System.out.println("Value:&nbsp;"&nbsp;+&nbsp;x),()&nbsp;->&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Not&nbsp;Present."));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional&nbsp;=&nbsp;Optional.empty();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional.ifPresentOrElse(&nbsp;x&nbsp;->&nbsp;System.out.println("Value:&nbsp;"&nbsp;+&nbsp;x),()&nbsp;->&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Not&nbsp;Present."));&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;}

6. 多版本兼容Jar包

很多公司使用的JDK都是老版本的,JDK6、JDk5 ,甚至JDk4的,不是他们不想升级JDk版本,而是担心兼容性问题。JDK 9的一个新特性,多版本兼容Jar包解决了这个问题。举个例子:假设你一直用的是小米8,已经非常习惯它的运行流程了,突然出来小米9,即使小米9很多新功能引人入胜,但是有些人不会轻易买小米9,因为已经已经习惯小米8的流程。同理,为什么很多公司不升级JDK,就是在此。但是呢,JDK 9的这个功能很强大,它可以让你的版本升级到JDK 9,但是还是老版本的运行流程,即在老的运行流程继承新的功能~

7. JShell工具

jShell工具相当于cmd工具,然后呢,你可以像在cmd工具操作一样,直接在上面运行Java方法,Java语句等~

jshell>&nbsp;System.out.println("关注公众号:捡田螺的小男孩");关注公众号:捡田螺的小男孩

8. try-with-resources的改进

JDK 9对try-with-resources异常处理机制进行了升级~

//JDK&nbsp;7,8try&nbsp;(BufferedReader&nbsp;br&nbsp;=&nbsp;new&nbsp;BufferedReader(new&nbsp;FileReader("d:七里香.txt"))&nbsp;{&nbsp;&nbsp;&nbsp;br.readLine();}catch(IOException&nbsp;e){&nbsp;&nbsp;log.error("IO&nbsp;异常,e:{}",e);}//JDk&nbsp;9BufferedReader&nbsp;br&nbsp;=&nbsp;new&nbsp;BufferedReader(new&nbsp;FileReader("d:七里香.txt")try(br){&nbsp;&nbsp;br.readLine();}catch(IOException&nbsp;e){&nbsp;&nbsp;log.error("IO&nbsp;异常,e:{}",e);}

9. Stream API的改进

JDK 9 为Stream API引入以下这些方法,丰富了流处理操作:

  • takeWhile()

  • dropWhile()

  • iterate

  • ofNullable

「takeWhile」

使用一个断言(Predicate 接口)作为参数,返回给定Stream的子集直到断言语句第一次返回 false

//&nbsp;语法格式default&nbsp;Stream<T>&nbsp;takeWhile(Predicate<?&nbsp;super&nbsp;T>&nbsp;predicate)//代码示例Stream.of(1,2,3).takeWhile(s->&nbsp;x<2)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.forEach(System.out::println);&nbsp;&nbsp;//输出&nbsp;1

「dropWhile」

与 takeWhile()作用相反,使用一个断言(Predicate 接口)作为参数,直到断言语句第一次返回true,返回给定Stream的子集

//语法default&nbsp;Stream<T>&nbsp;dropWhile(Predicate<?&nbsp;super&nbsp;T>&nbsp;predicate)//代码示例Stream.of(1,2,3).dropWhile(s->&nbsp;x<2)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.forEach(System.out::println);//输出23

「iterate」

iterate() 方法能够返回以seed(第一个参数)开头,匹配 Predicate(第二个参数)直到返回false,并使用第三个参数生成下一个元素的元素流。

//语法static&nbsp;<T>&nbsp;Stream<T>&nbsp;iterate(T&nbsp;seed,&nbsp;Predicate<?&nbsp;super&nbsp;T>&nbsp;hasNext,&nbsp;UnaryOperator<T>&nbsp;next)//代码示例IntStream.iterate(2,&nbsp;x&nbsp;->&nbsp;x&nbsp;<&nbsp;10,&nbsp;x&nbsp;->&nbsp;x*x).forEach(System.out::println);//输出24

「ofNullable」

如果指定元素为非null,则获取一个元素并生成单个元素流,元素为null则返回一个空Stream。

//语法static&nbsp;<T>&nbsp;Stream<T>&nbsp;ofNullable(T&nbsp;t)//代码示例Stream<Integer>&nbsp;s1=&nbsp;Stream.ofNullable(100);s1.forEach(System.out::println)Stream<Integer>&nbsp;s2&nbsp;=&nbsp;Stream.ofNullable(null);s2.forEach(System.out::println)//输出100

10.其他

  • HTTP 2客户端 (支持 WebSocket和 HTTP2 流以及服务器推送)

  • 进程API(控制和管理操作系统进程)

  • String底层存储结构更改(char[]替换为byte[])

  • 标识符添加限制( String _ ="hello"不能用)

  • 响应式流 API (支持Java 9中的响应式编程)

Java 10 新特性

1.局部变量类型推断

JDK 10增加了局部变量类型推断(Local-Variable Type Inference)功能,让 Java 可以像Js里的var一样可以自动推断数据类型。Java中的var是一个保留类型名称,而不是关键字。

JDK 10之前

List<String>&nbsp;list&nbsp;=&nbsp;new&nbsp;ArrayList<String>();Stream<Integer>&nbsp;stream&nbsp;=&nbsp;Stream.of(1,&nbsp;2,&nbsp;3);

JDK 10 之后

var&nbsp;list&nbsp;=&nbsp;new&nbsp;ArrayList<String>();&nbsp;//&nbsp;ArrayList<String>var&nbsp;stream&nbsp;=&nbsp;&nbsp;Stream.of(1,&nbsp;2,&nbsp;3);

var 变量类型推断的使用也有局限性,仅「局限」于以下场景:

  • 具有初始化器的局部变量

  • 增强型for循环中的索引变量

  • 传统for循环中声明的局部变量

「不能用于」

  • 推断方法的参数类型

  • 构造函数参数类型推断

  • 推断方法返回类型

  • 字段类型推断

  • 捕获表达式

2. 不可变集合的改进

JDK 10中,List,Set,Map 提供了一个新的静态方法copyOf(Collection coll),它返回Collection集合一个不可修改的副本。

JDK 源码:

static&nbsp;<E>&nbsp;List<E>&nbsp;copyOf(Collection<?&nbsp;extends&nbsp;E>&nbsp;coll)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;ImmutableCollections.listCopy(coll);}

使用实例:

var&nbsp;oldList&nbsp;=&nbsp;new&nbsp;ArrayList<String>();oldList.add("欢迎关注公众号:");oldList.add("捡田螺的小男孩");var&nbsp;copyList&nbsp;=&nbsp;List.copyOf(oldList);oldList.add("在看、转载、点赞三连");&nbsp;copyList.add("双击666");&nbsp;&nbsp;//UnsupportedOperationException异常

3. 并行全垃圾回收器 G1

JDK 9引入 G1 作为默认垃圾收集器,执行GC 时采用的是基于单线程标记扫描压缩算法(mark-sweep-compact)。为了最大限度地减少 Full GC 造成的应用停顿的影响,Java 10 中将为 G1 引入多线程并行 GC,同时会使用与年轻代回收和混合回收相同的并行工作线程数量,从而减少了 Full GC 的发生,以带来更好的性能提升、更大的吞吐量。

4. 线程本地握手

Java 10 中线程管控引入JVM安全点的概念,将允许在不运行全局JVM安全点的情况下实现线程回调,由线程本身或者JVM线程来执行,同时保持线程处于阻塞状态,这将会很方便使得停止单个线程或不停止线程成为可能。

5. Optional新增orElseThrow()方法

Optional、OptionalDouble等类新增一个方法orElseThrow(),在没有值时抛出异常

6. 其他新特性

  • 基于 Java 的 实验性 JIT 编译器

  • 类数据共享

  • Unicode 语言标签扩展

  • 根证书

  • 基于时间(Time-Based)的版本控制模型

Java 11 新特性

1.字符串操作

String类是Java最常用的类,JDK 11增加了一系列好用的字符串处理方法

  • isBlank() 判空。

  • strip() 去除首尾空格

  • stripLeading() 去除字符串首部空格

  • stripTrailing() 去除字符串尾部空格

  • lines() 分割获取字符串流。

  • repeat() 复制字符串

    // 判断字符串是否为空白"  ".isBlank();    // true// 去除首尾空格" jay ".strip();  // "jay"// 去除首部空格 " jay ".stripLeading();   // "jay "去除字符串尾部空格" jay ".stripLeading();   // " jay"// 行数统计"a\nb\nc".lines().count();    // 3// 复制字符串"jay".repeat(3);   // "jayjayjay"

2.用于 Lambda 参数的局部变量语法

局部变量类型推断是Java 10引入的新特性,但是不能在Lambda 表达式中使用。Java 11再次创新,它允许开发者在 Lambda 表达式中使用 var 进行参数声明。

var&nbsp;map&nbsp;=&nbsp;new&nbsp;HashMap<String,&nbsp;Object>();map.put("公众号",&nbsp;"捡田螺的小男孩");map.forEach((var&nbsp;k,&nbsp;var&nbsp;v)&nbsp;->&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(k&nbsp;+&nbsp;":&nbsp;"&nbsp;+&nbsp;v);});

3.标准化HTTP Client

Java 9 引入Http Client API,Java 10对它更新,Java 11 对它进行标准化。这几个版本后,Http Client几乎被完全重写,支持HTTP/1.1和HTTP/2 ,也支持 websockets。

HttpClient&nbsp;client&nbsp;=&nbsp;HttpClient.newHttpClient();HttpRequest&nbsp;request&nbsp;=&nbsp;HttpRequest.newBuilder()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.uri(URI.create("https://github.com/whx123/JavaHome"))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.GET()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.build();//&nbsp;同步HttpResponse<String>&nbsp;response&nbsp;=&nbsp;client.send(request,&nbsp;HttpResponse.BodyHandlers.ofString());System.out.println(response.body());//&nbsp;异步client.sendAsync(request,&nbsp;HttpResponse.BodyHandlers.ofString())&nbsp;&nbsp;&nbsp;&nbsp;.thenApply(HttpResponse::body)&nbsp;&nbsp;&nbsp;&nbsp;.thenAccept(System.out::println);

4. 单个命令编译运行源代码

Java 11增强了Java 启动器,使之能够运行单一文件的Java 源代码。

  • Java 11之前,要运行一个 Java 源代码必须先编译,再运行

    // 编译javac Jay.java// 运行java Jay

  • Java 11之后,只要一个java命令就搞定

    java Jay.java

5. ZGC:可伸缩低延迟垃圾收集器

ZGC ,即 Z Garbage Collector(垃圾收集器或垃圾回收器)。它是一个可伸缩的、低延迟的垃圾收集器。
ZGC 主要为了满足如下目标进行设计:

  • GC 停顿时间不超过 10ms

  • 既能处理几百 MB 的小堆,也能处理几个 TB 的大堆

  • 应用吞吐能力不会下降超过 15%(与 G1 回收算法相比)

  • 方便在此基础上引入新的 GC 特性和利用 colord

  • 针以及 Load barriers 优化奠定基础

  • 当前只支持 Linux/x64 位平台

6.其他一些特性

  • 添加 Epsilon 垃圾收集器。

  • 支持 TLS 1.3 协议

  • 飞行记录器分析工具

  • 动态类文件常量

  • 低开销的 Heap Profiling

Java 12 新特性

1. Switch 表达式扩展(预览功能)

传统的switch语句,容易漏写break而出错,同时写法并不简洁优雅。

Java 12之前

switch&nbsp;(day)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;MONDAY:&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;FRIDAY:&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;SUNDAY:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(6);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;TUESDAY:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(7);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;THURSDAY:&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;SATURDAY:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(8);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;WEDNESDAY:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(9);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;}

JDk 12 之后,Switch表达式得到增强,能接受语句和表达式。

switch&nbsp;(day)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;MONDAY,&nbsp;FRIDAY,&nbsp;SUNDAY&nbsp;->&nbsp;System.out.println(6);&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;TUESDAY&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;->&nbsp;System.out.println(7);&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;THURSDAY,&nbsp;SATURDAY&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;->&nbsp;System.out.println(8);&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;WEDNESDAY&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;->&nbsp;System.out.println(9);}

2. 紧凑的数据格式

JDK 12 新增了NumberFormat对复杂数字的格式化

NumberFormat&nbsp;numberFormat&nbsp;=&nbsp;NumberFormat.getCompactNumberInstance(Locale.CHINA,&nbsp;NumberFormat.Style.SHORT);System.out.println(numberFormat.format(100000));//output10万

3. 字符串支持transform、indent操作

  • transform 字符串转换,可以配合函数式接口Function一起使用

    List list1 = List.of("jay", " 捡田螺的小男孩");List list2 = new ArrayList<>();list1.forEach(element ->            list2.add(element.transform(String::strip)                    .transform((e) -> "Hello," + e))    );list2.forEach(System.out::println);//输出Hello,jayHello,捡田螺的小男孩

  • indent 缩进,每行开头增加空格space和移除空格

    String result = "Java\n Python\nC".indent(3);System.out.println(result);//输出   Java    Python   C

4. Files.mismatch(Path, Path)

Java 12 新增了mismatch方法,此方法返回第一个不匹配的位置,如果没有不匹配,则返回 -1L。

public&nbsp;static&nbsp;long&nbsp;mismatch(Path&nbsp;path,&nbsp;Path&nbsp;path2)&nbsp;throws&nbsp;IOException;

代码示例:

Path&nbsp;file1&nbsp;=&nbsp;Paths.get("c:\\jay.txt");Path&nbsp;file2&nbsp;=&nbsp;Paths.get("c:\\捡田螺的小男孩.txt");try&nbsp;{&nbsp;long&nbsp;fileMismatch&nbsp;=&nbsp;Files.mismatch(file1,&nbsp;file2);&nbsp;System.out.println(fileMismatch);}&nbsp;catch&nbsp;(IOException&nbsp;e)&nbsp;{&nbsp;e.printStackTrace();}

5. Teeing Collector

Teeing Collector 是 Streams API 中引入的新的收集器实用程序,它的作用是 merge 两个 collector 的结果,API格式如下:

public&nbsp;static&nbsp;<T,&nbsp;R1,&nbsp;R2,&nbsp;R>&nbsp;&nbsp;&nbsp;&nbsp;Collector<T,&nbsp;?,&nbsp;R>&nbsp;teeing(Collector<?&nbsp;super&nbsp;T,&nbsp;?,&nbsp;R1>&nbsp;downstream1,&nbsp;&nbsp;&nbsp;&nbsp;Collector<?&nbsp;super&nbsp;T,&nbsp;?,&nbsp;R2>&nbsp;downstream2,&nbsp;&nbsp;&nbsp;&nbsp;BiFunction<?&nbsp;super&nbsp;R1,&nbsp;?&nbsp;super&nbsp;R2,&nbsp;R>&nbsp;merger)

直接看代码例子吧,如下为求学生的平均分和总分的例子

&nbsp;&nbsp;List<Student>&nbsp;studentList=&nbsp;Arrays.asList(&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;Student("jay",&nbsp;90),&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;Student("捡田螺的小男孩",&nbsp;100),&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;Student("捡表情的小男孩",&nbsp;80)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;teeingResult=studentList.stream().collect(&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Collectors.teeing(&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Collectors.averagingInt(Student::getScore),&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Collectors.summingInt(Student::getScore),&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(s1,s2)->&nbsp;s1+&nbsp;":"+&nbsp;s2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);&nbsp;System.out.println(teeingResult);&nbsp;//90:270

6.其他特性

  • 支持unicode 11(684个新字符、11个新blocks、7个新脚本)

  • JVM 常量 API (主要在新的java.lang.invoke.constant包中定义了一系列基于值的符号引用类型,能够描述每种可加载常量。)

  • Shenandoah GC(低暂停时间垃圾收集器)

  • G1 收集器提升 (可中止的混合收集集合、及时返回未使用的已分配内存)

  • 默认CDS档案

  • JMH 基准测试

Java 13 新特性

Switch 表达式扩展(引入 yield 关键字)

传统的switch:

private&nbsp;static&nbsp;String&nbsp;getText(int&nbsp;number)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;result&nbsp;=&nbsp;"";&nbsp;&nbsp;&nbsp;&nbsp;switch&nbsp;(number)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;1,&nbsp;2:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;=&nbsp;"one&nbsp;or&nbsp;two";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;3:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;=&nbsp;"three";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;4,&nbsp;5,&nbsp;6:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;=&nbsp;"four&nbsp;or&nbsp;five&nbsp;or&nbsp;six";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;=&nbsp;"unknown";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;

Java 13之后,value break 语句不再被编译,而是用 yield 来进行值返回

private&nbsp;static&nbsp;String&nbsp;getText(int&nbsp;number)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;switch&nbsp;(number)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;1,&nbsp;2:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield&nbsp;"one&nbsp;or&nbsp;two";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;3:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield&nbsp;"three";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;4,&nbsp;5,&nbsp;6:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield&nbsp;"four&nbsp;or&nbsp;five&nbsp;or&nbsp;six";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield&nbsp;"unknown";&nbsp;&nbsp;&nbsp;&nbsp;};}

2.文本块升级

Java 13之前,字符串不能够多行使用,需要通过换行转义或者换行连接符等等,反正就是好麻烦、好难维护。

String&nbsp;html&nbsp;=&nbsp;"<html>\n"&nbsp;+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;<body>\n"&nbsp;+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<p>Hello,&nbsp;捡田螺的小男孩</p>\n"&nbsp;+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;</body>\n"&nbsp;+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"</html>\n";

Java 13之后,清爽多了~

String&nbsp;html&nbsp;=&nbsp;"""&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<html>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<body>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<p>Hello,&nbsp;&nbsp;捡田螺的小男孩</p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</body>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</html>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;""";

3. SocketAPI 重构

  • 传统的Java Socket API(java.net.ServerSocket 和 java.net.Socket)依赖于SocketImpl 的内部实现

  • 在 Java 13之前,通过使用 PlainSocketImpl 作为 SocketImpl 的具体实现。

  • Java 13 中的新底层实现,引入 NioSocketImpl 的实现用以替换 SocketImpl 的 PlainSocketImpl 实现,此实现与 NIO(新 I/O)实现共享相同的内部基础结构,并且与现有的缓冲区高速缓存机制集成在一起。

一个Socket简单例子:

import&nbsp;java.io.IOException;import&nbsp;java.net.ServerSocket;import&nbsp;java.net.Socket;public&nbsp;class&nbsp;SocketAPITest&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;(ServerSocket&nbsp;serverSocket&nbsp;=&nbsp;new&nbsp;ServerSocket(8080)){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;boolean&nbsp;runFlag&nbsp;=&nbsp;true;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(runFlag){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Socket&nbsp;clientSocket&nbsp;=&nbsp;serverSocket.accept();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//搞事情&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(IOException&nbsp;e)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;}}

运行以上的实例,看下是否有以下关键词输出~

[class,load]&nbsp;sun.nio.ch.NioSocketImpl

4.FileSystems.newFileSystem新方法

FileSystems 类中添加了以下三种新方法,以便更容易地使用将文件内容视为文件系统的文件系统提供程序:

  • 1、newFileSystem(Path)

  • 2、newFileSystem(Path, Map)

  • 3、newFileSystem(Path, Map, ClassLoader)

5. 增强 ZGC 释放未使用内存

  • ZGC 是Java 11 中引入的最为瞩目的垃圾回收特性,是一种可伸缩、低延迟的垃圾收集器。但是实际使用中,它不能够主动将未使用的内存释放给操作系统。

  • Java 13 中对 ZGC 的改进,包括释放未使用内存给操作系统、支持最大堆大小为 16TB、JVM参数-XX:SoftMaxHeapSize 来软限制堆大小

6.其他特性

  • 动态 CDS 存档, 扩展了 Java 10 中引入的类数据共享功能, 使用CDS 存档变得更容易。

  • 文本块的字符串类新方法,如formatted(Object…args),stripIndent()等。

Java 14 新特性

1. instanceof模式匹配

instanceof 传统使用方式:

if&nbsp;(person&nbsp;instanceof&nbsp;Singer)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;Singer&nbsp;singer&nbsp;=&nbsp;(Singer)&nbsp;person;&nbsp;&nbsp;&nbsp;&nbsp;singer.sing();}&nbsp;else&nbsp;if&nbsp;(person&nbsp;instanceof&nbsp;Writer)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;Writer&nbsp;writer&nbsp;=&nbsp;(Writer)&nbsp;person;&nbsp;&nbsp;&nbsp;&nbsp;writer.write();}

Java 14 对 instanceof 进行模式匹配改进之后

if&nbsp;(person&nbsp;instanceof&nbsp;Singer&nbsp;singer)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;singer.sing();}&nbsp;else&nbsp;if&nbsp;(person&nbsp;instanceof&nbsp;Writer&nbsp;writer)&nbsp;{&nbsp;&nbsp;&nbsp;writer.write();}

2.Record 类型(预览功能)

Java 14将Record 类型作为预览特性而引入,有点类似于Lombok 的@Data注解,看个例子吧:

public&nbsp;record&nbsp;Person(String&nbsp;name,&nbsp;int&nbsp;age)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;String&nbsp;address;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;String&nbsp;getName()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;name;&nbsp;&nbsp;&nbsp;&nbsp;}}

反编译结果:

public&nbsp;final&nbsp;class&nbsp;Person&nbsp;extends&nbsp;java.lang.Record&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;final&nbsp;java.lang.String&nbsp;name;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;final&nbsp;java.lang.String&nbsp;age;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Person(java.lang.String&nbsp;name,&nbsp;java.lang.String&nbsp;age)&nbsp;{&nbsp;/*&nbsp;compiled&nbsp;code&nbsp;*/&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;java.lang.String&nbsp;getName()&nbsp;{&nbsp;/*&nbsp;compiled&nbsp;code&nbsp;*/&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;java.lang.String&nbsp;toString()&nbsp;{&nbsp;/*&nbsp;compiled&nbsp;code&nbsp;*/&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;final&nbsp;int&nbsp;hashCode()&nbsp;{&nbsp;/*&nbsp;compiled&nbsp;code&nbsp;*/&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;final&nbsp;boolean&nbsp;equals(java.lang.Object&nbsp;o)&nbsp;{&nbsp;/*&nbsp;compiled&nbsp;code&nbsp;*/&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;java.lang.String&nbsp;name()&nbsp;{&nbsp;/*&nbsp;compiled&nbsp;code&nbsp;*/&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;java.lang.String&nbsp;age()&nbsp;{&nbsp;/*&nbsp;compiled&nbsp;code&nbsp;*/&nbsp;}}

可以发现,当用 Record 来声明一个类时,该类将自动拥有下面特征:

  • 构造方法

  • hashCode() 方法

  • euqals() 方法

  • toString() 方法

  • 类对象被final 关键字修饰,不能被继承。

3. Switch 表达式-标准化

switch 表达式在之前的 Java 12 和 Java 13 中都是处于预览阶段,终于在 Java 14 标准化,成为稳定版本。

  • Java 12 为switch 表达式引入Lambda 语法

  • Java 13 使用yield代替 break 关键字来返回表达式的返回值。

    String result = switch (day) {    case "M", "W", "F" -> "MWF";    case "T", "TH", "S" -> "TTS";    default -> {        if (day.isEmpty()) {            yield "Please insert a valid day.";        } else {            yield "Looks like a Sunday.";        }    }};System.out.println(result);

4. 改进 NullPointerExceptions提示信息

Java 14 之前:

String&nbsp;name&nbsp;=&nbsp;song.getSinger().getSingerName()&nbsp;//堆栈信息Exception&nbsp;in&nbsp;thread&nbsp;"main"&nbsp;java.lang.NullPointerException&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;NullPointerExample.main(NullPointerTest.java:6)

Java 14,通过引入JVM 参数-XX:+ShowCodeDetailsInExceptionMessages,可以在空指针异常中获取更为详细的调用信息。

Exception&nbsp;in&nbsp;thread&nbsp;"main"&nbsp;java.lang.NullPointerException:&nbsp;Cannot&nbsp;invoke&nbsp;"Singer.getSingerName()"&nbsp;because&nbsp;the&nbsp;return&nbsp;value&nbsp;of&nbsp;"rainRow.getSinger()"&nbsp;is&nbsp;null&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;NullPointerExample.main(NullPointerTest.java:6)

5. 其他特性

  • G1 的 NUMA 可识别内存分配

  • 删除 CMS 垃圾回收器

  • GC 支持 MacOS 和 Windows 系统

Java 15 新特性


1.EdDSA 数字签名算法

  • 使用 Edwards-Curve 数字签名算法(EdDSA)实现加密签名。

  • 与其它签名方案相比,EdDSA 具有更高的安全性和性能。

  • 得到许多其它加密库(如 OpenSSL、BoringSSL)的支持。

2.Sealed Classes(封闭类,预览)

封闭类,可以是封闭类、封闭接口,防止其他类或接口扩展或实现它们。

public&nbsp;abstract&nbsp;sealed&nbsp;class&nbsp;Singer&nbsp;&nbsp;&nbsp;&nbsp;permits&nbsp;Jay,&nbsp;Eason{&nbsp;&nbsp;&nbsp;&nbsp;...}

类Singer被sealed 修饰,是封闭类,只能被2个指定子类(Jay, Eason)继承。

3. Hidden Classes(隐藏类)

  • 隐藏类天生为框架设计的。

  • 隐藏类只能通过反射访问,不能直接被其他类的字节码。

4. Remove the Nashorn JavaScript Engine

  • Nashorn太难维护了,移除 Nashorn JavaScript引擎成为一种必然

  • 其实早在JDK 11 中就已经被标记为 deprecated 了。

5.Reimplement the Legacy DatagramSocket API(重新实现DatagramSocket API)

  • 重新实现老的DatagramSocket API

  • 更改java.net.DatagramSocket 和 java.net.MulticastSocket 为更加简单、现代化的底层实现。

6.其他

  • Disable and Deprecate Biased Locking(准备禁用偏向锁)

  • instanceof 自动匹配模式(预览)

  • ZGC,一个可伸缩、低延迟的垃圾回收器。(转正)

  • Text Blocks,文本功能转正(JDK 13和14预览,14终于转正)

  • Remove the Solaris and SPARC Ports(删除 Solaris 和 SPARC 端口)

  • 外部存储器访问 API(允许Java 应用程序安全有效地访问 Java 堆之外的外部内存。)

  • Record类型二次预览(在Java 14就预览过啦)

参考与感谢

个人公众号

Reference

[1]

JDK6 新特性: https://blog.csdn.net/weixin_40926603/article/details/84970283

[2]

Java 7的新功能: https://stackoverflow.com/questions/213958/new-features-in-java-7

[3]

Java 9 新特性概述: https://developer.ibm.com/zh/articles/the-new-features-of-Java-9/

[4]

Java 9 新特性: https://www.runoob.com/java/java9-new-features.html

[5]

Java 10 新特性介绍: https://developer.ibm.com/zh/technologies/java/articles/the-new-features-of-java-10/

[6]

Java 11 新特性介绍: https://developer.ibm.com/zh/technologies/java/articles/the-new-features-of-java-11/

[7]

Java 13 新特性概述: https://developer.ibm.com/zh/technologies/java/articles/the-new-features-of-java-13/

[8]

Java 14 新特性概述: https://developer.ibm.com/zh/technologies/java/articles/the-new-features-of-java-14/