JDK9-JDK17值得用的功能

1,151 阅读1分钟

现在已经干到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应用程序打包到特定平台中。

  1. 编写Java文件
public class Test{
	public static void main(String args[]){
		System.out.println("hello");
	}
}
  1. 编译&打包
$ javac Test.java 
$ jar cvf hello.jar Test.class 
  1. 平台打包
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
  1. 运行
$ /opt/test/bin/Test 
hello

JDK17 无