现在已经干到JDK17了,索性今天看看看这些版本中都有哪些比较有用的特性。
下面只介绍各个版本中一条特性,其他特性有的是关于JVM优化的,也看不懂,有的对写程序也没多大帮助。
JDK 9、JShell
Java Shell能使我们从shell中执行Java代码并立即显示输出,也可以使用代码执行,以下是我在JDK17下执行的jshell命令,所以会输出版本 17.0.1,但是JShell从9开始就有的。
hxl@hxl-ThinkPad-E580:~$ jshell
| 欢迎使用 JShell -- 版本 17.0.1
| 要大致了解该版本, 请键入: /help intro
jshell>
jshell> System.out.println("a");
a
jshell> int a=10;
a ==> 10
jshell> int b=10;
b ==> 10
jshell> System.out.println(a+b);
20
默认情况下,Jshell 可以使用以下包,我们不必导入它们。可以使用/imports命令查看。
jshell> /imports
| import java.io.*
| import java.math.*
| import java.net.*
| import java.nio.file.*
| import java.util.*
| import java.util.concurrent.*
| import java.util.function.*
| import java.util.prefs.*
| import java.util.regex.*
| import java.util.stream.*
以下是从代码中执行。
fun main() {
var jShell = JShell.create()
jShell.eval("int a=10;")
jShell.eval("int b=10;")
var eval = jShell.eval("int c=a+b;")
println(eval[0].value())
}
JDK10、- 局部变量类型推断
在JDK10中可以使用var标识非空并初始化后声明局部变量,比如下面代码。
var url = new URL("http://www.baidu.com");
var connection = url.openConnection();
var bufferedReader = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
var不是关键字,意味着var可以用作变量、方法或包名称。但是,var用作类或接口名称的代码会受到影响,比如下面这样,但是也没有多少人会这样写吧。
var var = new URL("http://www.baidu.com");
var connection = var.openConnection();
var bufferedReader = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
JDK11、HttpClient
HttpClient用来发送htp请求,不需要额外的框架,以下是同步请求,
fun main() {
var httpClient = HttpClient.newHttpClient()
var httpRequest = HttpRequest.newBuilder(URL("http://www.baidu.com").toURI()).build()
var httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString())
println(httpResponse.body())
}
下面是异步请求,异步请求返回的是一个CompletableFuture,更好的处理并发请求。
fun main() {
var httpClient = HttpClient.newHttpClient()
var httpRequest = HttpRequest.newBuilder(URL("http://www.baidu.com").toURI()).build()
var async = httpClient.sendAsync(httpRequest, HttpResponse.BodyHandlers.ofString())
println(async.get().body())
}
还可以下载文件
fun main() {
var httpClient = HttpClient.newHttpClient()
var httpRequest = HttpRequest.newBuilder(URL("https://img2.baidu.com/it/u=1239331460,2461813426&fm=253&fmt=auto&app=138&f=PNG?w=634&h=500").toURI()).build()
httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofFile(Paths.get("/home/HouXinLin/test.png")))
}
JDK12、无
JDK13、 文本块
以前是这样的。
String html = "<html>\n" +
" <body>\n" +
" <p>Hello, world</p>\n" +
" </body>\n" +
"</html>\n";
JDK13是这样的。
String html = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";
JDK14、record instanceof
以前是这样的。
class User{
private String name;
private int ags;
public User(String name, int ags) {
this.name = name;
this.ags = ags;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAgs() {
return ags;
}
public void setAgs(int ags) {
this.ags = ags;
}
}
现在是这样的。
record User(String name, int age) { }
public class Main {
public static void main(String[] args) throws IOException {
User user = new User("张三", 14);
System.out.println(user.age());
}
}
以前判断对象关系是这样的。
if (obj instanceof String) {
String str = (String) obj;
str.xxx
}else{
}
现在是这样的。
String target = new String("str");
Object obj = target;
if ((obj instanceof String s)) {
System.out.println(s.length());
} else {
}
JDK15、 Sealed Class
Sealed用来标识那些类是可以继承自己的,并且目标也会被强制加有final标识,下面Dog和Cat是被允许的,但是Monkey继承的时候就会报错。
sealed class Animal
permits Dog, Cat {
}
final class Dog extends Animal {
}
final class Cat extends Animal {
}
class Monkey extends Animal{
}
并且JDK15弃用了偏向锁。
JDK16、Jpackage
Jpackage 在JDK14中就已经出来了,但是根据文档所说,在JDK16中才正式进入生产环境。他是一个打包工具,用于将Java应用程序打包到特定平台中。
- 编写Java文件
public class Test{
public static void main(String args[]){
System.out.println("hello");
}
}
- 编译&打包
$ javac Test.java
$ jar cvf hello.jar Test.class
- 平台打包
jpackage -i . -n Test --main-jar hello.jar --main-class Test
我使用的环境是Ubuntu,所以会打包成一个.deb文件,使用以下命令安装。
sudo dpkg -i test_1.0-1_amd64.deb
默认安装目录在
- Linux 是
/opt - macOS 是
/Applications - windows是
C:\Program Files
- 运行
$ /opt/test/bin/Test
hello