本文视频源:
Youtube:https://youtu.be/Trw_jqRWKlc
Youku:https://v.youku.com/v_show/id_XNDA4NTI1NjA4OA==.html

虽然现在很少使用 Java 进行开发,但是仍然时不时的关注着它的动态,最近发现 Java 11 发布了,并且带来了很多新特性,关键它是 Java8 以后又一长期维护版本,可以在生产环境使用,这又增加了我关注它的动力,今天先介绍一个新特性:java 命令可以直接运行单文件。

运行单文件

举个例子,写一个类文件 HelloWorld.java

1
2
3
4
5
public class HelloWorld{
public static void main(String args[]){
System.out.println("Hello World");
}
}

以前需要这样运行

1
2
3
$ javac HelloWorld.java
$ java HelloWorld
Hello World

现在只需要这样

1
2
$ java HelloWorld.java
Hello World

嗯,Python 你闭嘴,还有你 Go。呵呵

为什么?

其他介绍 Java 11 新特性的文章,到这里也就点到为止了,但是我总觉得这事不是这么简单。

Java 为什么要这么做,真的是想用 java 取代 javac 吗,很显然不是,你可以做些实验,再多文件打包运行时,我们仍然需要 javac 来进行编译,也就是说 java 有其他的用途。

这几年 Java 一直在追赶脚本语言(如:Python、NodeJS)的脚步,比如 lambda 函数、服务器组件、轻量级的 JSON 组件,还有 Java 11 才增加的 Http Client Api。这无疑都在想让自己往脚本语言方向发展,并且现在已经越来越像了。

我们来做一些对比,拿入门的打印 Hello World 来举例,在 Python 中我们这样

1
2
3
#!/usr/bin/env python
print("Hello World")
# python Hello.py

Java 中这样

1
2
3
4
5
6
7
8
public class Hello{
public static void main(String args[]){
System.out.println("Hello World");
}
}

// javac Hello.java
// java Hello

好了,先不要笑,也先不要管 public, static, void 是个什么东西,Java 一直都很臃肿,你又不是不知道,至少现在它已经把 javac Hello.java 干掉了。

脚本运行

脚本语言的特性是可以在文件第一行以 #! 开头,并指定运行命令,然后可以直接在终端中运行,比如 Python

1
2
3
$ chmod +x hello.py
$ ./hello.py
Hello World

那 Java 呢,因为本身的特性,.java 后缀的文件不运行出现 #!,所以我们首先需要改一下名字,听到这里,你是不是已经开始心跳加速了。

1
2
$ mv Hello.java hello.sh
$ chmod +x hello.sh

然后修改文件

1
2
3
4
5
6
7
#!/usr/bin/env java --source 11

public class HelloWorld{
public static void main(String args[]){
System.out.println("Hello World");
}
}

然后执行该文件

1
2
$ ./hello.sh
Hello World

啊!我看到了什么,这真的是 Java 吗?

OK,现在为止,已经挑战了我的认知,这有悖于我们多年以来的认知。

当然文件还可以使用 java 运行

1
$ java -Dtrace=true --source 11 hello.sh

同一个文件多个公共类

我们刚才已经知道了两个有悖“常识”的知识点Java 可以作为脚本运行文件名可以和第一个公共类名不相同

看到第二点,我有个大胆的想法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class HelloWorld{
public static void main(String args[]){
System.out.println("Hello World");
User u = new User();
u.id = 1;
System.out.println(u.id);

}
}
public class User{
public int id;
public static void main(String args[]){
System.out.println("User");
}
}

这样的写法,如果放在几个月以前,是会被别人破口大骂的,因为只学过几天的菜鸟也知道,一个类中不能出现两个公共类,它会报这个错误。

1
error: class User is public, should be declared in a file named User.java

你把 User 类前边的 public 去掉就行了,那在 Java 11 中呢

1
2
3
$ java hello.java
Hello World
1

现在 Java 11 会正常运行该文件,并直接第一个公共类的 main 函数。

好吧,这确实颠覆了 20 几年来 Java 固守的东西,还有对于新手来说,这真的是一个痛苦的过程。

最后我们再来总结一下,在单文件运行的情况下 Java 11 做了哪些改变

  • Java 11 可以将单文件作为脚本来运行
  • 文件名不在需要跟第一个公共类名相同
  • 同一个文件下可以存在多个公共类
  • 单文件下不再需要 class 文件

参考:

03-16 22:24