这是Java脚本吗?
對於正在尋找JavaScript相關文章的大家,很抱歉本內容可能無法為您提供幫助,請按瀏覽器的返回按鈕。
此外,這是一個相當嚴肅的 Java 笑話,因此我們請諸位Java初學者不要當真對待。
从OpenJDK 11 开始,可以直接运行Java文件。
最近我刚刚知道,在OpenJDK 11中引入了JEP 330:启动单文件源代码程序,这样就可以在不使用javac等编译的情况下运行单个Java文件的程序。
-
- ソース・ファイル・モードで単一ファイルのソース・コードのプログラムを起動する方法
-
- JEP-330 Single-FIle Source-Code Programs って何? Java ファイルが java コマンドで実行できるってホント?! shebang でどう指定するの?調べてみた!
- 【Modern Java】JEP 330 Launch Single-File Source-Code Programs
在Shell中,我们使用各种脚本,对吧?在执行带有可执行属性的脚本文件时,Unix系统根据shebang的指定来解释该脚本的程序。像#!/bin/sh或#!/bin/bash这样指定了Shell的脚本被称为”Shell脚本”,而像#!/usr/bin/env perl这样指定了脚本语言的脚本被称为”Perl脚本”。那么,如果指定了#!/usr/bin/env java,这个脚本就被称为”Java脚本”,不是吗?
我在 macOS 上安装了 OpenJDK 15 进行了尝试,但幸好在之前的博客文章中,mike_neck 已经确定了可能出现问题的地方,所以我很顺利地执行了。这看起来很有趣。
Java脚本的文件格式
虽然我还没有完全掌握规范,但我首先会认真查看JEP 330。即使参考了Oracle的文档,最终还是写道要查看JEP 330。
我认为通常脚本都以 shebang 开头,所以在本文中,我将 JEP 330 中称为 shebang 文件的内容称为 Java 脚本。
#!/path/to/java –源代码版本
在JEP 330中提到,可以在第一行中编写如上所述的shebang。然而,我认为通过使用#!/usr/bin/env java –source 11这样的env方式可以提高可移植性。
在一个shebang文件中,前两个字节必须是0x23 0x21。
她的 shebang 必须是由0x23 0x21 字节序列组成。如果想要用 Java 编写,也必须将最开始的两个字节像 UTF-8 那样写入。
shebang 文件的名称不符合 Java 源文件的标准命名规范。
这基本上意思就是,不管是 public class Hello 还是 Hello.java,文件名可以是 hello 或 foobar 等其他名称。虽然不确定是否有意为之,但正如下面的例子一样,即使一个文件中有多个 public class,也能正常运行!
当启动器读取源文件时,如果文件不是Java源文件(即,其文件名不以.java结尾),并且如果第一行以#!开头,则在确定要传递给编译器的源代码时,将忽略该行的内容,直到第一个换行符之前的内容。
Shebang 行不会被传递给编译器,会被忽略。Java 的行注释不是用 #,而是用 //,通过这个技巧使其能够正常工作。
文件名以 .java 结尾时会被认为是 Java 源文件,在这部分会出现编译错误。只要不是 .java 结尾,例如 foobar.js 或 foobar.sh,都可以正常运行。可恼的是,这是无法通过扩展名来表示使用的语言的特性。如果其他人打开这个文件时,会想着”这个脚本怎么有bug啊?”然后竟然是一个 Java 程序!我相信他们一定会大吃一惊的。
剩下的就是普通的Java程序。main方法中的String[] args会完成好工作。
1. 我试着创建一个Shell命令。
作为一个例子,我创建了一个命令,它以x坐标和y坐标作为参数,并返回它们所在的第几象限。
我們試圖通過在程式腳本中宣告使用機會很少的 var 來展現腳本語言的特色。
#!/usr/bin/env java --source 11
public class Quadrant {
public static void main(String[] args) {
if (args.length == 2) {
try {
var x = Double.parseDouble(args[0]);
var y = Double.parseDouble(args[1]);
String s;
switch(Coordinate2D.quadrantOf(x, y)) {
case 1: s = "1st"; break;
case 2: s = "2nd"; break;
case 3: s = "3rd"; break;
case 4: s = "4th"; break;
default: throw new IllegalStateException();
};
System.out.println("The quadrant of (" + x + ", " + y + ") is the " + s);
System.exit(0);
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
// show usage and exit abnormally
System.err.println("usage: quadrant x y");
System.err.println(" where x and y are non-zero coordinate values in double");
System.exit(1);
}
}
public class Coordinate2D {
public static int quadrantOf(double x, double y) {
if (x > 0.0 && y > 0.0)
return 1;
else if (x < 0.0 && y > 0.0)
return 2;
else if (x < 0.0 && y < 0.0)
return 3;
else if (x > 0.0 && y < 0.0)
return 4;
else
throw new IllegalArgumentException("point must not be on any axis");
}
}
最近我多数使用IntelliJ,但这次为了体验写脚本的感觉,我使用了vim。switch语句的密集描述是因为没有使用格式化工具。我喜欢switch表达式,因为它不容易出错,但为了使脚本具有高可移植性,我选择了Java 11,并不情愿地用switch语句编写了脚本。
也许是因为我对Java很熟悉,所以写错误处理感觉很容易。只有我在Shell脚本中处理错误总是匆忙马虎吗?
% chmod +x quadrant
% ./quadrant
usage: quadrant x y
where x and y are non-zero coordinate values in double
% echo $?
1
% ./quadrant 2 -3
The quadrant of (2.0, -3.0) is the 4th
% echo $?
0
你真的不会觉得这是用Java编写的,只看到这些东西时候,实际上是这样。
尝试在 Java 脚本中执行 JavaScript
下一步,我们将使用令人怀念的 Rhino,在Java脚本中执行JavaScript。
https://github.com/mozilla/rhino 的 “JavaScript in Java” 这个信息恰好符合我的心情。
说实话,在 JDK 自带的时候我从未使用过 Rhino。今天是我第一次使用它,但官方文档让我感到困惑…。不过,我只是想通过 Java 脚本执行 JavaScript,仅此而已。
经过一番适当的搜索,我找到了一个使用Rhino从Java调用外部JavaScript文件的简单示例,这个示例很容易理解。所以我将它简化并将其转换为执行JavaScript的Java脚本。
#!/usr/bin/env java --source 11 -cp rhino-1.7.13.jar
import org.mozilla.javascript.Context;
class JavaScriptInJavaScript {
public static void main(String[] args) throws Exception {
var ctx = Context.enter();
var obj = ctx.evaluateString(
ctx.initStandardObjects(),
"'Java' + 'Script'",
"<Java script>",
1,
null
);
System.out.println(obj + " in a Java script!");
}
}
我使用 Shebang 在类路径中指定了Rhino的jar包。
% curl -OsSL https://github.com/mozilla/rhino/releases/download/Rhino1_7_13_Release/rhino-1.7.13.jar
% chmod +x javascript_in_java_script
% ./javascript_in_java_script
JavaScript in a Java script!
我可以从Java脚本中执行JavaScript并得到’Java’ + ‘Script’这个结果。
最后
你觉得怎么样?崩坏JavaScript概念的过程有点有趣。
我会全力以赴,认真整理。
Shell脚本常常无法理解各种B Shell之间微小的行为差异,往往只能在bash和特定的Linux发行版上运行。虽然可以通过使用脚本语言来避免这个问题,但另一方面会经常面临无法使用perl或python3的环境的缺点。
我认为,在以Java 11或更高版本开发的项目中,有能力运行Java脚本的JDK的两个Java命令具有以下特点:静态类型、便于确保Java程序员的可移植性等。因此,我认为它们是作为脚本语言的选择的一个值得考虑的候选项。
我可能還沒有足夠的勇氣在實務中使用它,但對於讀者們來說,挑戰一下「一次編寫,到處運行」的Java腳本也是很有趣的吧。期待您的報告。
和你一起使用JavaScript,立刻运行。
请使用#!/usr/bin/env node指定这是一个“JavaScript脚本”。 我可以接受异议。 ↩
GraalVM不受支持。 ↩
仅限于解释Shebang的环境。 ↩
请使用您喜欢的文件扩展名。 ↩