- •Особенности языка Java
- •История Java
- •Характерные особенности Java
- •Разработка и выполнение Java приложения:
- •Понятие среды выполнения Java
- •Переносимость языка Java
- •Высокая производительность языка Java
- •Типы Java-приложений
- •Автономное (самостоятельное) приложение – application
- •Апплет – applet
- •Комбинированное приложение
- •Сервлет – servlet
- •Мидлет – midlet
- •Различия между автономными приложениями и апплетами
- •Автономное приложение
- •Апплет
- •Этапы жизненного цикла апплета
- •Этапы жизненного цикла в соответствии со стандартом Sun:
- •Этап инициализации
- •Этап запуска
- •Этап останова
- •Этап уничтожения
- •Этап рисования (перерисовки) окна апплета
- •Отличия Java от C++
- •Конструкторы классов
- •«Сборщик мусора»
- •Типы данных в Java
- •Простые типы
- •Ссылочные (объектные) типы
- •Строки в Java
- •Массивы в Java
- •Классы в Java
- •Особенности реализации
- •Пакеты
- •Управление доступом к элементам класса
- •Поля класса
- •Методы
- •Перегрузка и переопределение методов
- •Ключевые слова THIS и SUPER
- •Интерфейсы в Java
- •Понятие Java API
- •Пакеты ядра Java API (в JDK 1.0):
- •Развитие ядра Java API (в новой версии JDK и в Java 2)
- •Основные понятия AWT
- •Компоненты
- •Контейнеры
- •Компоновки. Менеджеры компоновки
- •События
- •События. Обработка событий
- •Иерархия классов-событий
- •Семантические события и их источники-компоненты AWT
- •Модель делегирования событий
- •Методы, объявленные в интерфейсах для семантических событий
- •Способы реализации блока прослушивания событий от AWT-компонента
- •Понятие класса-адаптера
- •Комбинированное приложение Java. Обработка события WindowEvent
- •Исключения в Java и их обработка
- •Иерархия классов исключений
- •Различия между исключениями Exception и ошибками Error
- •Организация обработки исключений в программе
- •Используемые операторы:
- •Как правильно организовывать обработку исключений
- •Понятия процесса и потока
- •Конструкторы класса Thread
- •Наиболее важные методы класса Thread
- •Способы создания потоков
- •Синхронизация потоков
- •Когда следует использовать синхронизацию потоков?
- •Механизм блокировки объекта
- •Способы использования ключевого слова synchronized
- •Синхронизированные методы
- •Оператор synchronized
- •Преимущества оператора synchronized:
- •Взаимодействие потоков: использование методов wait(), notify(), notifyAll()
- •Стандартные образцы кода использования методов
- •Поток-диспетчер событий AWT
- •Потоки и исключения
- •О группах потоков
- •Технология компонентного программирования JavaBeans
- •Понятие технологии компонентного программирования
- •Этап компиляции
- •Этап разработки
- •Этап создания приложения
- •Этап выполнения
- •Понятие компонентной модели
- •Основные требования к классам Bean-компонентов
- •Соглашения об именах
- •Соглашения об именах для свойств
- •Соглашения об именах для событий
- •Соглашения об именах для методов
- •Использование событий для управления свойствами
- •Связанные свойства
- •Преобразование обычного свойства в связанное
- •Ограниченные свойства
- •Преобразование обычного свойства в ограниченное
- •Ввод-вывод в Java: основные понятия
- •Основные группы классов и интерфейсов пакета java.io
- •Фильтрованные потоки
- •Буферизированные потоки
- •Принципы работы Buffered-потоков
- •Входные потоки
- •Выходные потоки
- •Канальные потоки
- •Синхронизация потоков данных
- •Понятие отражения (рефлексии)
- •Класс java.lang.Class
- •Классы пакета java.lang.reflect
- •Понятие интроспекции
- •Понятие сериализации
- •Обеспечение сериализуемости Bean
- •Выполнение базовой сериализации
- •Пример с сериализацией (см. SerializationDemo.java)
- •Настройка сериализации
- •Методы readObject и writeObject
- •Интерфейс Externalizable
- •Создание экземпляров сериализованных Bean
- •Приложение
- •// Файл HelloApplet.java
- •// Файл MyApplet.java
- •// Файл StringDemo.java
- •// Файл ConstrDemo.java
- •// Фрагменты файла AnimBallsPlus.java
Скачано с сайта http://ivc.clan.su
}
}
// Фрагменты файла AnimBallsPlus.java
/* Апплет с эффектом анимации, выполняющий операции чтения/записи
*в локальный файл при предоставлении соответствующих прав доступа.
*Пример использования буфериэированных символьных потоков чтения/записи в файл
*/
import java.applet.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.*;
public class AnimBallsPlus extends Applet implements ActionListener, Runnable
{
...
Panel p1, p2, p3; // Компоненты интерфейса
Button b1, b2, b3; TextArea fileText;
//Имя файла-журнала для записи информации о работе апплета
String fileName = "";
String ls; // Разделителе строк (признак конца строки)
//Буферизированный символьный поток записи в файл
BufferedWriter out;
//Инициализация апплета
public void init()
{
...
// Панель для чтения файла-журнала p3 = new PanelWithInsets(); p3.setLayout(new BorderLayout()); p3.setBackground(Color.blue); fileText = new TextArea(); fileText.setBackground(Color.white);
p3.add(fileText, BorderLayout.CENTER); fileName = getParameter("FileName"); if (fileName == null)
{
fileName = "log.txt";
}
ls = System.getProperty("line.separator"); b3 = new Button("Чтение файла-журнала"); b3.addActionListener(new ActionListener()
{
// разделитель строк
public void actionPerformed(ActionEvent e)
{
try
{
//Сброс данных из буфера потока (запись в файл) out.flush();
//Чтение из файла
//Создание буферизированнохю символьного потока чтения из файла
BufferedReader in =
new BufferedReader(new FileReader(fileName)); String s = "", line;
while ((line = in.readLine()) != null)
{
s += line + "\n";
}
fileText.setText(s);
in.close();
}
78
Скачано с сайта http://ivc.clan.su
catch (IOException ex)
{
fileText.setText("Ошибка чтения файла: " + ls); fileText.append(ex.toString());
}
}
});
p3.add(b3, BorderLayout.NORTH); add(p3);
try
{
// Создание буферизированного символьного потока записи в файл out = new BufferedWriter(new FileWriter(fileName));
}
catch (IOException ex)
{
fileText.setText("Ошибка при создании потока записи:" + ls); fileText.append(ex.toString() + ls);
}
catch (SecurityException ex)
{
fileText.setText("Нет разрешения доступа к файлу: " + ls); fileText.append(ex.toString() + ls); b3.setEnabled(false);
}
if (out != null)
{
Calendar c = Calendar.getInstance(); String dateMessage =
"Дата и время: " + c.get(Calendar.DAY_OF_MONTH) + "/"
+(c.get(Calendar.MONTH) + 1) + " - " + c.get(Calendar.YEAR) + " "
+c.get(Calendar.HOUR_OF_DAY) + ":" + c.get(Calendar.MINUTE); writeLogMessage(dateMessage);
writeLogMessage("Инициализация апплета завершена");
}
}
//Запуск апплета public void start()
{
animThread = new Thread(this); // создание потока для анимации animThread.start(); // запуск потока
b1.setEnabled(false); b2.setEnabled(true); if (out != null)
{
writeLogMessage("Поток апплета запущен");
}
}
//Останов апплета
public void stop()
{
animThread = null; // для завершения выполнения метода run(), // т.е. работы потока
b1.setEnabled(true); b2.setEnabled(false); if (out != null)
{
writeLogMessage("Поток апплета остановлен");
}
}
// Уничтожение апплета public void destroy()
{
if (out != null)
79
Скачано с сайта http://ivc.clan.su
{
writeLogMessage("Выполнение апплета завершено"); try
{
out.close();
}
catch (IOException ex)
{
}
}
}
...
//Обработка событий от кнопок "Запуск" и "Останов" public void actionPerformed(ActionEvent e)
{
String acm = e.getActionCommand(); if ("Запуск".equals(acm))
{
start();
}
if ("Останов".equals(acm))
{
stop();
}
}
//Вывод сообщения в буферизированный поток для записи в файл private void writeLogMessage(String message)
{
try
{
out.write(message);
out.newLine();
}
catch (IOException ex)
{
fileText.setText("Ошибка записи в файл:" + ls); fileText.append(ex.toString() + ls);
}
}
...
}
//Файл PipeDemo.Java
//Демонстрация применения канального потока для обеспечения
//взаимодействия потока вычислений типа TextGenerator
//с потоком вычислений, получающим сгенерированный текст.
//Источник: Арнолд К., Гослинг Дж., Холмс Д. Язык программирования
//Java. - М.: Издательский дом "Вильяме", 2001, с. 390.
import java.io.*;
//Класс потока вычислений, который генерирует текст,
//осуществляя запись символов (букв алфавита) в поток данных
//типа Writer.
//Таким потоком может быть, как это показано в примере ниже,
//канальный поток PipedWriter.
class TextGenerator extends Thread
{
private Writer out; // ссылка на выходной символьный поток public TextGenerator(Writer out)
{
this.out = out;
}
public void run()
{
try
80
Скачано с сайта http://ivc.clan.su
{
try
{
for (char c = 'а'; c <= 'z'; c++) out.write(c);
}
finally
{
out.close();
}
}
catch (IOException e)
{
getThreadGroup().uncaughtException(this, e);
}
}
}
//Класс, метод main которого выполняется в основном потоке
//вычислений и осуществляет чтение данных из потока PipedReader,
//связанного с потоком PipedWriter
class PipeDemo
{
public static void main(String args[]) throws IOException
{
//Создание пары потоков Piped.
//He имеет значения, в каком порядоке создаются объекты
//пары потоков записи-чтения!
PipedWriter out = new PipedWriter();
PipedReader in = new PipedReader(out);
//Создание и запуск потока вычислений, выполняющего
//генерирование символов
TextGenerator data = new TextGenerator(out); data.start();
//Чтение символов, получаемых от генератора текста, и
//запись их в стандартный поток вывода типа PrintStream int ch;
while ((ch = in.readO) != -1) // читать, пока не конец потока System.out.print((char)ch);
//Можно записать символ в стандартный поток вывода и так:
//System.out.write(String.valueOf((char)ch).getBytes());
//но, разумеется, метод print гораздо удобнее!
System.out.println();
}
}
//Файл ReflectionDemo.java
//Демонстрация использования возможностей отражения для анализа класса,
//который указывается в параметре командной строки.
//Источник:
//Ноутон П., Шилдт Г. Java 2. - СПб.: БХВ-Петербург, 2000, с. 787-788. import java.lang.reflect.*; //используется пакет, поддерживающий отражение public class ReflectionDemo
{
public static void main(String args [])
{
try
{
//Получение объекта типа Class для анализируемого класса
Class с = Class.forName(args[0]);
//Имя анализируемого класса, который загружается с помощью статического
//метода Class.forName(), становится известным только во время
//выполнения программы, вся информация об этом классе извлекается во
//время выполнения.
System.out.println("Constructors:");
81
Скачано с сайта http://ivc.clan.su
//Получение информации о конструкторах
Constructor constructors[] = с.getConstructors(); for (int i = 0; i < constructors.length; i++)
{
System.out.println(constructors[i]);
}
System.out.println("Fields:");
//Получение информации о полях класса
Field fields[] = с.getFields();
for (int i = 0; i < fields.length; i++)
{
System.out.println(fields[i]); } System.out.println("Methods:");
// Получение информации о методах
Method methods[] = с.getMethods();
for (int i = 0; i < methods.length; i++)
{
System.out.println(methods[i].getName());
}
}
catch (Exception e)
{
System.out.println("Exception: " + e);
}
}
}
//Файл BeanDumper.java
//Пример использования интроспекции для получения информации о компоненте
//Исходная версия:
//Эккель Б. Философия Java. Библиотека программиста. - СПб.: Питер, 2001,
//с. 631-632.
import java.beans.*; import java.lang.reflect.*; import java.awt.*;
import java.awt.event.*; import java.applet.*;
public class BeanDumper extends Applet
{
TextField query = new TextField(20); TextArea results = new TextArea(); public void init()
{
setLayout(new BorderLayout()); Panel p = new Panel(); p.setLayout(new FlowLayout());
p.add(new Label("Полное составное имя компонента:"));
р.add(query);
add(p, BorderLayout.NORTH); add(results, BorderLayout.CENTER);
//Регистрация блока прослушивания Action-события от текстового поля
Dumper dmpr = new Dumper(); query.addActionListener(dmpr);
//Занесение текстовой строки-запроса в текстовое поле query.setText("colorsbean.ColorsBean");
//Программный запуск события
dmpr.actionPerformed(
new ActionEvent(dmpr, ActionEvent.ACTION_PERFORMED, ""));
}
// Блок прослушивания Action-события от текстового поля class Dumper implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
82
Скачано с сайта http://ivc.clan.su
String name = query.getText(); Class с = null;
try
{
с = Class.forName(name);
}
catch (ClassNotFoundException ex)
{
results.setText("He могу найти " + name); return;
}
try
{
dump(с);
}
catch (SecurityException ex)
{
results.setText("Отказано в доступе к " + name); return;
}
}
}
//Метод добавления строки в текстовую область public void prt(String s)
{
results.append(s + "\n");
}
//Метод исследования класса Bean и вывода результатов в текстовую область public void dump(Class bean)
{
results.setText(""); Beanlnfo bi = null; try
{
//Получение объекта Beanlnfo для класса Bean.
//Исследование класса проводится до класса Java.lang.Object.class.
bi = Introspector.getBeanlnfo(bean, java.lang.Object.class);
}
catch (IntrospectionException e)
{
prt("Исследование невозможно " + bean.getName()); return;
}
//Получение массива дескрипторов свойств:
PropertyDescriptor[] prop = bi.getPropertyDescriptors(); for (int i = 0; i < prop.length; i++)
{
Class p = prop[i].getPropertyType(); if (p != null)
prt("Тип свойства:\n " + p.getName()); prt("Имя свойства:\n" + prop[i].getName()); Method readMethod = prop[i].getReadMethod(); if (readMethod != null)
prt("Метод для чтения:\n " + readMethod); Method writeMethod = prop[i].getWriteMethod(); if (writeMethod != null)
prt("Метод для записи:\n " + writeMethod); prt("==========================");
}
prt("Открытые (public) методы: ");
//Получение массива дескрипторов методов: MethodDescriptor[] methods = bi.getMethodDescriptors(); for (int i = 0; i < methods.length; i++)
prt(methods[i].getMethod().toString());
83
Скачано с сайта http://ivc.clan.su
prt("=========================="); prt("Поддержка событий: ");
// Получение массива дескрипторов набора событий, запускаемых Bean:
EventSetDescriptor[] events = bi.getEventSetDescriptors();
for (int i = 0; i < events.length; i++)
{
prt("Имя события:\n " + events[i].getName()); prt("Тип блока прослушивания:\n " +
events[i].getListenerType().getName()); Method[] lm = events[i].getListenerMethods(); for (int j = 0; j < lm.length; j++)
prt("Метод блока прослушивания:\n " + lm[j].getName()); MethodDescriptor[] lmd = events[i].getListenerMethodDescriptors(); for (int k = 0; k < lmd.length; k++)
prt("Описание метода:\n " + lmd[k].getMethod()); Method addListener = events[i].getAddListenerMethod();
prt("Метод для добавления блока прослушивания:\n " + addListener); Method removeListener = events[i].getRemoveListenerMethod(); prt("Метод для удаления блока прослушивания:\n " + removeListener); prt("==========================");
}
}
}
//Файл ColorsBeanBeanlnfо.java
//Пример класса Beanlnfo для простого Bean-компонента.
//Объект этого класса создается в результате интроспекции
//и используется визуальной средой проектирования для
//предоставления разработчику информации о компоненте.
//Класс типа Beanlnfo должен размещаться в одном пакете с классом компонента
//и иметь то же имя с добавлением Beanlnfo
package colorsbean; import java.beans.*;
public class ColorsBeanBeanlnfo extends SimpleBeanlnfo
{
// Класс Bean-компонента ColorsBean
private final static Class beanClass = colorsbean.ColorsBean.class;
//В таблице свойств для компонента ColorsBean будут показаны
//только свойства, дескрипторы которых возвращаются данным
//методом в массиве дескрипторов:
public PropertyDescriptor[] getPropertyDescriptors()
{
try
{
//Экземпляр класса PropertyDescriptor создаѐтся для каждого
//свойства, представляемого в таблице свойств для настройки.
//Применяемый конструктор работает со свойствами, которые имеют
//стандартные get/set методы. Первый параметр - имя свойства,
//определѐнное в программе через методы get/set. Первая буква
//свойства должно быть строчной. Например, для методов
//"getBackground" и "setBackground" свойство будет называться
//"background".
PropertyDescriptor rectangular =
new PropertyDescriptor("rectangular", beanClass); PropertyDescriptor background =
new PropertyDescriptor("background", beanClass); PropertyDescriptor font = new PropertyDescriptor("font", beanClass); // Массив дескрипторов свойств:
PropertyDescriptor rv[] = { rectangular, background, font }; return rv;
}
catch (IntrospectionException e)
{
84
Скачано с сайта http://ivc.clan.su
throw new Error(e.toString());
}
}
//В списке событий, поддерживаемых компонентом ColorsBean, будут
//представлены только события, дескрипторы которых возвращаются
//данным методом в массиве дескрипторов:
public EventSetDescriptor[] getEventSetDescriptors()
{
//Используется один из конструкторов класса EventSetDescriptor.
//Первый параметр конструктора - класс объекта,
//запускающего событие;
//второй параметр - программное имя события (первая буква
//является строчной);
//третий параметр - объект типа Class интерфейса блока
//прослушивания событий данного типа;
//четвѐртый параметр - список имен методов обработки событий,
//объявленных в интерфейсе;
//пятый и шестой параметры - имена методов источника событий,
//используемых для регистрации и удаления блока прослушивания. try
{
EventSetDescriptor mouse = new EventSetDescriptor(beanClass, "mouse", java.awt.event.MouseListener.class, new String[]
{ "mouseClicked", "mousePressed", "mouseReleased", "mouseEntered", "mouseExited" },
"addMouseListener", "removeMouseListener");
//Экранное имя события, показываемое разработчику: mouse.setDisplayName("mouse event");
//Массив дескрипторов событий:
EventSetDescriptor[] rv = { mouse };
//Если не следует открывать разработчику список событий,
//создается пустой массив:
//EventSetDescriptor[] rv = {};
return rv;
}
catch (IntrospectionException e)
{
throw new Error(e.toString());
}
}
//В списке методов компонента ColorsBean будут представлены
//только методы, дескрипторы которых возвращаются данным методом
//в массиве дескрипторов:
public MethodDescriptor[] getMethodDescriptors()
{
try
{
MethodDescriptor change =
new MethodDescriptor(beanClass.getMethod("change", (Class[])null));
//null - ссылка на массив объектов типа Class, представляющих параметры
//метода.
MethodDescriptor[] rv = { change }; return rv;
}
catch (NoSuchMethodException e)
{
return null; // возврат к отражению нижнего уровня
}
}
}
//Файл SerializationDemo.java
//Демонстрация сериализации и десериализации объекта.
//Источник: Ноутон П., Шилдт Г. Java 2. - СПб.: БХВ-Петербург, 2000,
85
Скачано с сайта http://ivc.clan.su
// с.545-546. import java.io.*;
public class SerializationDemo
{
public static void main(String args[])
{
//Сериализация объекта try
{
MyClass object1 = new MyClass("Hello", -7, 2.7e10); System.out.println("object1: " + object1); FileOutputStream fos = new FileOutputStream("serial"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(object1);
oos.flush();
oos.close();
}
catch (Exception e)
{
System.out.println("Исключение при сериализации: " + e); System.exit(0);
}
//Десериализация объекта
try
{
MyClass object2;
FilelnputStream fis = new FilelnputStream("serial"); ObjectlnputStream ois = new ObjectlnputStream(fis); object2 = (MyClass)ois.readObject();
ois.close();
System.out.println("object2: " + object2);
}
catch (Exception e)
{
System.out.println("Исключение при десериализации: " + e); System.exit(0);
}
}
}
class MyClass implements Serializable
{
String s; int i; double d;
public MyClass(String s, int i, double d)
{
this.s = s; this.i = i; this.d = d;
}
public String toString()
{
return "s=" + s + "; i=" + i + "; d=" + d;
}
}
/* Вывод программы:
object1: s=Hello; i=-7 ; d=2.7E10 object2: s=Hello; i=-7 ; d=2.7E10
*/
//Файл BeanlnstantiateDemo.java
//Демонстрация создания экземпляра сериализованного Bean. import java.awt.*;
86
Скачано с сайта http://ivc.clan.su
import java.awt.event.*; import java.io.*; import java.beans.*; import colorsbean.*;
public class BeanlnstantiateDemo
{
public static void main(String args[])
{
try
{
WinAdapter wa = new WinAdapter(); Frame fl = new Frame("1"); f1.setLocation(100, 100);
//Создание экземпляра Bean и размещение его в окне фрейма №1
ColorsBean cbl =
(ColorsBean)Beans.instantiate(null, "colorsbean.ColorsBean"); fl.add(cbl, BorderLayout.CENTER);
f1.addWindowListener(wa); fl.setSize(200, 200); f1.Show();
//Создание и настройка другого экземпляра Bean
ColorsBean сЬ21 =
(ColorsBean)Beans.instantiate(null, "colorsbean.ColorsBean"); cb21.setRectangular(true); cb21.setBackground(Color.yellow); cb21.setFont(new Font("Dialog", Font.BOLD, 18));
// Сериализация Bean
FileOutputStream fos = new FileOutputStream("colbean.ser"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(cb21);
oos.close();
//Чтобы десериализованный Bean реагировал на щелчок мыши,
//т.е. обрабатывал события MouseEvent,класс Bean не должен
//содержать анонимного внутреннего несериализуемого
//класса-адаптера (см. файл colorsbean.ColorsBean.Java -
//версию класса компонента, реализующего интерфейс
//MouseListener)
//Десериализация Bean и размещение его в окне фрейма №2
//ColorsBean cb22 = (ColorsBean)Beans.instantiate(null, "colbean"); // или
Component cb22 = (Component)Beans.instantiate(null, "colbean"); Frame f2 = new Frame("2");
f2.setLocation(400, 100); f2.add(cb22, BorderLayout.CENTER); f2.addWindowListener(wa); f2.setSize(200, 200);
f2.show();
}
catch (Exception e)
{
System.err.println(e); System.exit(0);
}
}
}
// Класс, производный от класса-адаптера WindowAdapter class WinAdapter extends WindowAdapter
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
}
87