Распределенные системы обработки информации
public class MoneyCounter implements ActionListener {
public void actionPerformed( ActionEvent e ) {
money += money * percent;
System.out.println( "Денег сейчас: " + money );
}
}
1.8 Вложенные классы и интерфейсы
Вложенный (inner) класс или интерфейс – класс или интерфейс, определенный внутри другого класса. Объект вложенного класса имеет доступ ко всем
полям и методам содержащего его класса (включая закрытые). Его можно скрыть от других классов пакета. Можно создавать анонимные вложенные классы.
class MyClass {
.
private class MyInnerClass { … }
}
Обращение из вложенного класса к методам и полям внешнего: можно просто someMethod(), а можно так: MyClass.this.SomeMethod().
Создание экземпляра вложенного класса:
MyInnerClass obj = new MyInnerClass();
MyInnerClass obj = this.new MyInnerClass();
А если вне класса:
MyClass myobj = new MyClass();
MyClass.MyInnerClass obj = myobj.new MyInnerClass();
Вложенный класс можно определить даже внутри метода (локальный вложенный класс). Они объявляются без спецификаторов видимости.
Анонимные внутренние классы:
Чаще всего используется в обработчиках GUI:
MyInterface obj = new MyInterface() { … };
myButton.addActionListener( new ActionListener() {
public void actionPerformed( ActionEvent e ) {
doSmth( );
}
} );
Вложенный класс можно объявить static, в этом случае он не будет иметь доступ к нестатическим полям и методам внешнего класса. Это полезно, если экземпляр вложенного класса создается в статическом метода внешнего класса.
Вложенные классы, определенные в интерфейсах, считаются по умолчанию статическими и публичными.
1.9 Цикл for-each, аргументы переменной длины, настраиваемые типы в Java
Цикл for each позволяет последовательно перебрать все элементы набора данных.
for (ElementType element : collection) { … }
Объект collection должен поддерживать интерфейс Iterable или быть массивом:
public interface Iterable<E> {
Iterator<E> iterator();
}
Метод с переменным числом параметров:
int sum(int… args);
void format(String fmt, Object… objs);
Многоточие здесь эквивалентно [], то есть args и objs – массивы аргументов указанного типа.
Настраиваемые типы (generics) – способ параметризации класса другим классом. Обычно применяется в коллекциях объектов.
Использование:
LinkedList<Integer> li = new LinkedList<Integer>();
li.add(new Integer(0));
Объявление:
class LinkedList<T> {
void add(T element) { … }
}
Ограничение:
class MyClass<T extends Exception> { … }
Здесь T – подтип класса Exception.
Можно использовать несколько параметров:
class MyClass<T, E, M> {…}
Можно параметризировать метод:
<T> void method(T[] a, Colletion<T> c) { … }
Параметр ? обозначает любой тип:
ArrayList<?> a = new ArrayList<Number>();
Можно также указать ограничения:
ArrayList<? extends Shape> a = new ArrayList<Triangle>(); /* Triangle – подкласс Shape */
ArrayList<? super Triangle> a = new ArrayList<Shape>(); /* Shape – базовый для Triangle */
Ограничения generics: нельзя использовать простые типы в качестве параметров, нельзя определять параметризированные массивы, нельзя использовать generic-типы в исключениях, нельзя использовать instanceof, нельзя задавать значения по умолчанию для параметров типов, нельзя использовать тип-параметр для создания объекта, нельзя клонировать объект, имеющий тип параметра. Механизм generics реализуется компилятором, на уровне виртуальной машины про это ничего не известно. При параметризации не создаются новые классы (ключевое отличие от templates в C++).
1.10 Многопоточность в Java: создание потоков
Класс, код которого будет выполняться в другом потоке, должен реализовывать интерфейс Runnable:
public interface Runnable {
void run();
}
Затем действуем так:
MyRunnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();
Можно также унаследовать свой класс от Thread (он реализует Runnable), так еще проще.
Поток завершает работу, когда метод run() возвращает управление. Можно также запросить прерывание потока, вызвав t.interrupt(). После этого поток может проверить статус прерывания:
if( Thread.currentThread( ).isInterrupted( ) ) { … }
Если interrupt() вызван для заблокированного потока, он завершается и выбрасывает исключение InterruptedException.
Поток блокируется, если для него вызван sleep(), если он выполняет блокирующий ввод-вывод, если он пытается заблокировать заблокированный объект, если он ожидает выполнения условия, если для него вызван метод suspend() (устаревший).
1.11 Многопоточность в Java: синхронизация
Синхронизация в многопоточном приложении требуется в ситуации гонки (race condition). В этом случае требуется ограничить выполнение фрагмента кода одним потоком.
Раньше использовалось ключевое слово synchronized, которым помечается метод класса. Этот метод будет выполняться только одним потоком одновременно. Достигается за счет неявного создания объекта блокировки.
Более гибкий способ – использование объектов блокировок: java.util.concurrent.locks.ReentrantLock.
myLock.lock(); // объект ReentrantLock
try { … }
finally { myLock.unlock(); }
Объект ReentrantLock может блокироваться одним потоком несколько раз, но потом должен быть столько же раз разблокирован.
С объектом блокировки можно связать объект условия (типа Condition):
myCondition = myLock.newCondition();
Для условия определены методы:
myCondition.await() // уступить объект блокировки.
myCondition.signalAll() /* все ожидающие потоки возобновят выполнение */
Обычно делают так:
while (!(можно продолжать))
myCondition.await();
Каждый объект может быть объектом блокировки. Для этого в классе Object есть методы notifyAll(), notify(), wait().
Синхронизированные блоки:
synchronized(obj) { … }
Здесь obj – любой объект, который выступает в качестве объекта блокировки.
Можно сделать проще – объявить переменную volatile, тогда синхронизация доступа к этой переменной будет происходить автоматически.
Блокирующие очереди – используются для ситуации читателей и писателей. Классы: LinkedBlockingQueue, ArrayBlockingQueue, PriorityBlockingQueue, DelayQueue. Такие очереди обеспечивают синхронизированный доступ к своим элементам и имеют методы: add (добавить элемент), remove (удалить из головы), element (возвратить из головы без извлечения), offer (добавляет элемент с проверкой переполнения), poll (удаляет из головы с проверкой пустоты), peek (возвращает из головы без извлечения с проверкой пустоты), put (блокирующее добавление элемента), take (блокирующее удаление из головы).
1.12 Ввод-вывод в Java: общие сведения
В Java ввод-вывод основывается на потоках (streams) и файлах (files).
Другие рефераты на тему «Программирование, компьютеры и кибернетика»:
Поиск рефератов
Последние рефераты раздела
- Основные этапы объектно-ориентированного проектирования
- Основные структуры языка Java
- Основные принципы разработки графического пользовательского интерфейса
- Основы дискретной математики
- Программное обеспечение системы принятия решений адаптивного робота
- Программное обеспечение
- Проблемы сохранности информации в процессе предпринимательской деятельности