JEP 330 — Запуск однофайловых программ с исходным кодом — одна из захватывающих функций в готовящемся выпуске JDK 11 (18.9). Эта функция позволяет выполнять исходный код Java непосредственно с помощью интерпретатора java
. Исходный код компилируется в памяти и затем исполняется интерпретатором. Ограничение состоит в том, что все классы должны быть определены в одном файле.
Эта функция особенно полезна для тех, кто начинает изучать Java и хочет попробовать простые программы. Эта функция вместе с jshell
станет jshell
инструментов для любого новичка в изучении языка. Не только они, но и профессионалы могут также использовать эти инструменты для изучения новых языковых изменений или опробовать неизвестный API.
В этом посте я не буду вдаваться в подробности того, как реализована эта функция, вместо этого я сосредоточусь на использовании этой функции, пробуя различные образцы. Начнем с самого простого примера, как обычно, Hello World!
Простейший пример
Приведенный ниже код сохраняется в файле HelloWorld.java
1
2
3
4
5
|
public class HelloWorld{ public static void main(String[] args){ System.out.println( "Hello World!!!" ); } } |
Я выполню приведенный выше код, как показано ниже:
1
2
|
PS G:\samples\java11\single-file> java HelloWorld.java Hello World!!! |
В приведенном выше примере есть только один класс, и он содержит метод main
. При выполнении кода с использованием java
мы должны передать ему имя файла, заканчивающееся расширением .java
. Если имя файла не заканчивается расширением .java
тогда мы должны использовать опцию --source
как мы увидим в следующем примере.
С аргументами командной строки
Давайте расширим программу Hello Worl, чтобы создать индивидуальное приветствие для каждого человека:
1
2
3
4
5
6
7
8
9
|
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
. Обратите внимание, что имя файла не совпадает с именем открытого класса. Давайте запустим приведенный выше код, используя:
1
2
|
PS G:\samples\java11\single-file> java HelloGreeting.Java sana Hello sana!! |
Любые аргументы, которые будут переданы в код, как указано после имени исполняемого файла. Давайте переименуем HelloGreeting.java
в просто greeting
и попробуем выполнить, используя тот же подход:
1
2
3
|
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
как показано ниже:
1
2
|
PS G:\samples\java11\single-file> java --source 11 greeting sana Hello sana!! |
Позвольте мне показать вам, как код, написанный для JDK 10, не будет работать для JDK 9, когда мы используем опцию --source
:
1
2
3
4
5
6
|
public class Java10Compatible{ public static void main(String[] args){ var message = "Hello world" ; System.out.println(message); } } |
Давайте выполним вышеуказанное для JDK 10 и JDK 9, как показано ниже:
01
02
03
04
05
06
07
08
09
10
|
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 symbol var message = "Hello world" ; ^ symbol: class var location: class Java10Compatible 1 error error: compilation failed |
Несколько классов в одном файле
Как я упоминал ранее, эта функция поддерживает запуск кода, который находится в одном файле, нет ограничений на количество классов в файле. Давайте посмотрим на пример кода, который содержит два класса:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
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 ; } } |
Давайте запустим это:
1
2
|
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 Client. Эти API, которые были представлены в Java 9 в качестве функции инкубатора, были перемещены из инкубатора в модуль java.net.http
. Пример кода:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
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() .build(); HttpResponse<String> response = client.send(request, BodyHandlers.ofString()); System.out.println(response.statusCode()); System.out.println(response.body()); } } |
Мы можем запустить приведенный выше код, выполнив следующую команду:
1
2
3
4
5
6
7
8
9
|
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" , { "id" : 2 , "first_name" : "Janet" , "last_name" : "Weaver" , { "id" : 3 , "first_name" : "Emma" , "last_name" : "Wong" , |
Это позволяет нам быстро тестировать новые функции в разных модулях без необходимости создавать модули, файлы module-info
модулях и так далее.
Шебанг файлы
В этом разделе мы рассмотрим создание файлов shebang. Файлы Shebang — это те файлы, которые могут быть выполнены непосредственно в системах Unix, предоставив исполнителю синтаксис #!/path/to/executable
в качестве первой строки файла.
Давайте создадим файл shebang:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
#!/g/jdk- 11 /bin/java --source 11 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){ 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. В нашем случае мы сохранили приведенный выше код в файле с именем simpleInterest
и мы можем запустить его так:
1
2
3
|
sanaulla @Sana -Laptop /g/samples/java11/single-file (master) $ ./simpleInterest 1000 20 2 Simple Interest is: 400.0 |
На компьютерах с Windows я использовал оболочку bash, которая поставляется с установкой git
. Есть несколько других способов, таких как Cygwin, поддержка Windows 10 Ubuntu и так далее.
Исходный код для этого можно найти здесь .
Опубликовано на Java Code Geeks с разрешения Мохамеда Санауллы, партнера нашей программы JCG . См. Оригинальную статью здесь: Запустите однофайловые программы с исходным кодом в JDK 11
Мнения, высказанные участниками Java Code Geeks, являются их собственными. |