Выбери формат для чтения
Загружаем конспект в формате pdf
Это займет всего пару минут! А пока ты можешь прочитать работу в формате Word 👇
Содержание
Введение ........................................................................................................................................ 3
Установка и настройка JDK, среды разарботки ........................................................................... 3
Основные конструкции языка Java ........................................................................................ 5
Hello, World! .......................................................................................................................................... 5
Комментарии ........................................................................................................................................ 5
Типы данных ........................................................................................................................................ 5
Переменные ........................................................................................................................................... 7
Константы ............................................................................................................................................. 7
Операции (арифметические, логические) ....................................................................................... 7
Преобразование и приведение типов ............................................................................................... 8
Строки .................................................................................................................................................... 9
Ввод/вывод в консоль ....................................................................................................................... 10
Ветвления ............................................................................................................................................ 10
Циклы .................................................................................................................................................. 10
Объекты, классы ....................................................................................................................... 12
Пакеты ................................................................................................................................................. 14
Импортирование классов ................................................................................................................. 14
Наследование ............................................................................................................................. 16
Классы, суперклассы и подклассы................................................................................................. 16
Класс Object ........................................................................................................................................ 16
hashCode() и equals() .......................................................................................................................... 17
toString() ............................................................................................................................................... 17
Переопределение методов ................................................................................................................ 17
Абстрактные классы ......................................................................................................................... 18
Модификаторы доступа .................................................................................................................... 19
Интерфейсы ........................................................................................................................................ 19
Enum ............................................................................................................................................ 20
Collections .................................................................................................................................... 20
Исключения................................................................................................................................ 21
Разработка приложений с графическим интерфейсом ...................................................... 23
Фреймы ................................................................................................................................................ 23
Java 2D .................................................................................................................................................. 24
1
Основные компоненты Swing .......................................................................................................... 28
Компоновка элементов ..................................................................................................................... 29
Обработка событий ........................................................................................................................... 29
Многопоточность ...................................................................................................................... 31
Состояние потока ............................................................................................................................... 32
Синхронизация потоков ................................................................................................................... 32
2
Введение
Java – объектно-ориентированный язык программирования, разработанный
компанией Sun Microsystems (теперь ее уже не существует, так как она была
куплена Oracle в 2010 году). Формально, Java является не только языком
программирования, а целой платформой, которая включает в себя
непосредственно язык программирования, мощную библиотеку, содержащую
огромный объем кода, пригодного для повторного изучения и среду дял
выполнения программ, которая обеспечивает безопасность, независимость от
операционной системы и автоматическую «сборку мусора».
Одной из основных особенностей языка Java, как уже было сказано выше,
является независимость от операционной системы. Это достигается путем
использования виртуальной машины. Код программы не компилируется, а
интерпретируется в байт-код, который выполняется виртуальной машиной,
преобразующей его в набор машинных команд. Таким образом, программа,
написанная на Java может быть выполнена на практически любой
операционной системе, где установлена виртуальная Java машина (Java
Virtual Machine - JVM). Скачать Java машину можно на официальном сайте
компании Oracle(http://www.oracle.com/technetwork/java/index.html).
Установка и настройка JDK, среды разарботки
Для написания, запуска и отладки программ, написанных на Java потребуется
JDK(Java Developer Kit), который включает в себя как саму виртуальную
машину, компилятор, так и весь набор необходимых библиотек. Скачать
последнюю
JVM
можно
по
ссылке
http://www.oracle.com/technetwork/java/javase/downloads/index.html . Весь код,
который будет встречаться в процессе обучения, гарантированно работает
начиная с JDK 6.0.
Для более удобной разработки и отладки программ на Java рекомендуется
использовать одни из следующих сред разработки.
3
• Eclipse (http://www.eclipse.org/downloads/. Выбрать Eclipse IDE for Java
Developers).
• NetBeans (https://netbeans.org/downloads/. Выбрать Java SE).
Все,
приведенные
выше,
среды
разработки
являются
абсолютно
бесплатными и имеют весь необходимый функционал.
4
Основные конструкции языка Java
Hello, World!
Начнем изучение языка с классического примера – написания программы
“Hello, World!” Далее будет рассмотрено как создавать новый Java проект в
среде разработки Eclipse. Создание проектов в других средах разработки
аналогично.
Комментарии
Комментарии в Java, как и в большинстве языков программирования,
игнорируются при выполнении программы. В языке Java существует два
основных способа выделения комментариев в тексте.
• Две косые черты (//). Комментарий начинается сращу ща символами //
и продолжается до конца строки.
System.out.println(“Hello, world!”);
// Это комментарий, он игнорируется компилятором.
• Блочные комментарии реализуются с помощью разделителей /* и */.
System.out.println(“Hello, world!”);
/* Это блочный комментарий.
Он может быть на несколько строк.*/
Типы данных
Язык Java является строго типизированным. Это значит, что тип каждой
переменной должен быть объявлен. Всего в Java восемь примитивных типа
данных. Четыре из них целочисленные, два – для действительных чисел,
один – символ в формате Unicode и последний – логическое значение.
Целочисленные типы используются для представления как положительных,
так и отрицательных чисел, не имеющих дробной части.
• int – занимает в памяти 4 байта и может хранить числа от -2147483648
до 2147483647.
5
• short – занимает в памяти 2 байта и может хранить числа от -32768 до
32767.
• long – занимает в памяти 8 байт и может хранить числа от 9223372036854775808 до 9223372036854775807.
• byte – занимает в памяти один байт и может хранить числа от -128 до
127.
В языке Java диапазоны целочисленных типов не зависят от машины, на
которой выполняется программа. Это существенно упрощает перенос
программы с одной платформы на другую.
Типы с плавающей точкой представляют значения, имеющие дробную часть.
• float – занимает в памяти 4 байта и может хранить числа от 3,30282347Е до 3,30282347Е.
• double – занимает в памяти 8 байт и может хранить числа от 1,7976931348623157Е до 1,7976931348623157Е.
Тип char используется для представления индивидуальных символов. Любой
символ в Java можно представить в виде кодовой единицы Unicode, которую
можно выразить шестнадцатеричным числом в диапазоне от \u0000 до
\uFFFF.
В Java предусмотрены некоторые спецсимволы, которые могут быть знакомы
по другим языкам программирования.
• \b – возврат на одну позицию.
• \t – табуляция.
• \n – переход на новую строчку.
• \r – возврат каретки.
• \” – двойная кавычка.
• \’ – одинарная кавычка.
• \\ - обратная косая черта.
Тип boolean, отвечающий за хранение логических переменных, имеет два
значения: true и false. Преобразование переменных типа boolean в
целочисленные и наоборот невозможно.
6
Переменные
В языке Java каждая переменная имеет тип. При объявлении переменной
сначала указывается ее тип, а затем ее имя. Ниже приведено несколько
примеров объявления переменных.
double price;
int age;
long timeInMsec;
boolean fl;
Имена переменных должны начинаться с любого символа Unicode,
являющегося буквой.
После объявления переменной ее нужно инициализировать с помощью
оператора присваивания, поскольку использовать переменную, которой не
присвоено никакого значения, невозможно. Например,
int n =10;
int v;
v = 4;
Константы
В языке Java для обозначения констант используется ключевое слово final.
final double pi = 3.14;
Ключевое слово final означает, что присвоить какое0либо значение данной
переменной можно лишь один раз и менять его нельзя.
Операции (арифметические, логические)
Для обеспечения операций сложения, вычитания, умножения и деления в
языке Java используются обычные арифметические операции + - * /.
Операция / обозначает целочисленное деление, если оба ее аргумента
являются целыми числами. В противном случае эта операция обозначает
деление чисел с плавающей точкой. Остаток от деления целых чисел
обозначается символом %.
7
Также
в
языке
Java
предусмотрена
сокращенная
запись
бинарных
арифметических операций. Например, оператор
x += 4;
эквивалентен
x = x + 4;
В языке Java, как и в языках С и С++, есть операции инкрементирования и
декрементирования: в результате вычисления выражения n++ к текущему
значению переменной n прибавляется единица, а n-- уменьшает n на единицу.
Язык Java содержит полный комплект операций отношений. Чтобы
проверить равенство, следует использовать символы ==. Например, значение
выражения 3==7 равно false.
Для проверки неравенства используются символы !=. Так, значение 3 != 7
равно true.
Кроме того, в языке Java есть обычные операции < (меньше), > (больше), <=
(меньше или равно), >= (больше или равно).
Также, как и в С++, используются символы && для логической операции
«и», а также символы || для обозначения логической операции «или». Как
обычно, знак восклицания означает логическую операцию отрицания.
Операция && и || задают вычисление по сокращенной схеме, согласно
которой, если первый элемент определяет значение всего выражения, то
остальные элементы не вычисляются.
Преобразование и приведение типов
Часто возникает необходимость преобразовать один числовой тип в другой.
На рис.1 показаны допустимые преобразования.
Если два значения объединяются бинарной операцией (анпример, n+f, где n –
целое число, а f – число с плавающей точкой), то перед выполнением
операции оба операнда преобразовываются в числа одинакового типа.
• Если хотя бы один из операндов имеет тип double, то второй тоже
преобразовывается в число типа double.
8
• В противном случае, если хотя бы один из операндов имеет тип float,
то второй тоже преобразовывается в тип float.
• В противном случае, если хотя бы один из операндов имеет тип long, то
второй тоже преобразовывается в число long.
• В противном случае оба операнда преобразовываются в числа типа int.
Приводить числовые типы можно и явным образом. Например,
double x = 9.997;
int n = (int) x;
При таком приведении дробная часть числа просто отбрасывается, т.е. в n
будет записано число 9.
Строки
Строки Java – это последовательность символов Unicode.
В языке Java нет встроенного типа для строк. Вместо этого стандартная
библиотека языка содержит класс String. Каждая строка, помещенная в
кавычки, представляет собой экземпляр класса String.
String s = “”; // пустая строка
String greeting = “Hello”;
Язык Java, как и большинство языков программирования, дает возможность
использовать знак + для объединения (конкатенации) двух строк.
String str1 = “Hello, ”;
String str2 = “world!”;
String message = str1 + str2; // “Hello, world!”
В классе String отсутствуют методы, которые позволяли бы изменить
символы в существующей строке.
Для получения информации о всех доступных методах по работе со строками
следует
обратиться
к
официальной
документации.
http://docs.oracle.com/javase/8/docs/api/java/lang/String.html
9
Ввод/вывод в консоль
Как уже рассматривалось ранее, для вывода информации на экран на
стандартное
устройство
вывода
(т.е.
в
консольное
окно)
можно
воспользоваться методом System.out.println(). Чтение из «стандартного
входного потока» System.in не так просто. Для того, чтобы организовать
чтение информации с консоли, вам надо создать объект Scanner и связать его
со стандартным входным потоком System.in.
Scanner in = new Scanner(System.in);
String name = in.nextLine();
Ветвления
Условный оператор в языке Java имеет следующий вид:
if (условие) оператор
Условие должно указываться в скобках. Например,
if (n > m) {
System.out.println(«n bigger then m»);
} else {
System.out.println(«m bigger then n»);
}
Циклы
В языке Java существует стандартный набор циклов.
Цикл while обеспечивает выполнение выражения (или группы операторов,
составляющих блок) до тех пор, пока условие равно true.
while (n < 10) {
n++;
}
Условие цикла while проверяется в самом начале. Следовательно, возможна
ситуация, при которой код, содержащийся в блоке не будет выполнен
никогда. Если вы хотите, чтобы блок выполнился хотя бы один раз, проверку
10
условия нужно перенести в конец. Для этого используется цикл do while.
Например,
do {
n++;
} while (n < 10);
Циклы for – очень распространенная языковая конструкция. В ней
количество
повторений
контролируется
переменной,
играющей
роль
счетчика и обновляемой на каждой итерации. Например,
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
Первый элемент оператора for обычно выполняет инициализацию счетчика,
второй формулирует условие выполнения тела цикла, а третий определяет
способ обновления счетчика.
Для того, чтобы прервать выполнение цикла, следует воспользоваться
ключевым словом break.
for (int i = 0; i < 10; i++) {
System.out.println(i);
if (i > 5) {
break;
}
}
11
Объекты, классы
Язык
Java
является
полностью
объектно-ориентированным
языком
программирования. Поэтому в основе всех программ, написанных на этом
языке, являются классы.
Далее приведен пример создания простого класса User.
public class User {
private String login;
private String passHash;
public User(String login, String passHash) {
this.login = login;
this.passHash = passHash;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPassHash() {
return passHash;
}
public void setPassHash(String passHash) {
this.passHash = passHash;
}
}
12
Создание класса начинается со строчки
public class User
, где public (модификатор доступа для класса, будут рассмотрены позднее),
ключевое слово class за которым следует название класса.
В Java существует соглашение(полностью с которым можно ознакомиться по
ссылке
http://www.oracle.com/technetwork/java/codeconventions-150003.pdf),
что при именовании используется подход «camel case». При этом название
классов начинаются с большой буквы, названия переменных, методов с
маленькой.
Для
создания
экземпляра
класса
необходимо
воспользоваться
конструктором. Например,
User user = new User(“my_login”, “pass_hash”);
В результате будет создан экземпляр класса User, у которого переменная
login равна «my_login», а passHash равен «pass_hash». В данном примере есть
только один конструктор. Всего в классе может быть произвольное
количество конструкторов. Если в классе явно не указано ни одного
конструктора, то у него все равно есть один констурктор – конструктор по
умолчанию. Например, User user = new User(); Т.е. констуктор по умолчанию
– конструктор без параметров.
Для объявления конструкторов существует следующие правила.
public User(String login, String passHash) {
…}
Вначале идет модификатор доступа (в данном случае public), затем название
класса и в скобках входные параметры для инициализации.
Поля экземпляра можно объявить с помощью ключевого слова final. Такое
поле должно быть проинициализировано при создании объектов. После
инициализации такого поля его значение нельзя будет изменить.
private final String login;
13
Еще одним ключевым словом, которое можно использовать при объявлении
объекта, является static. Поле, имеющее модификатор static, существует в
одном экземпляре для каждого класса.
private static int nextId;
Статические переменные используются крайне редко. Если используются
static
переменные,
то
это,
скорее
всего,
говорит
о
проблемах
в
проектировании классов. А вот использование static констант встречает
постоянно.
private static double PI = 3.14;
Константы, как правило, именуются используя буквы только верхнего
регистра.
Деструкторов в языке Java нет. Т.е. удалять объект после того, как он нужен
нет необходимости – он будет удален автоматически сборщиком мусора.
Пакеты
Язык Java позволяет объединять классы в наборы, называемые пакетами
(package). Пакеты облегчают организацию работы и позволяют отделить
классы, созданные одним разработчиком, от классов, разработанных другим.
В стандартной поставке Java можно встретить следующие пакеты: java.lang,
java.util, java.net и т.д. Стандартные пакеты языка Java представляют собой
иерархичные структуры. Подобно каталогам на диске компьютера, пакеты
могут быть вложены один в другой. Все стандартные пакеты принадлежат
иерархиям java, javax. Также пакеты используются для уникальности имен
классов. Например, если поместить класс User в пакет ru.miet, то полное имя
класса будет ru.miet.User. С точки зрения Java классы ru.miet.User и
com.miet.User два абсолютно разных класса и конфликта имен не будет.
Импортирование классов
Класс может использовать все классы из собственного пакета и все
общедоступные классы из других пакетов.
14
Доступ к классам из других пакетов можно получить двумя способами. Вопервых, можно указывать полное имя пакета перед именем каждого класса.
Например:
ru.miet.User user = new ru.miet.User();
Очевидно, что этот способ слишком утомителен. Более простой и
распространенный способ предусматривает применение ключевого слова
import. В самом начале класса объявляем.
import ru.miet.User;
И далее в коде можно просто писать:
User user = new User();
Чтобы вручную не прописывать все import в Eclipse есть комбинация клавиш
Ctrl + Shift + O, которая позволит автоматически прописать все недостающие
import.
15
Наследование
Классы, суперклассы и подклассы
Наследование в Java осуществляется с помощью ключевого слова extends.
Например, опишем класс Administrator, который будет расширять класс User.
public class Administrator extends User {
…
}
Класс User в таком случае называется суперклассом или родительским, а
класс Administrator подклассом или дочерним. Дочерний класс «шире»
родительского. Т.е. все свойства, которые есть в родительском
инкапсулируются в дочерний, так же в дочерний класс можно добавить
новые свойства.
Класс Object
В языке Java все объекты неявным образом наследуются от класса Object.
Этот класс является родительским для абсолютно всех классов. Поэтому в
каждом классе есть следующие метод
• public int hashCode()
• public boolean equals()
• public void wait()
• public void notify()
• public String toString()
Этот список не полон. Подробнее ознакомиться со всеми методами можно
тут http://docs.oracle.com/javase/8/docs/api/index.html?java/lang/Object.html.
Подробнее разберем только три из всех методов.
16
hashCode() и equals()
Метод equals() проверяет эквивалентны ли два объекта. В классе Object
данный метод проверяет только одно – ссылаются ли обе переменный на
один и тот же объект.
hashCode() – генерирует хэш-код для объекта. Для абсолютно одинаковых
двух объектов хэш-код должен совпадать. Если же хэш-коды объектов
равны, то это не значит что и объекты будут равны. Это объясняется
коллизией хэш-функций.
Два объекта в Java нельзя сравнивать через «==», т.к. при использовании
этого оператора будет проверяться на один и тот же объект ссылаются
объекты или нет.
toString()
Метод toString() позволяет преобразовать объект в строку. Это бывает часто
полезно. Например, при выводе в консоль можно указать просто
System.out.println(user);
Метод toString() вызовется автоматически.
Разумеется каждый из этих трех методов можно переопределить в своем
классе. Всегда ли это надо делать? Зависит от конкретной задачи. В
некоторых обязательно, в некоторых нет. Иногда надо обязательно
переопределять, но методы должны учитывать не все поля.
Переопределение методов
При наследовании можно переопределить метод родительского класса. При
этом у методов обязательно должна совпадать сигнатура.
public class User() {
public void printName() {
System.out.println(“I’m user.”)
}
}
17
public class Admin extends User {
@Override
public void printName() {
System.out.println(“I’m admin.”)
}
}
Для того, чтобы запретить переопределение метода нужно воспользоваться
ключевым словом final.
public class User() {
public final void printName() {
System.out.println(“I’m user.”)
}
}
Точно также можно запретить наследование от класса.
public final class User() {
public void printName() {
System.out.println(“I’m user.”)
}
}
Абстрактные классы
Чтобы создать абстрактный класс, необходимо объявить его как abstract.
public abstract class User {
}
Нельзя создать экземпляр абстрактного класса.
Также можно создать абстрактный метод.
public abstract String getName();
Такой метод не может содержать тела и должен быть обязательно
переопределен в дочернем классе.
18
Модификаторы доступа
Всего в Java существует четыре модификатора доступа:
• Область видимости ограничена классом (private).
• Область видимости не ограничена (public).
• Область видимости ограничена пакетов и всеми подклассами
(protected).
• Область видимости ограничена пакетом (по умолчанию). Никакого
модификатора указывать не надо.
Интерфейсы
Интерфейсы в Java не являются классами. Они представляют собой
множество требований , предъявляемых к классу.
public interface Comparable {
int compareTo(Object other);
}
Интерфейс объявляется с помощью ключевого слова interface и содержит в
себе список методов. Реализации методов быть не может. Также в
интерфейсах еще можно размещать какие-либо статические константы.
Реализация интерфейса осуществляется следующим образом:
public class User implements Comparable {
public int compareTo(Object other) {
// … тут реализация метода
}
}
В Java нет множественного наследования, но классы могут реализовывать
сколько угодно интерфейсов.
При объявлении методов в интерфейсе, как правило, не указываются
модификаторы доступа, потому что по-умолчанию они являются public.
Для реализации интерфейса не обязательно явным образом создавать класс.
Comparable c = new Comparable() {
19
public int compareTo(Object other) {
// … тут реализация метода
}
}
В данном случае new Comparable(){…} называется анонимным классом.
Enum
В Java, как и в большинстве языков программирования, существует
возможность создать тип данных «перечисление». Например,
public enum DAYS {
sunday, monday, wednesday
}
Воспользоваться каким-либо значением можно следующим образом:
DAYS d = DAYS.monday;
Объектипа enum’a можно сравнивать через оператор «==».
Collections
В Java большое количество разных коллекций: массивы, списки, стеки,
очереди, наборы. Все коллекции в Java реализуют интерфейс
java.util.Collection. Подробнее о нем можно прочитать тут
http://docs.oracle.com/javase/8/docs/api/index.html?java/util/Collection.html
Все его реализации имеют определенную специфику. Рассмотрим самые
популярные:
• java.util.ArrayList – по своей сути обычный массив с возможностью
динамически менять длину.
• java.util.LinkedList – классический список.
Все необходимые методы описаны по ссылке, располагающейся выше.
Рассмотрим пример использования LinkedList.
List list = new LinkedList();
20
list.add(3L);
Выше приведено создание переменной и добавление в нее числа 3. Т.к.
LinkedList реализует интерфейс List, то переменную можно объявлять просто
как List, а не LinkedList.
List list;
Внутри <…> указывается какой тип имеют переменные в коллекции. Там
может быть абсолютно любой класс, в том числе и другая коллекция.
Исключения
В языке Java объект исключения всегда является экземпляром класса,
производного от Throwable
(http://docs.oracle.com/javase/8/docs/api/java/lang/Throwable.html).
У этого класса есть два прямых потомка java.lang.Error и java.lang.Exception.
Класс Error и его наследники описывают внутренние ошибки и ситуации,
связанные с нехваткой ресурсов, в системе поддержки выполнения команд.
Ни один объект этого типа самостоятельно сгенерировать невозможно.
Чаще всего приходится сталкивать с классами Exception и его наследниками.
Всех прямых потомков Exception можно разделить на две категории:
unchecked(RuntimeException и все его потомки) и unchecked(все остальные)
исключения. Исключения типа RuntimeException возникают вследствие
ошибок программирования, например, неверное приведение типов, вызод за
пределы массива, попытка обратиться к null объекту.
Чтобы бросить какое либо исключение необходимо воспользоваться
ключевым словом throw и указать объект исключения.
throw new IOException();
Для обработки исключений существует классическая система из блоков try,
catch, finally.
21
try {
// блок try
} catch(IOException e) {
// блок catch
} finally {
// блок finally
}
Блок catch – любой блок, в котором выв хотите поймать исключение. В блоке
catch описывается действие, которые необходимо выполнить в случае
возникновения исключений. В catch указывается при каком типе исключение
необходимо выполнить действие. В данном примере блок catch будет вызван
при возникновении IOException, либо любого другого исключения, которое
является потомком IOException. Блоков catch может быть любое количество.
Блок finally вызывается всегда. Не важно возникло ли исключение или нет.
Не обязательно наличие блоков catch и finally. Может быть указан только
catch или только finally.
В случае, если в методе вы не хотите обрабатывать checked исключение и
ходите отдать обработку исключения методу, который вызвал этот метод, то
необходимо в сигнатуре метода сделать пометку о том, что этот метод может
бросить исключение. Например,
public void test() throws IOException {
// тут находится код, который может вызвать IOException
}
В Java есть достаточно большое количество исключений, но их, как правило,
не хватает. Ничто не мешает реализовать свое исключение и унаследовать
его от Exception.
22
Разработка приложений с графическим интерфейсом
Первая версия языка Java содержала библиотеку классов Abstract Window
Toolkit (AWT), предоставляющую основные средства программирования
графического интерфейса на конкретной платформе (Windows, Macintosh…)
Позднее появился Swing, который не является полной заменой AWT (взяты
некоторые основы архитектуры). Swing содержит более богатый и удобный
набор элементов пользовательского интерфейса. Swing менее зависим от
платформы, на которой выполняется приложение. Также эта библиотека
обеспечивает однотипные средства для работы на разных платформах. В
последнем свойстве кроется и не достаток. Т.к. нативные решения, к
которым привык пользователь определенной операционной системы, могут
выглядеть иначе в приложении, реализованном с помощью Swing.
Фреймы
Фрейм – окно верхнего уровня (т.е. окно, которое не содержится внутри
другого окна). В библиотеке Swing он представлен классом JFrame.
Посмотрим на пример просто приложения, которое создает простое пустое
окно.
public class Test {
public static void main(String[] args) {
MyFrame frame = new MyFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
public class MyFrame extends JFrame {
public MyFrame() {
setSize(300, 200);
}}
23
После запуска на экране должно отобразиться пустое окно с размерами 300
на 200.
Разберем подробнее некоторые строки.
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Задает действие на нажатие «крестика(закрытия окна)». По-умолчанию
действие по нажатию на «крестик» делает фрейм просто невидимым. Для
того, чтобы выходить из программы нужно прописать
JFrame.EXIT_ON_CLOSE.
По-умолчанию фрейм создается невидимым, поэтому после создания
необходимо ему указать видимость.
frame.setVisible(true)
Подробнее со всеми методами доступным для фрейма можно ознакомиться
тут.
http://docs.oracle.com/javase/8/docs/api/javax/swing/JFrame.html
Java 2D
Итак, все классы отвечающие за отрисовку различный окон и компонентов в
графических приложениях наследуются от класса java.awt.Component
http://docs.oracle.com/javase/8/docs/api/java/awt/Component.html. Но сейчас
остановимся подробнее на его дочернем классе javax.swing.JComponent
http://docs.oracle.com/javase/8/docs/api/javax/swing/JComponent.html. От
данного наследуются все компоненты, которые могут быть расположены на
фрейме.
В классе javax.swing.Component есть метод
protected void printComponent(Graphics g)
http://docs.oracle.com/javase/8/docs/api/javax/swing/JComponent.html#printCom
ponent-java.awt.GraphicsДанный метод всегда вызывает при отрисовке компонента. Разберем
подробнее как происходит отрисовка компонент, а именно как работать с
24
классом Graphics.
(http://docs.oracle.com/javase/8/docs/api/java/awt/Graphics.html)
Начиная с версии 1.0, в классе Graphics имелись методы для рисования
линий, прямоугольников, эллипсов и т.д. Но функционал был весьма
ограничен. Невозможно было даже изменить ширину линий.
В версии 1.2 появилась библиотека Java 2D с более мощным функционалом.
Для того, чтобы воспользоваться возможностями Java 2D, необходимо
создать объект класса Graphics2D, который является подклассом Graphics.
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
}
При создании геометрических фигур в библиотеке Java 2D применяется
объектно-ориентированный подход. Все фигуры наследуются от интерфейса
Shape. Например, такие классы, как Line2D, Rectangle2D, Ellipse2D.
Подробнее со всеми классами можно ознакомиться в официальной
документации http://docs.oracle.com/javase/8/docs/api/java/awt/Shape.html.
Далее будет приведен пример работы с этими классами.
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
/**
* @version 1.32 2007-04-14
* @author Cay Horstmann
*/
public class DrawTest
{
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
25
{
public void run()
{
DrawFrame frame = new DrawFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
/**
* A frame that contains a panel with drawings
*/
class DrawFrame extends JFrame
{
public DrawFrame()
{
setTitle("DrawTest");
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
// add panel to frame
DrawComponent component = new DrawComponent();
add(component);
}
public static final int DEFAULT_WIDTH = 400;
public static final int DEFAULT_HEIGHT = 400;
}
26
/**
* A component that displays rectangles and ellipses.
*/
class DrawComponent extends JComponent
{
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
// draw a rectangle
double leftX = 100;
double topY = 100;
double width = 200;
double height = 150;
Rectangle2D rect = new Rectangle2D.Double(leftX, topY, width, height);
g2.draw(rect);
// draw the enclosed ellipse
Ellipse2D ellipse = new Ellipse2D.Double();
ellipse.setFrame(rect);
g2.draw(ellipse);
// draw a diagonal line
g2.draw(new Line2D.Double(leftX, topY, leftX + width, topY + height));
27
// draw a circle with the same center
double centerX = rect.getCenterX();
double centerY = rect.getCenterY();
double radius = 150;
Ellipse2D circle = new Ellipse2D.Double();
circle.setFrameFromCenter(centerX, centerY, centerX + radius, centerY +
radius);
g2.draw(circle);
}
}
Основные компоненты Swing
Рассмотрим все основные компоненты, которые доступны в Swing.
Начнем с компонентов, которые позволяют вводить и редактировать текст.
JTextField(http://docs.oracle.com/javase/8/docs/api/javax/swing/JTextField.html)
– позволяет однострочный ввод текста, JTextArea
(http://docs.oracle.com/javase/8/docs/api/javax/swing/JTextArea.html) –
позволяет ввод многострочного текста и JPasswordField
(http://docs.oracle.com/javase/8/docs/api/javax/swing/JPasswordField.html) – для
однострочного ввода текста, при этом, содержимое не отображается.
Для отображения не редактируемых данных(лейблов) можно
воспользоваться компонентом JLabel
(http://docs.oracle.com/javase/8/docs/api/javax/swing/JLabel.html).
Кнопки реализованы в классе JButton
(http://docs.oracle.com/javase/8/docs/api/javax/swing/JButton.html).
Пример всех компонент можно найти в папке components_1.
28
Компоновка элементов
Для расположении элементов на окне используются различные диспетчеры
компоновки (layout manager). Стандартным диспетчером компоновки
является flow layout manager. Все добавляемые элементы будут добавляться
слева на право, если элемент не помещается в строку, то он переносится на
следующую строку.
• Border layout
(http://docs.oracle.com/javase/8/docs/api/java/awt/BorderLayout.html) позволяет располагать компоненты с привязкой к областям. При
добавлении компоненты необходимо указать одну из констант. SOUTH
(южная), NORTH (северная), WEST (западная), EAST (восточная) или
CENTER (центральная). Пример можно посмотреть в components_2.
• Grid layout
(http://docs.oracle.com/javase/8/docs/api/java/awt/GridLayout.html) размещает компоненты по строкам и столбцам, как в таблице.
Компоненты добавляются построчно, сначала – в первую ячейку
первой строки, затем – во вторую ячейку первой строки и т.д. Пример
можно посмотреть в components_3.
Всего существует большое количество других диспетчеро компоновки, более
того, вы можете реализовать свой собственный.
Обработка событий
Каждая операционная среда, поддерживающая графический интерфейс,
непрерывно отслеживает такие события, как нажатие клавиш или щелчок
мыши, а затем сообщают о них выполняемой программе. Программа решает,
как реагировать на эти события.
Так как Java является полностью объектно-ориентированным языком, то и
иерархия всех события начинается с одного класса java.util.EventObject
(http://docs.oracle.com/javase/8/docs/api/java/util/EventObject.html). Например,
кнопка может создавать объекты класса ActionEvent
29
(http://docs.oracle.com/javase/8/docs/api/java/awt/event/ActionEvent.html), а
окно WindowEvent
(http://docs.oracle.com/javase/8/docs/api/java/awt/event/WindowEvent.html).
Кратко механизм обработки событий можно описать следующим образом.
• Объект – слушатель представляет собой экземпляр класса,
реализующего специальный интерфейс, называемый интерфейсом
слушателя.
• Источник события – это объект, который может регистрировать
слушателей и посылать им объекты событий.
• При наступлении событий источник посылает объекты события всем
зарегистрированным слушателям.
• Слушатели используют информацию, инкапсулированную в объекте
события, для того, чтобы решать, как реагировать на это событие.
Пример можно посмотреть в components_4.
30
Многопоточность
Многопоточность имеет исключительную практическую ценность.
Например, браузер должен уметь одновременно загружать множество
изображений, программы с графическим пользовательским интерфейсом
имеют отдельные потоки для сбора интерфейсных событий от окружающей
операционной среды.
Рассмотрим программу ball_1. Эта программа анимирует прыгающий мяч не
используя многопоточность. Если нажать на кнопку start, то мячик начнет
двигаться. При этом, обработка перемещения мячика занимает весь поток,
поэтому, пока мячик не прекратит двигаться не возможно будет
взаимодействовать с программой.
Теперь перейдем к многопоточной реализации программы. Найти готовый
код можно в ball_2.
Рассмотрим процедуру генерации потока.
1. Поместить код задачи в метод run класса, реализующего интерфейс
Runnable
(http://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html). Этот
интерфейс содержит единственный мтеод.
public interface Runnable {
void run();
}
public class MyRunnable implements Runnable {
public void run() {
// тут код, который нужно выполнить в отдельном потоке.
}
}
2. Создать объект этого класса.
Runnable r = new MyRunnable();
31
3. Создать объект Thread
(http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html) из
Runnable
Thread t = new Thread(r);
4. Запустить поток
t.start();
Состояние потока
Потоки могут пребывать в одном и шести состояний:
• новый;
• работоспособный;
• блокированный;
• ожидающий;
• временно ожидающий;
• завершенный.
Когда вы только создали поток операцией new, то поток еще не запущен. Он
находится в состоянии “новый”.
После вызова метода start() поток оказывается в работоспособном состоянии.
Работоспособный поток может в данный момент выполняться, а может и нет.
Это зависит от операционной системы – будет ли выделено потоку время на
выполнение.
Когда поток заблокирован или находится в состоянии ожидания, он
временно не активен. Он не выполняет никакого кода и потребляет минимум
ресурсов.
Поток завершается по одной из следующчх причин. Либо он умирает, в
случае, если метод run закончил свое выполнение, либо он умирает внезапно
из-за неперехваченного исключения в методе run().
Синхронизация потоков
В Java существует большое количество разных способов синхронизировать
потоки. Рассмотрим некоторые из них.
32
1. Использование слова synchronized.
Его можно использовать двумя разными способами. Первый –
объявить метод как synchronized. Например,
public synchronized void do() {/*тут код*/}
Метод do может одновременно вызываться только одним потоком.
Второй вариант использовать synchronized блок.
public void do() {
…
synchronized(v) {
// критическая секция
}
}
Блок внутри этого кода может вызываться только одни потоком в
какой то момент выполнения. Все остальные будут блокированы. В
качестве переменной v может быть указан абсолютно любой объект.
2. Использование ReentrantLock
(http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/Reentran
tLock.html)
Например,
ReentrantLock myLock = new ReentrantLock();
myLock.lock();
try {
…
} finally {
myLock.unlock();
}
3. ReentrantReadWriteLock
(http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/Reentran
tReadWriteLock.html)
Использование аналогично обычному ReentrantLock.
33
34