JEP 330 –启动单文件源代码程序是即将发布的JDK 11(18.9)发行版中令人兴奋的功能之一。 此功能允许直接使用java
解释器执行Java源代码。 源代码在内存中编译,然后由解释器执行。 限制是必须在同一文件中定义所有类。
对于刚开始学习Java并想尝试简单程序的人来说,此功能特别有用。 该功能与jshell
将是任何初学者学习该语言的绝佳工具集。 不仅它们,而且专业人员也可以使用这些工具来探索新的语言更改或尝试未知的API。
在本文中,我将不详细介绍如何实现此功能,而是将通过尝试不同的示例来专注于使用此功能。 让我们从最简单的示例开始,像往常一样,Hello World!
最简单的例子
下面的代码保存在文件HelloWorld.java
public class HelloWorld{public static void main(String[] args){System.out.println("Hello World!!!");}
}
我将运行上面的代码,如下所示:
PS G:\samples\java11\single-file> java HelloWorld.java
Hello World!!!
在上面的示例中,只有一个类,并且包含main
方法。 使用java
执行代码时,我们需要将以.java
扩展名结尾的文件的名称传递给它。 如果文件名不以.java
扩展名结尾,那么我们必须使用--source
选项,如我们在下一个示例中看到的那样。
带有命令行参数
让我们增强Hello Worl程序,为每个人创建个性化的问候:
public class Greeting{public static void main(String[] args){if ( args == null || args.length < 1 ){System.err.println("Name required");System.exit(1);}System.out.println(String.format("Hello %s!!", args[0]));}
}
让我们将上面的代码存储在名为HelloGreeting.java
的文件中。 请注意,文件名与公共类的名称不匹配。 让我们使用以下代码运行上面的代码:
PS G:\samples\java11\single-file> java HelloGreeting.Java sana
Hello sana!!
在要执行的文件名之后提供给代码的任何参数。 让我们将HelloGreeting.java
重命名为greeting
然后尝试使用相同的方法执行:
PS G:\samples\java11\single-file> java greeting sana
Error: Could not find or load main class greeting
Caused by: java.lang.ClassNotFoundException: greeting
您可以看到,在没有.java
的情况下,解释器正在通过提供的名称作为参数来搜索编译的类。 在这种情况下,我们需要使用--source
选项,如下所示:
PS G:\samples\java11\single-file> java --source 11 greeting sana
Hello sana!!
让我向您展示当使用--source
选项时,为JDK 10编写的代码如何不适用于JDK 9:
public class Java10Compatible{public static void main(String[] args){var message = "Hello world";System.out.println(message);}
}
让我们对JDK 10和JDK 9执行以上操作,如下所示:
PS G:\samples\java11\single-file> java --source 10 Java10Compatible.java
Hello world
PS G:\samples\java11\single-file> java --source 9 Java10Compatible.java
.\Java10Compatible.java:3: error: cannot find symbolvar message = "Hello world";^symbol: class varlocation: class Java10Compatible
1 error
error: compilation failed
单个文件中包含多个类
如前所述,此功能支持驻留在单个文件中的运行代码,因此文件中的类数没有限制。 让我们看一个包含两个类的示例代码:
public class SimpleInterest{public static void main(String[] args){if ( args == null || args.length < 3 ){System.err.println("Three arguments required: principal, rate, period");System.exit(1);}int principal = Integer.parseInt(args[0]);int rate = Integer.parseInt(args[1]);int period = Integer.parseInt(args[2]);double interest = Maths.simpleInterest(principal, rate, period);System.out.print("Simple Interest is: " + interest);}
}public class Maths{public static double simpleInterest(int principal, int rate, int period){return ( principal * rate * period * 1.0 ) / 100;}
}
让我们运行这个:
PS G:\samples\java11\single-file> java .\SimpleInterest.java 1000 2 10
Simple Interest is: 200.0
对于定义了多个类的文件,第一类应包含main方法,并且在内存中编译后的解释器将使用第一类来启动执行。
使用模块
使用选项--add-modules=ALL-DEFAULT
在内存中编译的代码作为未命名模块的一部分运行。 这使代码可以使用不同的模块,而无需使用module-info.java
显式声明依赖关系。
让我们看一下使用新的HTTP客户端API进行HTTP调用的代码。 这些在Java 9中作为孵化器功能引入的API已从孵化器移至java.net.http
模块。 示例代码为:
import java.net.http.*;
import java.net.http.HttpResponse.BodyHandlers;
import java.net.*;
import java.io.IOException;public class ExternalModuleDepSample{public static void main(String[] args) throws Exception{HttpClient client = HttpClient.newBuilder().build();HttpRequest request = HttpRequest.newBuilder().GET().uri(URI.create("https://reqres.in/api/users")).build();HttpResponse<String> response = client.send(request, BodyHandlers.ofString());System.out.println(response.statusCode());System.out.println(response.body()); }
}
我们可以通过发出以下命令来运行以上代码:
PS G:\samples\java11\single-file>java ExternalModuleDepSample.java
200
{"page":1,"per_page":3,"total":12,"total_pages":4,
"data":[{"id":1,"first_name":"George","last_name":"Bluth",
"avatar":"https://s3.amazonaws.com/uifaces/faces/twitter/calebogden/128.jpg"},
{"id":2,"first_name":"Janet","last_name":"Weaver",
"avatar":"https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg"},
{"id":3,"first_name":"Emma","last_name":"Wong",
"avatar":"https://s3.amazonaws.com/uifaces/faces/twitter/olegpogodaev/128.jpg"}]}
这使我们能够快速测试不同模块中的新功能,而无需创建模块, module-info
文件等。
Shebang文件
在本节中,我们将研究创建shebang文件。 Shebang文件是通过使用语法#!/path/to/executable
作为#!/path/to/executable
的第一行提供执行程序,可以直接在Unix系统上执行的那些文件。
让我们创建一个shebang文件:
#!/g/jdk-11/bin/java --source 11public class SimpleInterest{public static void main(String[] args){if ( args == null || args.length < 3 ){System.err.println("Three arguments required: principal, rate, period");System.exit(1);}int principal = Integer.parseInt(args[0]);int rate = Integer.parseInt(args[1]);int period = Integer.parseInt(args[2]);double interest = Maths.simpleInterest(principal, rate, period);System.out.print("Simple Interest is: " + interest);}
}public class Maths{public static double simpleInterest(int principal, int rate, int period){if ( rate > 100 ){System.err.println("Rate of interest should be <= 100. But given values is " + rate);System.exit(1);}return ( principal * rate * period * 1.0 ) / 100;}
}
如果文件名不遵循标准的Java文件名命名约定,则使用shebang中的source选项。 在我们的例子中,我们将上面的代码保存在一个名为simpleInterest
的文件中,可以这样运行:
sanaulla@Sana-Laptop /g/samples/java11/single-file (master)
$ ./simpleInterest 1000 20 2
Simple Interest is: 400.0
在Windows机器上,我使用了git
安装随附的bash shell。 还有其他多种方式,例如Cygwin,Windows 10 Ubuntu支持等。
源代码可以在这里找到。
翻译自: https://www.javacodegeeks.com/2018/07/single-file-source-code-programs-jdk-11.html