- •Оглавление
- •Предисловие
- •Введение
- •Глава 1. Средства разработки приложений
- •1.1. Системные требования
- •1.2. Введение в NetBeans
- •1.3. Установка NetBeans
- •1.4. Первый запуск NetBeans
- •1.5. Интерфейс пользователя
- •1.6. Настройки среды
- •1.7. Создание проекта
- •Глава 2. Язык программирования Java
- •2.1. Первое приложение
- •2.2. Метод main
- •2.3. Основные понятия языка Java
- •2.3.1. Переменные и константы
- •2.4. Примитивные типы данных
- •2.4.1. Целые и символьные типы(byte, short, char, int, long)
- •2.4.2. Логический тип Boolean
- •2.4.3. Вещественные типы (float и double)
- •2.5. Ссылочные типы
- •2.6. Выражения и операторы
- •2.6.1. Логические операторы
- •2.6.2. Целочисленные битовые операторы
- •2.6.3. Арифметические операторы
- •2.6.4. Приоритеты выполнения операторов
- •2.6.5. Преобразование типов
- •2.6.6. Оболочечные классы
- •2.7. Класс Math
- •2.8. Сложные типы данных и строки
- •2.8.1. Массивы
- •2.8.2. Строки
- •2.9. Управляющие конструкции
- •2.9.1. Составной оператор
- •2.9.2. Условный оператор if
- •2.9.3. Оператор выбора
- •2.9.4. Операторы цикла
- •2.9.5. Операторы перехода
- •Глава 3. Введение в ООП
- •3.1. Основные принципы ООП
- •3.2. Состав структура и основные свойства классов
- •3.2.1. Описание полей класса
- •3.2.2. Оператор new
- •3.2.3. Описание методов
- •3.2.4. Модификаторы
- •3.2.5. Конструкторы
- •Совмещение методов
- •Глава 4. Рефакторинг
- •Глава 5. Ввод и вывод в Java
- •Глава 6. Графический интерфейс пользователя GUI
- •6.1. Компоненты и контейнеры
- •6.2. Встроенные пакеты GUI классов на основе библиотеки awt
- •6.2.1. Метка Label
- •6.2.2. Кнопка Button
- •6.2.3. Кнопка выбора CheckBox
- •6.2.4. Радио-кнопка Radiobutton
- •6.2.5. Поле ввода TextField
- •6.2.6. Поле ввода TextArea
- •6.3. Использование визуального редактора для проектирования ГИП
- •6.4. Графика в Java
- •6.5. Обработка событий
6.4. Графика в Java
Для работы с графикой в Java имеется класс Graphics пакета java.awt. Поскольку класс Graphics является абстрактным, т.к. графический контекст сильно зависит от конкретной графической платформы, создать экземпляры данного класса не удастся. Для простоты работы и снятия необходимости в самостоятельной реализации абстрактных методов, каждая виртуальная машина Java реализует эти методы и создает объекты данного класса методом getGraphics() или с помощью аргумента метода paint().
Рисование возможно на любых контейнерах. В рамках данного пособия рассмотрим рисование непосредственно в окне. Для начала нужно создать так называемый «лист для рисования», или окно. В главе «Программирование графического интерфейса пользователя» вы познакомились с тем, как создавать окна и некоторые другие компоненты ГИП. Далее на примере рассмотрим процесс рисования.
01 |
import java.awt.*; |
02 |
import javax.swing.*; |
03 |
public class Gr1 extends JFrame{ |
04 |
Gr1(String s){ |
05 |
super(s); |
06 |
setLayout(null); |
07 |
setSize(300,500); |
08 |
setVisible(true); |
09this.setDefaultCloseOperation(EXIT_ON_CLOSE);
10}
11public void paint(Graphics my_picture){
12my_picture.setColor(Color.LIGHT_GRAY);
13my_picture.fillRect(0, 0, 300, 800);
14my_picture.setColor(Color.BLACK);
15my_picture.drawOval(90, 50, 100, 100);
16my_picture.drawLine(140, 150, 140, 300);
17my_picture.drawLine(140, 300, 100, 400);
18my_picture.drawLine(140, 300, 180, 400);
19my_picture.drawLine(140, 200, 75, 250);
20my_picture.drawLine(140, 200, 205, 250);
21}
22public static void main(String[] args) {
23new Gr1("");
24}
25
}
Вданном примере мы использовали метод paint(). Сначала заливаем рабочую область (строка 13) светло-серым цветом (строка 12), затем устанавливаем обратно черный цвет чернил (строка 14) и рисуем фигуру человечка (строки 15-20).
Графический объект с именем my_picture мы создали с помощью
аргумента метода paint(), затем в самом методе использовали данный
объект для рисования. Объект my_picture наследует все методы класса Graphics, вызывая которые можно рисовать.
Класс Graphics имеет очень большой набор методов для работы с графикой, рассмотрим наиболее часто используемые методы:
drawLine(int x1, int y1, int x2, int y2); рисует линию из точки с координатами (x1,y1) до точки с координатами (x2,y2).
drawOval(int x1, int y1, int width, int height); рисует овал (эллипс) с координатами левого верхнего угла (x1,y1), шириной width и высотой height.
drawRect(int x1, int y1, int width, int height); рисует прямоугольник с координатами левого верхнего угла (x1,y1), шириной width и высотой height.
drawArc(int x1, int y1, int width, int height, int startAngle, int arcAngle); строит окружность с координатами верхнего левого угла (x1,y1) затем отсекает и рисует арку сектора с углом arcAngle. Начальный угол, от которого начинается отсечение
startAngle.
drawPolygon(int[] xPoints, int[] yPoints, int points);
рисует многоугольник по точкам, которые содержат массивы xPoints и yPoints, с количеством переломов points.
fillOval(int x1, int y1, int width, int height); fillRect(int x1, int y1, int width, int height); fillPolygon(int[] xPoints, int[] yPoints, int points);
fillArc(int x1, int y1, int width, int height, int startAngle, int
arcAngle);
данные четыре метода проделывают то же что и предыдущие, при этом заливая полученные фигуры текущим цветом.
setColor(Color c); устанавливает текущий цвет. c – объект типа
Color.
getColor(Color); возвращает значение текущего цвета, точнее объект типа Color.
drawstring(String s, int x, int y); выводит строку символов s с координатами (x,y).
Для установки текущего цвета чернил нужно в качестве аргумента метода setColor() указать объект типа Color. Можно предварительно создать такой объект конструкцией
Color clr = new Color();
Конструкторов цвета несколько, а точнее 7 штук, наиболее удобным является конструктор Color(int r, int g, int b), где r – целое число типа int – составляющая красного цвета, g – зеленого, b – голубого. Каждая составляющая имеет длину 1 байт или 256 вариаций (0-255). С помощью данного конструктора можно получить 16,7 миллионов возможных цветов.
Однако можно не пользоваться конструктором и не создавать цветовые объекты, можно установить цвет в методе getColor(), как показано выше в листинге, выбрав один из 12 цветов, просто введите Color, далее введите точку и ассистент NetBeans выдаст все варианты цветов. Так же можно вызвать метод getColor() класса Color, и указать ему в качестве аргумента строку, которая будет преобразована в цвет.
С помощью данных методов можно нарисовать практически любой рисунок, все зависит только от сложности.
Так же, класс Graphics поддерживает различные шрифты, их размеры, цвет и другие параметры. Однако в рамках данного пособия нет возможности описать все особенности данного класса. Если у вас возникло желание более углубленного изучения, используйте рекомендуемые материалы.
6.5.Обработка событий
Вразделе 6.1. мы написали программу, которая создает окно и помещает в него по одному из экземпляров рассмотренных компонентов. Однако программой данное приложения назвать сложно, поскольку она ничего не делает, можно нажать на кнопку, выбрать радио-кнопку, ввести текст, но ничего не последует после этого. Для того что бы добавить интерактивность в программу, необходимо описать обработку событий. Событие происходит или возникает при воздействии на какой-либо компонент пользователем – нажатие кнопок мыши, клавиатуры, перемещение окна, изменение его размеров и т.д.
Объект, в котором произошло событие, называется источником
события. Главный в иерархии класс-событие – EventObject.
Самое главное, что нужно знать, это то, что событие нельзя обработать одним произвольным методом, у каждого из событий есть свои методы, они описаны в интерфейсах слушателях (LISTENERS). Имена интерфейсов слушателей составляются из имени события и слова Listener, например MouseListener. Что бы задать обработку события, необходимо реализовать соответствующий интерфейс. Классы, которые реализуют такие интерфейсы, называются обработчиками (HANDLERS). Для связи с обработчиком события, классы-источники события должны получить ссылку на экземпляр класса-обработчика
события одним из методов add***Listener(***Event eventHandler), где
*** - имя события. Так же можно убрать обработчик и прекратить прослушивание объекта методом remove***Listener().
В качестве примера обработки события, создадим мини записную книжку, в которой будет поле ввода TextField, многострочное текстовое поле TextArea и кнопка. При нажатии кнопки или клавиши <Enter> на клавиатуре, когда фокус находится на объекте TextField, строка из TextField должна добавиться в поле TextArea. В обоих случаях произойдет событие класса ActionEvent. Однако у нас будет два компонента, которые будут являться потенциальными источниками этого события и обоих их нужно будет добавить в класс-источник как прослушиваемые объекты. В интерфейсе ActionListener есть один метод, который нужно определить – это actionPerformed(). Именно этот метод и описывает действия, которые буду происходить при нажатии на кнопку или клавишу <Enter>.
Опишем наше окно – записную книжку:
import java.awt.*; import java.awt.event.*; import javax.swing.*;
public class EventExample extends JFrame{ EventExample(String s){
super(s);
Container container = getContentPane(); JTextField input = new JTextField("",35); container.add(input, BorderLayout.NORTH); JTextArea memory = new JTextArea(); memory.setEditable(false); container.add(memory);
JButton send = new JButton ("Сохранить");
container.add(send, BorderLayout.SOUTH); input.addActionListener(new Handler(input, memory)); send.addActionListener(new Handler(input, memory));
setVisible(true);
setSize(500,400);
}
public static void main(String[] args) {
JFrame NoteBook = new EventExample("Мой блокнот"); NoteBook.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Книжку мы сделали с использованием компонентов SWING, заметны небольшие отличия – строка Container container = getContentPane(); - создание контейнера и получение верхнего уровня для этого контейнера методом конструктора getContentPane(). В отличии от компонентов AWT, компоненты SWING в данном примере мы добавляет не напрямую в окно, а в контейнер, обращаясь к методу add() контейнера, а не конструктора окна, а так же новым является параметр BorderLayout для этого метода, который указывает, как разместить компонент в контейнере.
Выделенные жирным шрифтом обращения к методам addActionListener добавляют слушателей для себя, то есть при каждом вызове метода addActionListener, создается экземпляр классаобработчика Handler с параметрами в качестве компонентов, задействованных в обработке события.
Теперь нужно описать сам класс-обработчик Handler. Сразу же после фигурной скобки, закрывающей класс EventExample, добавьте код класса-обработчика:
class Handler implements ActionListener{ private JTextField input;
private JTextArea memory; Handler(JTextField input, JTextArea memory){
this.input = input; this.memory = memory;
}
public void actionPerformed(ActionEvent aevt){ memory.append(input.getText()+"\n"); input.setText("");
}
}
Рассмотрим подробно, из чего состоит данный класс.
Сначала объявляются две закрытые переменные – типа поля ввода и текстового поля, затем создается конструктор, в котором происходит
подстановка параметров в качестве переменных, используемых далее в методе actionPerformed(), то есть в описании обработки мнимо используются внутренние закрытые переменные input и memory JTextField и JTextArea, но в случае возникновения реального события, они заменяются параметрами, указанными в объявлении слушателя в классе самой записной книжки. Далее описывается сам метод actionPerformed для обработки события ActionEvent – методом append объекта memory добавляется строка в конец этого текстового поля memory, эта строка складывается из двух составляющих – метода getText() переменной input и "\n", где \n – это Unicode конструкция, означающая переход на новую строку. И второе действие методаобработчика – очистка содержимого поля ввода методом setText(“”).
В результате должно получиться окно следующего вида:
Строк, которые вы видите на рисунке, у вас не будет, можете добавить свои собственные записи.
Стоит так же привести пример обработки событий без описания отдельного класса обработчика, как сделано выше. Событию можно назначить обработку путем указания в качестве аргумента метода addActionListener() непосредсвенно вызов конструктора классаинтерфейса ActionListener с последующей реализацией его методов, а метод в данном интерфейсе только один - actionPerformed(). Теперь изменим программу таким образом, что бы события обрабатывались бы не с помощью класса слушателя, описанного отдельно, а с помощью
вложенного класса слушателя. Для этого нам потребуется заменить только строки добавления слушателей к объектам:
input.addActionListener(new Handler(input, memory));
send.addActionListener(new Handler(input, memory));
В качестве аргументов методов добавления слушателя (addActionListener()) нам нужно описать вложенные классы обработчики, самое главное в данном процессе не запутаться с открывающими и закрывающими скобками:
input.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent evt){
memory.append(input.getText()+"\n");
input.setText("");
}
});
send.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent evt){
memory.append(input.getText()+"\n");
input.setText("");
}
});
Для большей разборчивости, круглые открывающие и закрывающие скобки данных методов выделены жирным шрифтом. На первый взгляд данный подход выглядит более продуктивным, однако в нем есть большой недостаток, который в некоторых случаях может стать недопустимым. Данный недостаток заключается в наложении ограничения на объекты, используемые в процессе обработки события, а именно, они должны иметь модификатор final. Таким образом, помимо произведенных изменений вам будет необходимо добавить в конструкторе блокнота final модификатор к объектам JTextField и JTextArea. Сделать это можно вручную, либо, после полного ввода
предложенного кода, Eclipse уведомит вас о ошибке значком
. Щелкнув мышкой по данному значку, раскроется контекстное меню с вариантами устранения ошибки, просто выберите верхний пункт, в котором предложено добавить модификатор final к используемому объекту. После того как все ошибки устранены, можно запускать программу.
Теперь программа имеет некоторую интерактивность, она отвечает на действия пользователя.
Событие ActionEvent – одно из наиболее часто используемых событий, так как чаще всего, работа приложения складывается из нажатий кнопок и ввода данных. Так же немного реже используются события мыши MouseEvent, имеющие набор методов типа
mouseClicked, mousePressed, mouseEntered, mouseMoved и др. Эти методы используются часто для обработки событий при работе с графикой, например для рисования.
Обрабатывать события можно и не создавая новых объектов класса AtcionListener, обработку можно выполнить собственным методом класса. Как вы уже знаете, действия, которые будут выполняться, описаны внутри метода actionPerformed(), который принадлежит интерфейсу AtcionListener. Почему бы не использовать данный метод внутри класса, компонент которого вызывает событие. Для этого необходимо просто указать то, что данный класс наследует методы интерфейса AtcionListener. Добавляем к описанию основного класса implements ActionListener, и теперь можно определить метод actionPerformed() внутри основного класса. Затем, добавляя слушателя к компоненту, указываем, что слушать класс будет сам себя. Например send.addActionListener(this). Ключевое слово this
означает ссылку на объект, из которого происходит вызов, поскольку вызов данного метода происходит внутри конструктора класса EventExample (в нашем примере), то конструкция send.addActionListener(this) предпишет прослушивать классу
EventExample кнопку с именем send, которая в нем самом находится. Данный подход называется самообработкой событий.
Работа с файлами
ВJava существует класс File, с помощью которого можно работать
сфайлами и папками. Данный класс обеспечивает работу с именами файлов, путями и директориями, а так же атрибутами файлов и папок. Так же в процесс работы с файлами можно отнести работу с I/O потоками – потоками ввода-вывода, обеспечивающими работу не только
сфайлами и папками, но и с оперативной памятью и различными устройствами.
Объекты типа File можно рассматривать как некоторые классы, содержащие в себе методы работы с файлами, а точнее с их именами. Каталог или папка в Java рассматривается тоже как файл с особыми атрибутами.
Для создания объекта типа File существует несколько конструкторов:
●File(имя файла)
●File(имя папки)
●File(имя папки, имя файла)
Имена файлов и папок могут быть как абсолютные, так и относительные. Файлы и папки виртуальной машиной, при выполнении программы, ищутся по правилам установленной на компьютере ОС. Например, в системе семейства Linux мы указали рабочее пространство /home/***/workspace (где *** – имя пользователя), то есть теперь наши проекты хранятся по указанному адресу. Проект Hello, который был нашим первым проектом, должен находится по адресу
/home/***/workspace/Hello/.
Для выполнения примера создайте папку с именем MyFolder, и в ней создайте новый файл, введите в него произвольный текст.
Для того что бы создать папку в проекте, нажмите черный
треугольник на кнопке
, после чего, в раскрывающемся списке выберите пункт Folder. Затем в панели Package Explorer (должен быть активен) выделите новую, созданную вами папку MyFolder и аналогичным способом создайте в ней файл с именем My_File, выбрав в раскрывающемся списке пункт File.
После того, как папка с файлом созданы, создайте новый класс с именем, например Files, и введите в него предложенный в листинге код.
Пример работы с файлами: import java.io.*; public class Files {
static File f1 = new File("src/MyFolder/My_File"); public static void main(String[] args) {
System.out.print(f1.getName()+"\n");
System.out.print(f1.getPath()+"\n");
System.out.print(f1.getAbsolutePath());
}
}
Как вы заметили, для работы с файлами, нужно подключить класс ввода-вывода java.io.
В примере создается объект типа File с именем f1, которому сопоставлен реальный, вами созданный файл на жестком диске, находящийся в папке MyFolder. Затем в главном методе происходит вывод трех строк, в первой строке выводится имя файла – My_File, во второй – путь к файлу, указанный в конструкторе /src/MyFolder/My_File
– и в третьей – вывод абсолютного пути - /home/***/workspace/Hello/MyFolder/My_File. В случае, если программа находится не в проекте Hello, с которого начиналось наше изучение Java, тогда вместо «Hello» в абсолютном пути будет имя того проекта, в котором находится программа.
Основные методы и переменные класса File:
● pathSeparatorChar – переменная, содержащая сивол разделитель (Windows – “\”, Linux – “/”);
●exists() – метод возвращающий значение true если файл имеется по указанному пути;
●length() – метод, возвращающий длину файла в байтах;
●canRead() - метод, возвращающий true в случае, если файл можно прочитать;
●setReadOnly() - метод, возвращающий true в случае, если файл существует и на него удалось поставить атрибут «только чтение»;
●canWrite() - метод, возвращающий true в случае, если файл можно записать;
●isDirectory() - метод, возвращающий true в случае, если по указанный в конструкторе файл является папкой;
●isFile() - метод, возвращающий true в случае, если по указанный в конструкторе файл является файлом;
●isHidden() - метод, возвращающий true в случае, если по указанный в конструкторе файл является скрытым. Для Windows, скрытый файл – это файл имеющий атрибут «скрытый», для Linux
–файл, начинающийся с точки;
●getName() - метод, возвращающий строку, содержащую имя файла;
●getAbsolutePath() - метод, возвращающий строку, содержащую абсолютный путь к файлу;
●getCannonicalPath() - метод, возвращающий строку, содержащую абсолютный путь к файлу, включая имя файла. Может возбуждать исключение типа IOException, относящееся к проверяемому, и поэтому данный метод должен быть заключен в блок try{};
●createNewFile() – метод, пытающийся создать новый файл. Может возбуждать исключение типа IOException, относящееся к проверяемому, и поэтому данный метод должен быть заключен в блок try{};
●mkdir() – попытка создания папки по указанному пути, возвращает true в случае успешного создания;
●mkdirs() – попытка создания папки по указанному пути конструктора, а так же подпапок, указанных в данном пути возвращает true в случае успешного создания;
●delete() – попытка удаления файла или папки по указанному пути, возвращает true в случае успешного удаления;
●renameTo(путь к файлу с новым именем) – попытка переименования файла или папки, возвращает true в случае успешного переименования;
●list() – возвращает массив строк, содержащих имена файлов, находящихся в указанной папке, если указан файл вместо папки,
возвращается значение null. Имена файлов в подпапках не показываются;
● listFiles() – аналогично предыдущему, за исключением того, что возвращается массив объектов типа File.
С помощью указанных методов можно производить все основные операции с именами файлов и папок. В качестве примера, выведем имена выбранных в диалоговом окне файлов в текстовое поле TextArea. Замените код класса Files на предложенный ниже.
import java.awt.*; import java.awt.event.*; import java.io.*; import javax.swing.*;
public class Files extends JFrame{ Files(String wintitle){ super(wintitle);
Container cont = getContentPane(); setLayout(null);
setSize(600,400);
setVisible(true); setDefaultCloseOperation(Jframe.EXIT_ON_CLOSE); Button btn = new Button(“Открыть”); btn.setBounds(250, 20, 100, 25);
cont.add(btn);
TextArea listoffiles = new TextArea(); listoffiles.setBounds(0, 55, 590, 315); cont.add(listoffiles);
btn.addActionListener(new BtnHandler(listoffiles));
}
public static void main(String[] args) {
Jframe FileList = new Files(“Пример списка файлов”);
}
}
class BtnHandler implements ActionListener{ private TextArea list; BtnHandler(TextArea list){
this.list = list;
}
public void actionPerformed(ActionEvent aevt){ JFileChooser fc = new JFileChooser(); fc.setMultiSelectionEnabled(true);
if (fc.showOpenDialog(null)!=fc.APPROVE_OPTION){ return;
};
File[] flist = fc.getSelectedFiles(); for (int i=0; i<flist.length; i++){
list.setText(list.getText()+flist[i]+”\n”);
}
}
}
В данном коде, а точнее в классе Files, который является самим окном, не используются объекты типа File. Данные объекты используются в обработчике BtnHandler(). Поскольку, ничего нового в классе Files нет, интерес представляет только обработчик BtnHandler. Разберем подробно работу обработчика:
Сначала создается закрытый объект типа TextArea с именем list. В разделе «обработка событий» мы познакомились способом подстановки вместо закрытого объекта класса обработчика объекта, являющегося частью обработки события. В данном примере мы совершаем подстановку только объекта listoffiles типа TextArea вместо мнимо обрабатываемого закрытого объекта list того же типа. Но наибольший интерес представляет сам метод actionPerformed обработки события ActionEvent. Сначала создается объект типа JFileChooser с именем fc и устанавливается параметр setMultiSelectionEnabled в значение true, для того, чтобы можно было выбрать несколько файлов в диалоговом окне. Затем, необычным образом – в теле условного оператора, вызывается метод этого объекта fc – showOpenDialog, который производит вывод диалогового окна открытия файла(ов) на экран. Поскольку данный оператор находится в теле условия, сразу же происходит и проверка на отказ от открытия, и если пользователь отказался от открытия файла (нажал кнопку «Cancel» или закрыл диалоговое окно) происходит возврат в программу оператором return. В случае, если файл(ы) выбраны, и нажата кнопка «ОК», или клавиша <Enter>, происходит создание массива flist типа File, в который заносятся объекты этого типа, а точнее ссылки на выбранные файлы. Затем в цикле происходит запись содержимого этого массива в поле TextArea.
Рассмотрим основы работы с содержим файлов – чтением и записью.
Для того чтобы считать текст файла, нужно создать массив символов, затем с помощью потока InputStream записать в него содержимое файла. Для примера используем уже готовую форму предыдущего примера, но в этот раз в текстовое поле будет помещаться содержимое файла, а не пути выбранных файлов. Поскольку считывать будем содержимое только одного файла, уберем строку fc.setMultiSelectionEnabled(true); или установим ее значение в false. Наш класс обработчик примет следующий вид:
class BtnHandler implements ActionListener{ private TextArea list;
File my_file; BtnHandler(TextArea list){
this.list = list;
}
public void actionPerformed(ActionEvent aevt){ JFileChooser fc = new JFileChooser(); fc.setMultiSelectionEnabled(false);
if (fc.showOpenDialog(null)!=fc.APPROVE_OPTION){ return;
};
my_file = fc.getSelectedFile(); try{
InputStream fis = new FileInputStream(my_file); int fileSize = fis.available();
fis.close();
char[] fileBuffer = new char[fileSize]; Reader frs = new FileReader(my_file); frs.read(fileBuffer); list.setText(String.copyValueOf(fileBuffer));
}
catch (IOException xcpt){ JOptionPane.showMessageDialog(null,"Файл нельзя
прочитать");
}
}
}
В данном примере создается объект my_file типа File для дальнейшего использования в потоке, и сразу же ему сопоставляется выбранный в диалоге файл my_file = fc.getSelectedFile(); Затем начинается блок try{}, поскольку не всегда можно считать данные из файла и может быть вызвано исключение IOException, которое и перехватывается в конце. В блоке try «пытаемся» провести следующие действия:
Создаем переменную fis типа InputStream, она нужна для работы потока FileInputStream;
Функцией available() данной переменной получаем значение числа байт, которые мы можем считать из файла, и присваиваем это значение новой созданной переменной fileSize;
Создаем массив символов с именем fileBuffer и размером fileSize. Этот массив и является ключевым в данной программе, в него будем считывать файл;
Создаем объект типа Reader с именем frs и указываем ему в качестве параметра файл, который будет считываться в содержимое массива;
Читаем файл функцией read();
Функцией copyValueOf() оболочечного класса String преобразуем массив символов в строку и записываем ее в поле TextArea.
Вблоке catch{} перехватываем возможное исключение, и
в случае если такое исключение будет возбуждено, выводим сообщение (средствами окна сообщения из класса JOptionPane методом showMessageDialog) о том, что файл не может быть прочитан.
Запись в файл осуществляется намного проще, поскольку не нужно создавать никаких потоков. Замените блоки try{} и catch(){} на предложенные в листинге 61.
class BtnHandler implements ActionListener{ private TextArea list;
File my_file; BtnHandler(TextArea list){
this.list = list;
}
public void actionPerformed(ActionEvent aevt){ JFileChooser fc = new JFileChooser();
fc.setMultiSelectionEnabled(true);
if (fc.showSaveDialog(null)!=fc.APPROVE_OPTION){ return;
};
my_file = fc.getSelectedFile(); try{
Writer fws = new FileWriter(my_file); fws.write(list.getText()); fws.close();
}
catch (IOException xcpt){
JOptionPane.showMessageDialog(null,”Файл нельзя изменить”);
}
}
}
Листинг 61. Запись в файл
В итоге изменений коснулись только блоки перехвата исключительных ситуаций и метод показа диалога (в листинге выделено жирным).
7. Обработка исключительных ситуаций
Исключительная ситуация – это такая ситуация, при которой обычный ход программы прерывается непредвиденными ошибками, такими ошибками, которые вызваны человеческим фактором и не известны вплоть до наступления самой ошибки. Можно попробовать исключить выполнение такой ошибки условным оператором до начала выполнения операции, которая может такую ошибку вызвать:
if (что то не так) { вывод сообщения об ошибке } else {
Выполнение задуманных действий
}
Однако такой подход является логически некорректным, поскольку при этом уходит много времени на проверку, и программа не выдает той производительности, которой могла бы достигнуть.
Для обработки таких нежелательных ситуаций в JAVA имеется блоки пробы, перехвата и выброса.
Для того, чтобы попытаться перехватить исключительную ситуацию, необходимо весь код программы, в котором может возникнуть исключительная ситуация охватить блоками try{ } и catch(){ }. Например, имеется некоторое окно, в котором есть три поля ввода и кнопка, при нажатии на кнопку, текст первого поля преобразуется в число и делится на преобразованный в число текст второго поля и выводится в третье поле. Запишем обработку события нажатия на кнопку:
public void actionPerformed(ActionEvent aevt){ tf3.setText(Long.toString(Long.valueOf(tf1.getText())/
Long.valueOf(tf2.getText())));
}
Где tf1, tf2 и tf3 – это имена полей ввода.
Какие же непредвиденные ситуации могут произойти в процессе выполнения этой программы? В данном случае два типа исключительных ситуаций – ArithmeticException
(арифметическое исключение) и NumberFormatException (исключение числового формата). В качестве арифметического исключения предполагается деление на 0, а в качестве исключения второго типа – это невозможность преобразовать букву или строку букв в цифру или число, а так же невозможность преобразовать пустую строку в цифру или число. Для перехвата таких нежелательных ситуаций поместим обработку события в блок try{}catch(){}:
try{tf3.setText(Long.toString(Long.valueOf(tf1.getText(
))/Long.valueOf(tf2.getText()))); }catch(ArithmeticException ae){
tf3.setText("Исключение типа ArithmeticException, перехвачено - " + ae);
}catch(NumberFormatException nfe){ tf3.setText("Исключение типа NumberFormatExcep-
tion, перехвачено - " + nfe);
}
Таким образом, программа начинает работать без ошибок, т.к. исключительные ситуации обрабатываются и выбрасываются.
Тот факт, что метод не обрабатывает возникшее в нем исключение, а просто выбрасывает его, это следует отмечать в заголовке этого метода служебным словом throws.
Исключительные ситуации делятся на непроверяемые и проверяемые, первые характеризуются тем, что компилятор их не проверяет, а вторые характеризуются тем, что при проверке компилятор замечает необработанные в методах исключения и считает ошибкой отсутствия в заголовке этих методов пометки throws.
В нашем примере исключение относится к типу непроверяемых и пометка словом throws необязательна. Почему компилятор не проверяет такие типы исключений? Это заключается в том, что эти исключения вызваны ошибками в программе, и, наиболее актуальный метод решения – исправить программу. Или, например, исключения класса Error непроверяемые потому, что их очень трудно отследить на этапе компиляции, а так же отследить место их
возникновения. Для примера, занесем процедуру деления в отдельный метод devide():
public long devide(String s1, String s2){ long s3;
s3 = Long.valueOf(s1)/Long.valueOf(s2); return s3;
}
В этом методе происходит деление внутренних переменных метода.
Затем, блок try изменим на:
try{
tf3.setText(Long.toString(devide(tf1.getText(), tf2.getText())));
}
Таким образом, уже используется отдельный метод, который, если бы исключения были бы проверяемыми, следовало бы оформить следующим образом:
public long devide(String s1, String s2) throws ArithmeticException, NumberFormatException {
long s3;
s3 = Long.valueOf(s1)/Long.valueOf(s2); return s3;
}
После чего оператором throw нужно «выбросить» исключение в блоке try:
try{ jTextField3.setText(Long.toString(devide(jTextField1.get-
Text(), jTextField2.getText()))); }catch(ArithmeticException ae){
jTextField3.setText("Исключение типа ArithmeticException,
перехвачено - " + ae); throw ae;
}catch(NumberFormatException nfe){ jTextField3.setText("Исключение типа NumberFormatException,
перехвачено - " + nfe); throw nfe;
}
Таким образом, методы, потенциально имеющие возможность вызова проверяемых исключений, необходимо помечать служебным словом throws и, в блоке try оператором throw выбрасывать исключения.
9. Апплеты
Апплеты – это программы, являющиеся несамостоятельными объектами, для запуска которых необходима какая-либо сторонняя программа, поддерживающая JVM. В частности апплеты используются в интернет-браузерах – программах отображения гипертекстового интернет контента.
Класс Applet является расширением класса Panel, то есть апплет – это ни что иное как усовершенствованная панель, на которую можно разместить некоторые компоненты ГИП, а так же на ней можно рисовать, используя класс Graphics.
Сначала рассмотрим код простейшего апплета, в котором происходит хаотичное заполнение области большим количеством линий разного цвета:
0 |
import java.awt.*; |
1 |
import java.applet.*; |
0 |
|
2 |
public class Firstapplet extends Applet{ |
0 |
|
3 |
public void init(){ |
0 |
|
4 |
} |
0 |
|
5 |
public void paint(Graphics g){ |
0 |
|
6 |
for(int i=1;i<3000;i++){ |
0 |
|
7 |
Color clr = new Color((int)(((Math.random()*255), |
0 |
|
8 |
(int)(Math.random()*255),(((int)(Math.random()*255)); |
0 |
(((g.setColor(clr); |
9 |
g.drawLine((int)(Math.random()*200), (int) ( |
1 |
0((Math.random()*200), (int)(Math.random()*200), (int) (
1 |
((Math.random()*200)); |
} |
|
1 |
} |
1 |
|
2 |
} |
1 |
|
3 |
|
Практически ничего нового в данной программе нет. Метод paint() (06-12) в цикле рисует 3000 линий со случайными координатами случайного полученного цвета.
Новым в данной программе является метод init()(04-05), который в листинге не реализован (пустой). Метод init() предназначен для начальной инициализации апплета, исполняющей системой Java вашего браузера он запускается автоматически. Этот метод является некоторой заменой конструктора ГИП в приложениях, в нем описываются и добавляются компоненты в контейнер.
Стоит так же заметить отсутствие метода main() в апплетах. Поскольку данный метод отсутствует, запустить виртуальной машине апплет как приложение не удастся.
Апплеты как и приложения с ГИП могут быть интерактивными, например, класс, расширяющий и определяющий апплет, может еще имплементировать интерфейс ActionListener и самостоятельно обрабатывать события, происходящие в собственных компонентах.
Для того, что бы апплет добавить на Web-страницу необходимо добавить в нужное место страницы тег <applet code = “” width = “” height = “”></applet>. В листинге, представленном ниже, описан код пустой Web-страницы с апплетом.
0<html>
1
0<body>
2
0 <applet code = "Firstapplet.class" width = 200 height =
3200>
0</applet>
4
0</body>
5
0</html>
6
Наиболее важным атрибутом тега applet является code, данный атрибут указывает браузеру где находится байт-код класса апплета.
10. Отладка и тестирование приложений
Отладка – это процесс пошаговой проверки программ и приложений с целью выявления ошибок логического типа. Логических ошибок именно потому, что будь в программе ошибки синтаксические, программа бы не запустилась, об этом бы предупредил компилятор на стадии компиляции, однако не все программы, которые запускаются и работают без сбоев, не имеют ошибок. С целью выявления таких ошибок были придуманы отладчики – специальные подмодули различных оболочек программирования, а иногда, даже и отдельные модули, как например, JUnit.
Процесс отладки ничем не отличается от простого запуска, за одним исключением – ход программы останавливается каждый раз, как будет достигнута очередная точка прерывания. Если точек прерывания не установлено, отладка не будет ничем отличаться от обычного запуска. Рассмотрим отладку на примере. Создайте новый класс с именем Debuging и введите предложенный в листинге код.
public class Debuging {
public static void main(String[] args){ for (int i=0;i<10;i++){
System.out.print("Шаг "+i+"\n");
}
}
}
Для запуска отладчика нажмите кнопку с изображением
жука.
При нажатии данной кнопки включается режим отладки
текущей программы, если окно кода программы активно. Если активна панель Package Explorer, тогда отладке подвергнется выбранный (выделенный) класс, если он имеет метод main(). Однако, данная кнопка, как и некоторые другие, имеет черный треугольник, нажав который, можно из списка выбрать нужный класс, если их более одного в проекте.
В поле кода программы есть столбец, в котором устанавливаются точки прерывания:
Для того чтобы поставить точку, нужно дважды щелкнуть мышью в данном столбце напротив нужной строки, для которой будет осуществляться остановка программы. Точки прерывания выглядят в виде маленьких красных квадратов. Если не установлена ни одна точка прерывания, режим отладки запустится, однако ничем не будет отличаться от простого запуска программы, нужно поставить хотя бы одну точку прерывания, что бы отладка имела смысл.
Установите точку прерывания напротив строки System.out-
.print("Шаг "+i+"\n");. Теперь можно приступать к отладке После того, как вы установите точку прерывания и
нажмете кнопку
, на экране появится диалоговое окно (рис. 31), предлагающее переключить режим рабочего стола из JAVA в Debug.
Для того что бы переключиться обратно в режим JAVA,
используйте кнопку
, находящуюся в верхнем правом углу рабочего стола. Далее, примите данное предложение, нажав кнопку «Yes», и в итоге рабочий стол примет следующий вид:
Рис. 32. Рабочий стол Debug
Это стандартный, по умолчанию, вид рабочего стола Debug, но вы можете его изменить, удаляя, добавляя или перетаскивая панели мышкой.
На данном рабочем столе можно выделить следующие основные компоненты:
●Окно Debug. В данном окне отображаются задействованные
вотладке элементы.
●Окно состояния переменных и точек прерывания. Вкладка Variables содержит список переменных, задействованных в текущей точке прерывания. Данное окно является наиболее важным в процессе отладки, оно производит мониторинг переменных на каждой точке прерывания. Именно с помощью данного окна программист может увидеть поведение объекта, изменение его свойств более тщательно в процессе выполнения программы. Вкладка Breakpoints содержит список точек прерывания, которые программист установил, их можно отключать и включать в процессе отладки, устанавливая, или удаляя галочку напротив нужной точки.
Влевом столбце указаны идентификаторы (имена) переменных, в правом их текущее значение.
●Панель Outline, редактор кода и консоль. Назначение данных элементов рассмотрено ранее.
Теперь программа запущена в режиме отладки. Начиная с самого начала, она доходит до первой попавшейся точки и останавливается, не выполняя оператор, находящийся на строке точки прерывания, программист может посмотреть состояние переменных программы. После того, как вы проанализируете состоянии программы на данном шаге, можно продолжать. Нажмите кнопку
(Resume) или клавишу F8 для продолжения выполнения программы. В нашем случае программа остановилась на операторе вывода данных в консоль, после продолжения выполнения, тело цикла продолжится выполнятся, т.к. в теле нашего цикла только один оператор, он выполнится и в консоль выведется
первая строка, на первом шаге переменная i=0, в этом можно убедиться просмотрев вкладку Variables окна состояния:
Состояние переменных на первом шаге
После вывода строки цикл начнет выполняться еще раз, пременная i изменится и станет равной 1. При этом в панели Variables она выделится желтым цветом, что сигнализирует о изменении ее значения:
Состояние переменных на втором шаге
И так далее, нажимая клавишу F8, или кнопку
, программа будет переходить от одной точки прерывания к другой. Если точка прерывания установлена на оператор, находящийся в цикле, программа в этом случае будет останавливаться на этой точке столько раз, сколько раз будет проходить цикл.
В отладчике Eclipse есть еще одна полезная функция, с помощью которой, можно увидеть состояния выражений. Например, нас интересует состояние логического выражения условия, при котором выполняется цикл, выделите нужный текст, в нашем случае это i<10 в блоке условия цикла и нажмите сочетание клавиш <Ctrl>+<Shift>+D, появится всплывающее окно, в котором будет отображен тип выражения (в нашем случае это boolean) и его состояние.
Когда программа дойдет до конца, отладка закончится. Для повтора отладки нужно еще раз нажать кнопку
. Для
остановки отладки и выполнения программы необходимо нажать кнопку
в панели Debug.
11. Поддержка, советы рекомендуемые ресурсы Ресурсы
Список рекомендуемой литературы по Eclipse. [Электронный ресурс] — http://www-128.ibm.com/developerworks/library/os- ecl-read/?S_TACT=105AGX01&S_CMP=LP
Ресурсы для разработчика в Eclipse http://www.ibm.com/developerworks/ru/opensource/top-projects/ eclipse.html
1.Документация по классам Java. [Электронный ресурс] — http://java.sun.com/docs/
2.Учебные пособия по Java (Java Tutorial). [Электронный ресурс] — http://java.sun.com/docs/books/tutorial/
3.Ответы на часто задаваемые вопросы (FAQ). Линден П. [Электронный ресурс] — http://www.afu.com/javafaq.html
Шилдт Г. Полный справочник по Java. - М:, Вильямс, 2007. - 1040 с.
Ноултон П. Java 2. - C-Пб:, BНV-Санкт Петербург, 2005. - 1072 с.
Конференции
1.Сетевая конференци программистов Java. Comp.lang.java.programmer
2.Сетевая конференци Comp.lang.java.*
3.
