Введение в обработку исключений
Последнее обновление: 30.10.2015
Нередко в процессе выполнения программы могут возникать ошибки, при том необязательно по вине разработчика. Некоторые из них трудно
предусмотреть или предвидеть, а иногда и вовсе невозможно. Так, например, может неожиданно оборваться сетевое подключение при передаче файла.
Подобные ситуации называются исключениями.
В языке Java предусмотрены специальные средства для обработки подобных ситуаций. Одним из таких средств является конструкция try…catch…finally.
При возникновении исключения в блоке try управление переходит в блок catch, который может обработать
данное исключение. Если такого блока не найдено, то пользователю отображается сообщение о необработанном исключении, а дальнейшее выполнение
программы останавливается. И чтобы подобной остановки не произошло, и надо использовать блок try..catch. Например:
int[] numbers = new int; numbers=45; System.out.println(numbers);
Так как у нас массив numbers может содержать только 3 элемента, то при выполнении инструкции консоль отобразит
исключение, и выполнение программы будет завершено. Теперь попробуем обработать это исключение:
try{ int[] numbers = new int; numbers=45; System.out.println(numbers); } catch(Exception ex){ ex.printStackTrace(); } System.out.println("Программа завершена");
При использовании блока try…catch вначале выполняются все инструкции между операторами try и catch.
Если в блоке try вдруг возникает исключение, то обычный порядок выполнения останавливается и переходит к инструкции сatch.
Поэтому когда выполнение программы дойдет до строки , программа остановится и перейдет к блоку
Выражение catch имеет следующий синтаксис: .
В данном случае объявляется переменная , которая имеет тип . Но если возникшее исключение не
является исключением типа, указанного в инструкции сatch, то оно не обрабатывается, а программа просто зависает или выбрасывает
сообщение об ошибке.
Но так как тип является базовым классом для всех исключений, то выражение
будет обрабатывать практически все исключения. Обработка же исключения в данном случае сводится к выводу на консоль стека трассировки ошибки с
помощью метода , определенного в классе Exception.
После завершения выполнения блока catch программа продолжает свою работу, выполняя все остальные инструкции после блока catch.
Конструкция try..catch также может иметь блок . Однако этот блок необязательный, и его можно при обработке исключений
опускать. Блок выполняется в любом случае, возникло ли исключение в блоке try или нет:
try{ int[] numbers = new int; numbers=45; System.out.println(numbers); } catch(Exception ex){ ex.printStackTrace(); } finally{ System.out.println("Блок finally"); } System.out.println("Программа завершена");
Обработка нескольких исключений
В Java имеется множество различных типов исключений, и мы можем разграничить их обработку, включив дополнительные блоки catch:
int[] numbers = new int; try{ numbers=45; numbers=Integer.parseInt("gfd"); } catch(ArrayIndexOutOfBoundsException ex){ System.out.println("Выход за пределы массива"); } catch(NumberFormatException ex){ System.out.println("Ошибка преобразования из строки в число"); }
Если у нас возникает исключение определенного типа, то оно переходит к соответствующему блоку catch.
Оператор throw
Чтобы сообщить о выполнении исключительных ситуаций в программе, можно использовать оператор throw. То есть с помощью
этого оператора мы сами можем создать исключение и вызвать его в процессе выполнения. Например, в нашей программе происходит ввод числа, и
мы хотим, чтобы, если число больше 30, то возникало исключение:
package firstapp; import java.util.Scanner; public class FirstApp { public static void main(String[] args) { try{ Scanner in = new Scanner(System.in); int x = in.nextInt(); if(x>=30){ throw new Exception("Число х должно быть меньше 30"); } } catch(Exception ex){ System.out.println(ex.getMessage()); } System.out.println("Программа завершена"); } }
Здесь для создания объекта исключения используется конструктор класса Exception, в который передается сообщение об исключении. И если
число х окажется больше 29, то будет выброшено исключение и управление перейдет к блоку catch.
В блоке catch мы можем получить сообщение об исключении с помощью метода .
НазадВперед
Summary
This is a simple code to execute external applications. If you want to call functions from other program (ex. C++, Visual Basic DLL), you need to use JNI (Java Native Interface) which you can find a nice tutorial at codeproject.com.
If you need more information, below are some sites that talk about executing external code.
For Java users
- Execute an external program – Real’s Java How-to.
http://www.rgagnon.com/javadetails/java-0014.html - When Runtime.exec() won’t – Java World.
http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html - Trouble with Runtime.getRuntime().exec(cmd) on Linux – Java.
http://www.thescripts.com/forum/thread16788.html - Runtime.getRuntime().exec (Linux / UNIX forum at JavaRanch).
http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=13&t=001755 - Java’s Runtime.exec() and External Applications.
http://www.ensta.fr/~diam/java/online/io/javazine.html
For C++ users
- How can I start a process?
http://www.codeguru.com/forum/showthread.php?t=302501 - Executing programs with C(Linux).
http://www.gidforums.com/t-3369.html
Пример контроля свойства modify окна Shell
В следующем примере выполняется контроль свойства modify окна при его закрытии. Для этого к Shell подключается слушатель, который перехватывает событие закрытия окна и вызывает метод getModified(). Окно изменено, если метод возвращает true.
В интерфейсе окна размещается текстовое поле text, к которому подключается слушатель события изменения SWT.Modify. При внесении изменения в текстовое поле слушатель устанавливает свойству окна modify значение true, которое можно сбросить (false), используя соответствующий пункт меню.
Листинг примера ShellModifiedTest
Интерфейс примера контроля состояния окна Shell представлен на следующем скриншоте.
В методе createMenu() создается основное меню «Файл», включающее подпункт «Сохранить», по нажатию на который свойство окна modify сбрасывается. Подробное описание работы с меню библиотеки SWT представлено на странице Menu Popup MenuItem.
Java ProcessBuilder environment
The method returns a string map view of
the process builder’s environment.
com/zetcode/ProcessBuilderEnvEx.java
package com.zetcode; public class ProcessBuilderEnvEx { public static void main(String[] args) { var pb = new ProcessBuilder(); var env = pb.environment(); env.forEach((s, s2) -> { System.out.printf("%s %s %n", s, s2); }); System.out.printf("%s %n", env.get("PATH")); } }
The program shows all environment variables.
configsetroot C:\WINDOWS\ConfigSetRoot USERDOMAIN_ROAMINGPROFILE LAPTOP-OBKOFV9J LOCALAPPDATA C:\Users\Jano\AppData\Local PROCESSOR_LEVEL 6 USERDOMAIN LAPTOP-OBKOFV9J LOGONSERVER \\LAPTOP-OBKOFV9J JAVA_HOME C:\Users\Jano\AppData\Local\Programs\Java\openjdk-11\ SESSIONNAME Console ...
This is a sample output on Windows.
In the next program, we define a custom environment variable.
com/zetcode/ProcessBuilderEnvEx2.java
package com.zetcode; import java.io.IOException; public class ProcessBuilderEnvEx2 { public static void main(String[] args) throws IOException { var pb = new ProcessBuilder(); var env = pb.environment(); env.put("mode", "development"); pb.command("cmd.exe", "/c", "echo", "%mode%"); pb.inheritIO().start(); } }
The program defines a variable and outputs it on
Windows.
pb.command("cmd.exe", "/c", "echo", "%mode%");
The is a Windows syntax for environment variables;
on Linux we use .
Аргументы командной строки
Приложение на Java может принимать любое количество аргументов с командной строки. Это позволяет пользователю указать необходимую конфигурационною информацию при запуске приложения.
Пользователь вводит аргументы командной строки при вызове приложения и указывает их после имени запускаемого класса. Например, приложением Sort сортирует строки в файле. Для сортировки файла «frients.txt» пользователь может ввести:
java Sort friends.txt
1 | java Sort friends.txt |
Приложение получает аргументы командной строки в массиве строк метода
main.
Следующая программа выводит в консоль аргументы командной строки, каждый аргумент на выводится на отдельной строке:
Java
public class Echo {
public static void main (String[] args) {
for (String s: args) {
System.out.println(s);
}
}
}
1 |
publicclassEcho{ publicstaticvoidmain(Stringargs){ for(Stringsargs){ System.out.println(s); } } } |
Если пользователь запустит программу так:
java Echo Drink Hot Java
1 | java Echo Drink Hot Java |
То вывод будет таким:
Drink
Hot
Java
1 |
Drink Hot Java |
Каждое слово вывелось на отдельной строке, потому что пробел разделяет аргументы командной строки, в результате каждое слово оказалось в отдельном аргументе. Чтобы получить все слова в одном аргументе пользователь должен заключить их в кавычки:
java Echo «Drink Hot Java»
1 | java Echo «Drink Hot Java» |
Установка JDK 8 и JRE 8 в автоматическом режиме на компьютере Windows через командную строку
Для этого я сейчас создаю сценарий, который автоматически запускает правильный установщик (32/64 бит) . Я попытался запустить установщик с помощью следующей команды:
jdk-8u25-windows-x64.exe /s ADDLOCAL=»ToolsFeature,SourceFeature,PublicjreFeature»
Это прекрасно работает на машине без установленной JDK/JRE 8. Однако я сталкиваюсь с несколькими проблемами:
- Если JDK/JRE 8 уже установлен, установщик удаляет JDK и JRE вместо того, чтобы просто ничего не делать (или переустанавливать)
- Если требуется перезагрузка, она принудительно выполняется автоматически, и мне нужно избегать этого, так как есть другие действия, которые мне нужно выполнить в сценарии после завершения установки.
- Нет режима/файла журнала VERBOSE, чтобы указать, что на самом деле делает установщик
но они кажутся недостающими и очень запутанными относительно того, что даст мне желаемый результат.
Я бы занялся JDK и JRE отдельно:
JDK не зависит от записей реестра или от того, что делает установщик exe. Так что установите JDK — без Public JRE — только на one машине, используя
Затем вы можете просто заархивировать полученную установку, скопировать и разархивировать ее на другие машины того же типа ОС.
Установщик JRE (отдельно загружаемый из Oracle) можно запустить с параметрами и файлом конфигурации, как описано здесь: http://docs.Oracle.com/javase/8/docs/technotes/guides/install /windows_installer_options.html
Предполагая, что конфиг находится в том же каталоге, что и exe программы установки, можно использовать параметр INSTALLCFG=»%cd%\jre-install-options.cfg» . В противном случае требуется указать полный путь к файлу конфигурации (INSTALLCFG = «c:\path\to\jre-install-options.cfg»). Итак, что-то вроде этого (с файлом журнала и при условии, что файл конфигурации находится в том же каталоге exe):
Кажется, что следующий jre-install-options.txt может работать для вас:
Я столкнулся с аналогичной проблемой с параметром/s. Я нашел ошибку jdk https://bugs.openjdk.Java.net/browse/JDK-8033364 . Кажется, они убрали поддержку или помощь. Попробуйте/QN это сработало для меня
Для тихой установки JRE:
start /wait msiexec /i «%
Java8.40×64.msi » JU=0 JAVAUPDATE=0 AUTOUPDATECHECK=0 RebootYesNo=No WEB_Java=1 /q
Вы можете увидеть полный пост здесь .
Кажется, есть постоянные изменения в поддерживаемых параметрах командной строки. В последнем 8 Обновлении 131 мне пришлось отказаться от всех опций стиля msiexec, потому что ни один из них не работал. Я использовал документацию для версии Java, которую я скачал, чтобы создать переключатели для установщика. Как показано в ответах выше, параметры файла конфигурации можно передать установщику из командной строки. Последняя команда, которую я использовал в Packer для установки Java на AMI Win2016 Server, была:
What is a shell and why is it so important?
“In order to present a command-line interface, you should use a computer program named shell. It enables users to control their computer with the help of commands entered with a keyboard. There is no need to control graphical user interfaces (GUIs) with mouse or keyboard combinations,” admits Tom Hayes, a UX designer at Essay Tigers.
Reasons to use a shell:
- You can use a lot of bioinformatics tools with the help of a command-line interface and get more command-line version capabilities. For example, BLAST is accessible to those who know how to deal with a shell.
- You will avoid making the same mistakes caused by manual repetitive work thanks to a shell that makes your work less error-prone.
- Your work will be more reproducible since using a shell your computer keeps a record of your every step. It enables people to re-do the work when needed and address others for checking or applying a process to new data.
Пример: получение информации о среде выполнения
В приведенном ниже примере мы создаем экземпляр класса Runtime с помощью метод. Используя этот экземпляр, мы можем получить различную информацию, относящуюся к выполняющейся в данный момент Java-среде, например, доступную память, используя метод, общая память с использованием метод, количество доступных процессоров, использующих метод и максимальный объем памяти, который JVM может использовать с помощью метод.
public class RuntimeDemo { public static void main(String[] args) { Runtime r = Runtime.getRuntime(); System.out.println("Available memory in JVM: " + r.freeMemory()); System.out.println("Total memory in JVM: " + r.totalMemory()); System.out.println("Available processors: " + r.availableProcessors()); System.out.println("Maximum memory: " + r.maxMemory()); } }
Available memory in JVM: 133169152 Total memory in JVM: 134217728 Available processors: 4 Maximum memory: 2124414976
Java ProcessBuilder non-blocking operation
In the following example, we create a process which is asynchronous.
com/zetcode/ProcessBuilderNonBlockingEx.java
package com.zetcode; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; public class ProcessBuilderNonBlockingEx { public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException, IOException { var executor = Executors.newSingleThreadExecutor(); var processBuilder = new ProcessBuilder(); processBuilder.command("cmd.exe", "/c", "ping -n 3 google.com"); try { var process = processBuilder.start(); System.out.println("processing ping command ..."); var task = new ProcessTask(process.getInputStream()); Future<List<String>> future = executor.submit(task); // non-blocking, doing other tasks System.out.println("doing task1 ..."); System.out.println("doing task2 ..."); var results = future.get(5, TimeUnit.SECONDS); for (String res : results) { System.out.println(res); } } finally { executor.shutdown(); } } private static class ProcessTask implements Callable<List<String>> { private InputStream inputStream; public ProcessTask(InputStream inputStream) { this.inputStream = inputStream; } @Override public List<String> call() { return new BufferedReader(new InputStreamReader(inputStream)) .lines() .collect(Collectors.toList()); } } }
The program creates a process that runs the ping command on the console.
It is executed in a separate thread with the help of the
method.
processing ping command ... doing task1 ... doing task2 ... Pinging google.com with 32 bytes of data: Reply from 2a00:1450:4001:825::200e: time=108ms Reply from 2a00:1450:4001:825::200e: time=111ms Reply from 2a00:1450:4001:825::200e: time=112ms Ping statistics for 2a00:1450:4001:825::200e: Packets: Sent = 3, Received = 3, Lost = 0 (0% loss), Approximate round trip times in milli-seconds: Minimum = 108ms, Maximum = 112ms, Average = 110ms
Командные файлы
В отличие от создания программных файлов, где знания нужны поосновательнее и требуется наличие специальных программ для того. чтобы получились файлы с расширением *.exe, командные файлы можно написать в любом текстовом редакторе, потом сменить на нужное расширение и файл можно запускать. Если файл нужно изменить, то это также просто сделать в том же редакторе, открыв файл для внесения изменений.
Командные файлы чаще всего имеют расширение *.bat, но могут иметь и другие расширения. Например, *.cmd будут запускаться только в командной строке. В зависимости от набора команд само окно командной строки может не появляться, обеспечивая быстрое и скрытное выполнение команд, записанных в файле.
В файл команды записывать проще, можно разбивать на строки, вписывать комментарии. Командные файлы можно сохранять и использовать на любом компьютере.
Итак, смысл понятий прояснил, насколько смог, можно глубже влезать в эту тему. Рекомендую, кроме информации в упомянутом выше сборнике, вот эти статьи:
- Секреты работы с командной строкой в WINDOWS;
- Тонкости работы в командной строке Windows.
Не знаю, есть ли потребность в продолжении публикаций на эту тему, зависит от вас!
Скачать примеры Shell
Рассмотренные примеры Shell в виде проекта Eclipse, включающего библиотеки SWT для 32- и 64- разрядных Windows, можно скачать здесь (5.76 Мб).
1 Introduction to JShell
The Java Shell tool (JShell) is an interactive tool for learning the Java programming language and prototyping Java code. JShell is a Read-Evaluate-Print Loop (REPL), which evaluates declarations, statements, and expressions as they are entered and immediately shows the results. The tool is run from the command line.
For reference information for this tool, see jshell in Java Platform, Standard Edition Tools Reference .
Java ProcessBuilder inherit IO
The sets the source and destination for subprocess
standard I/O to be the same as those of the current Java process.
com/zetcode/ProcessBuilderInheritIOEx.java
package com.zetcode; import java.io.IOException; public class ProcessBuilderInheritIOEx { public static void main(String[] args) throws IOException, InterruptedException { var processBuilder = new ProcessBuilder(); processBuilder.command("cmd.exe", "/c", "dir"); var process = processBuilder.inheritIO().start(); int exitCode = process.waitFor(); System.out.printf("Program ended with exitCode %d", exitCode); } }
By inheriting the IO of the executed command, we can skip the reading step.
The program outputs the contents of the project directory and the message
showing the exit code.
02/14/2019 04:55 PM <DIR> . 02/14/2019 04:55 PM <DIR> .. 02/19/2019 01:11 PM <DIR> .idea 02/14/2019 04:55 PM <DIR> out 02/14/2019 04:52 PM 433 ProcessBuilderInheritIOEx.iml 02/14/2019 04:53 PM <DIR> src 1 File(s) 433 bytes 5 Dir(s) 157,350,264,832 bytes free Program ended with exitCode 0
We get both the output of the executed command and of our own Java program.
Java ProcessBuilder redirect output
With , we can redirect the process builder’s standard
output destination.
com/zetcode/RedirectOutputEx.java
package com.zetcode; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; public class RedirectOutputEx { public static void main(String[] args) throws IOException { var homeDir = System.getProperty("user.home"); var processBuilder = new ProcessBuilder(); processBuilder.command("cmd.exe", "/c", "date /t"); var fileName = new File(String.format("%s/Documents/tmp/output.txt", homeDir)); processBuilder.redirectOutput(fileName); var process = processBuilder.start(); try (var reader = new BufferedReader( new InputStreamReader(process.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } } }
The program redirects the builder’s output to a file. It runs the Windows
command.
processBuilder.redirectOutput(fileName);
We redirect the process builders standard output to a file.
try (var reader = new BufferedReader( new InputStreamReader(process.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } }
Now the output goes to the file.
$ echo %cd% C:\Users\Jano\Documents\tmp $ more output.txt Thu 02/14/2019
The current date was written to the file.
Работа с Ворд через СОМ-Объект
Статья представляет собой еще один велосипед на тему формирования документов на основе шаблонов через СОМ-Объект. Как и все другие велосипеды, этот написан потому, что другие велосипеды — плохие. В действительности, если погуглить, мы получим огромное количество ссылок на советы в стиле «сделай так и будет тебе счастье». Но почему «так», зачем «так», какие есть альтернативы — авторы советов не раскрывают. Хуже того, половина найденных таким способом рецептов окажутся откровенно вредными. Судя по тому, как вредные рецепты копируются из совета в совет, большинство разработчиков, из тех, что переписываются на форумах, просто воспроизводят то, что когда-то нагуглили сами. Ну да, работает — не трогай
Пример слушателя закрытия окна Shell
В следующем примере в зависимости от значения adapter к Shell подключается один из слушателей,
который перехватывает событие «закрытия окна» и вызывают перезагруженную функцию confirmExit для
подтверждения завершения работы. Функция confirmExit открывает модальное диалоговое окно
MessageBox в приложении (стиль SWT.APPLICATION_MODAL) с размещением в интерфейсе двух кнопок OK
и Cancel.
import org.eclipse.swt.*; import org.eclipse.swt.events.ShellAdapter; import org.eclipse.swt.events.ShellEvent; import org.eclipse.swt.widgets.*; public class ShellTest { private static boolean adapter = true; private static int confirmExit(Shell shell) { int style = SWT.APPLICATION_MODAL | SWT.OK | SWT.CANCEL; MessageBox messageBox = new MessageBox (shell, style); messageBox.setText ("Подтверждение выхода"); messageBox.setMessage ("Закрыть окно?"); return messageBox.open(); } private static int confirmExit(Shell shell, ShellEvent event) { return confirmExit(shell); } public static void main (String [] args) { Display display = new Display (); final Shell shell = new Shell (display, SWT.SHELL_TRIM); shell.setText("Пример Shell"); if (adapter) { shell.addListener (SWT.Close, new Listener() { @Override public void handleEvent(Event event) { event.doit = confirmExit(shell) == SWT.OK; } }); } else { shell.addShellListener(new ShellAdapter() { @Override public void shellClosed(ShellEvent event) { event.doit = confirmExit(shell, event) == SWT.OK; } @Override public void shellActivated(ShellEvent e) {} @Override public void shellDeactivated(ShellEvent e) {} @Override public void shellDeiconified(ShellEvent e) {} @Override public void shellIconified(ShellEvent e) {} }); } // shell.pack(); shell.open(); while (!shell.isDisposed ()) { if (!display.readAndDispatch ()) display.sleep (); } display.dispose (); System.exit(0); } }
Интерфейс окна примера слушателя закрытия Shell представлен на следующем скриншоте.
Переменная CLASSPATH
Переменная окружения CLASSPATH указывает на пути, в которых нужно будут искаться классы пользователя. Лучший способ указать путь к классам — это использовать аргумент командной строки
-cp , что позволяет указать CLASSPATH индивидуально для каждого приложения.
Значение по умолчанию
«.», которое означает, что поиск будет происходить только в текущем каталоге. Указание переменной CLASSPATH или аргумента командной строк
-cp переопределяет это значение.
Цикл статей «Учебник Java 8».
Следующая статья — «Java 8 регулярные выражения».
Предыдущая статья — «Java 8 многопоточность».
Стили Shell
Shell может использовать стили BORDER, CLOSE, MIN, MAX, NO_TRIM, RESIZE, TITLE, ON_TOP, TOOL, SHEET MODELESS, APPLICATION_MODAL, PRIMARY_MODAL, SYSTEM_MODAL. Стили окон могут комбинироваться.
Если стиль окна установлено «модальным», то window manager блокирует работу с другими окнами экрана :
- PRIMARY_MODAL закрывает доступ к окну своего родителя;
- APPLICATION_MODAL блокирует доступ ко всем окнам экрана приложения;
- SYSTEM_MODAL закрывает доступ ко всем окнам разных приложений.
Примечание: при определении в стиле модальности окна можно использовать один из трех доступных стилей.
Класс SWT включает два «комбинированных» стиля :
- SHELL_TRIM — комбинирование стилей TITLE | CLOSE | MIN | MAX | RESIZE, используется при создании типичного окна;
- DIALOG_TRIM — комбинирование стилей TITLE | CLOSE | BORDER, используется при создании диалогового окна.
Стиль | Описание | Интерфейс |
---|---|---|
SWT.SHELL_TRIM | Окно можно развернуть, свернуть и изменить размер | |
SWT.MAX | SWT.RESIZE | Окно можно развернуть и изменить размер | |
SWT.MIN | SWT.RESIZE | Окно можно свернуть и изменить размер | |
SWT.DIALOG_TRIM | Окно имеет фиксированный размер |
Окна Shell в интерфейсе могут быть представлены в «развернутом» (maximized), в «свернутом» (minimized) или в «нормальном» (normal) состоянии.
Если реализации Shell будет определено состояние «maximized», то window manager развернет окно так, чтобы оно заняло всю видимую область экрана (display). В развернутом состоянии размер Shell не может быть изменен, даже если оно имеет стиль RESIZE. Если Shell находится в нормальном состоянии, то внешний вид окна контролируется стилями, которые были определены на этапе создания. Размер окна может быть изменен, если окно имеет соответствующий стиль. Если стиль окна «minimized», то интерфейс окна (клиентская область) не виден. В зависимости от window manager окно может быть «свернуто» в иконку или скрыто.
Слушатель окна ShellListener, ShellAdapter
Слушатель окна ShellListener позволяет перехватить сообщения об активации/деактивации окна,
сворачивании/разворачивании окна, закрытии окна. В следующем коде к окну shell поключается слушатель
ShellAdapter, включающий соответствующие методы.
Display display = new Display (); final Shell shell = new Shell (display); shell.setText("Пример Shell Listener"); shell.addShellListener(new ShellAdapter() { // Метод обработки события закрытия окна @Override public void shellClosed(ShellEvent e) { } // Метод обработки события активации окна @Override public void shellActivated(ShellEvent e) { } // Метод обработки события деактивации окна @Override public void shellDeactivated(ShellEvent e) { } // Метод обработки события разворачивании окна @Override public void shellDeiconified(ShellEvent e) { } // Метод обработки события сворачивания окна @Override public void shellIconified(ShellEvent e) { } });
Использование ShellListener — это не единственный способ перехватывания соответствующего
события. Можно использовать и обычного слушателя Listener. В следующем коде к shell подключается
Listener, который перехватывает событие закрытия окна.
shell.addListener (SWT.Close, new Listener() { @Override public void handleEvent(Event event) { } });
Ввод и вывод
Также нужно подключиться к входным и выходным потокам нашего процесса. По крайней мере, нужно получить выходные данные, иначе процесс зависнет.
Реализуем класс StreamGobbler, который использует InputStream:
private static class StreamGobbler implements Runnable { private InputStream inputStream; private Consumer<String> consumer; public StreamGobbler(InputStream inputStream, Consumer<String> consumer) { this.inputStream = inputStream; this.consumer = consumer; } @Override public void run() { new BufferedReader(new InputStreamReader(inputStream)).lines() .forEach(consumer); } }
Примечание. Этот класс реализует интерфейс Runnable, а это означает, что он может быть выполнен любым исполнителем.