Код:
Java позволяет создавать 3 типа приложений: 1) программы - на компе и 2) аплеты - браузером. 3) Сервлеты на сервере
Выход компилятора java - байткод. Набор команд выполняемых виртуальной java машиной (JVM)
В java 2 есть JIT (Just in Time) - компиляция байткода часть-за-частью, во время выполнения, по мере необходимости. Целиком компилировать нельзя, т.к. java делат разные проверки во время выполнения.
Архитектуронезависимость - выполнения всегда, в любое время.
Есть RMI (Remote Method Invocation) - выполнение обьектами процедур на двух компьютерах дистанционно.
Java программы содержат много информации времени выполнения - проверка и разрешение доступа к обектам во время выполнения.
Свойства java 1.1:
Java Beans - компонент на java.
RMI
Java Database Connectivity (JDBC) - для SQL
Java Native Interface (JNI) - взаимодействие программ с библиотеками кода на других языках.
Отражение, определение полей, методов, конструкторов во время выполнения.
Свойства защиты. Цифровые подписи, генерация ключей, обзоры сообщений, список управления доступом.
Поддержка 16 разрядных символьных протоколов, обработывают юникод.
GUI
Внутренние классы - один в другом.
Date исключен, но не исчез. Как и др компоненты, для совместимости.
Свойства java 2:
Swing - компонент интерфейса на java - дает использовать look-and-feel
Колекции - гшруппы обьектов. Связные списки, динамические массивы, хэш таблицы.
policy file - определяют разрешение для кода из различных источников. (доступ к файлам и т.д.)
Цифровые удостоверения.
Криптографические инструменты
Java 2D - формы, текст и т.д.
и т.д.
Исключены из java 2: suspend() resume() stop()
java в HTML с используется с тегом <applet>
class Example {
public static void main(String args[]) {
System.out.println("Hello!" + " сложение строк через плюс"); // в методе класса с именем main начинается выполнение программы, такой метод один на программу
// static для того, чтобы можно вызывать функцию до создание экземпляра
}
}
C:\> javac Example.java - компиляция
C:\> Example - запуск
После компиляции каждый класс помещается в файл с именем класса и расширением .class
Имя класса принято с большой буквы.
Пробельные символы - перевод строки, пробела, табулиция.
Тип определяет поведение, а не размер.
В java нельзя присвоить целому значение с плавающий точкой.
Типы:
Целые - byte, short, int, long.
Плавающие float, double.
Символы - char
булевские - boolean (только true или false)
java не поддерживает беззнаковых чисел.
Ширина целого числа не определена, как количество памяти.
long - 64
int - 32
short - 16 -32768 32767 (для 16 разрядных)
byte - 8 - -128 127 (для сетевых, файловых потоков данных, рядами двоичных данных )
В выражениях с меньшими типами и int меньшие типы расширяются до выполнения. Нет гарантий что меньший тип будет эфективнее.
Исключение - массивы, byte гарантирует использование одного байта.
В java тип char 65 536 т.к. он в юникод (16 bit в java, а не как в C 8 bit)
09 - octal
0x12 - hex
9L - long
6F - float
false и true это не 0 и 1 !!!
строки это обьекты
Типы преобразуютс автоматом, если например int и float совместимы, а char и boolean нет.
int a;
float b;
int a = (float) b; - приведение типа, происходит усечение, отбрасывание дробной части.
Массив
int mass[];
mass = new int[12]; //элементы будут инициализированны нулями.
int mass[] = {1,2,3,4,5,7878,34,0};
int mass[][] = new int[1][3];
int mass[][] = new int[2][];
mass[0] = new int[3];
mass[1] = new int[3];
Если это массив обьектов, то им нужно выделять память.
SomeClass ary[][] = new SomeClass[3][3];
for ( int k = 0; k < 3; k++ )
for ( int j = 0; j < 3; j++ )
ary[k][j] = new SomeClass();
SomeClass ary[][] = new SomeClass[][] {
{ new SomeClass(), new SomeClass(), new SomeClass(), },
{ new SomeClass(), new SomeClass(), new SomeClass(), },
{ new SomeClass(), new SomeClass(), new SomeClass(), },
};
<< - левый сдвиг смещает все биты влево, старший выходит за пределы и теряется. Используют как эффективную альтернативу умножению на 2. Но нельзя выходить за пределы облости.
>> - эффективное целочисленноеделение на 2.
>>> - беззнаковый сдвиг в право вставляет нуль в старший байт, используется например в работе с пиксельной графикой.
все описания класса должны храниться в одном файле
class Box {
double width;
double height;
double depth;
}
Box mybox = new Box();
mybox.width = 100;
После компиляции каждый класс помещается в свой файл .class
Переменная типа класс это ссылка на класс (Box mybox; - ссылка)
Если конструктора в классе нет, то вызывается конструктор по умолчанию. Он инициализирует все переменные нулями.
Обычные типы реализованны как нормальные переменные.
// Две ссылки на ОДИН обьект (для простых типов типа int это не так)
Box b1 = new Box();
Box b2 = b1;
class Box {
void method1 () {
System.out.println("Hell!");
}
float method1 () {
return 10.1;
}
}
Box b1 = new Box();
b1.method1();
Конструктор
class Box {
int i;
Box() {
i = 10;
}
}
this - ссылка на текущий обьект
Метод finalize() вызывается при удалении обьекта. Нельзя определить когда и будет ли вообще выполнен идентефикатор, поэтому его нельзя использовать как деструктор. Не известно когда выполнится, потому что обьект при разрушении только отмечается как неиспользуемый (на него уже нету никаких ссылок), а сама finalize() вызывается при уничтожении обьекта (вызов gc()) а когда он вызовется не известно (зависит от реализации платформы).
protected void finalize() {
//код
}
Пример. Стек.
class Stack {
int stck[] = new int[10];
int tos;
Stack() {
tos = -1;
}
void push(int item) {
if(tos == 9){
System.out.println("Стек заполнен");
}
else stck[++tos] = item;
}
int pop() {
if(tos < 0 ) {
System.out.println("Стек пуст");
return 0;
}
else return stck[tos--];
}
}
перегрузка обычная. - метод в наследнике перекрывает метод в родителе, если методы имеют одинаковые названия, то они вызываются в зависимости от того какие параметры (*типы параметров) в функции отправляются.
Простые типы переменные передаются по значению в методы (их значение не изменяется), классы - по ссылке (изменение внутри функции влияет на обьект)
class Test {
int j;
void method(Test t) { //Значение j из обьекта t изменяется
t.j = 999;
}
}
class Box {
public static void main(String args[]){
}
}
class Test {
int a; (по умолчанию public)
public int b;
private int c;
}
Если же модификатор public не задан, то использовать класс мы можем исключительно внутри пакета. Помимо того, что мы можем создавать экземпляры класса, помеченного как public, нам также дозволено обращаться к полям и методам этого класса, помеченным этим же модификатором.
friendly — модификатор класса по умолчанию (если модификатор не определен явно для класса). Такой класс доступен (public) только для объектов находящихся в том же самом пакете, вне пакета, он выступает как private.
public — доступы для использования или расширения любым объектом вне зависимости от пакета. Public классы должны храниться в файлах с именем public-класса: <имя_класса>.java. Для остальных классов такое соответствие рекомендуемое.
Итак, перечислим модификаторы доступа:
· private – метод или поле класса, помеченные этим модификатором, доступны только в пределах данного класса;
· package – поле/метод доступно в пределах всего пакета; это значение по умолчанию для всех полей или методов объявленных без модификаторов доступа;
· protected – здесь доступ разграничивается для всех “родных” (т.е. производных или родительских) классов данного класса;
· public – доступ открыт отовсюду и для всех;
protected - при наследовании
В каких местах видимы:
Class Package Subclass World
private Y — — —
(без спецификатора) Y Y — —
protected Y Y Y —
public Y Y Y Y
переменные static - глобальные переменные, одна для всех экзепляров
Методы static:
могут вызывать только другие static-методы
должны обращаться только к static данным (static переменным)
не могут ссылаться на this или super
class Test {
static int i = 3;
static int j;
// статистический блок выполняется только один раз, когда класс впервые загружается ОН ИСПОЛЬЗУЕТСЯ ДЛЯ ИНИЦИАЛИЗАЦИИ static переменных
static {
j = 66;
}
void method() {
System.out.println("Hello!");
}
}
Обращаться Test.method();
Сначало выполняется i = 3, потом j = 66, потом main()
Внутри static метода недопустимо обращаться ко всем экземплярным переменным
final аналог const, дальнейшее изменение не возможно
class Test {
final int i = 999;
}
метод final нельзя переопределять
class A {
final void method(){
System.out.println("Hell");
}
}
int a[] = new int[10];
a.length; - число элементов в массиве
Один класс внутри другого - вложенный. Вложенны имеет доступ к членам класса включая private
static вложенный класс может обращаться только через обьекты. Используются когда не нужно обращаться к переменным и методам внешнего (т.к. не содержат неявную ссылку на внешний)
class Test1 {
int i;
static class Test2 {
int j;
}
}
Члены внутреннего класса известны только в пределах его. Внутренний класс можно определять и в методах, и в for...
String s = "123";
s.charAt(3); - тредтий символ
class A {
}
B наследник A
class B extends A {
}
A a;
B b;
a = b;
ссылка базового класса может указывать на производный.
super(int i); - конструктор базового класса
super - указатель на базовый (родитель данного) класс
super.member
Одноименные методы с одинаковыми параметрами класса-наследника перекрывают методы базового класса.
Какой из переопределенных метод выполнять выбирается на основе типа обьекта на который указывает ссылка, определение делается во время выполнения.
(как виртуальные функции)
В java все функции виртуальные. (отличие от перегрузки в виртуальных функциях параметры и возвращаемое значение совпадает)
abstract class A {
abstract void method1();
}
class B extends A {
void method1() {
System.out.println("Hell!");
}
}
Абстрактный класс должен быть переопределен, если есть хоть один абстрактный метод, то и класс нужно обьявить абстрактным. Обстрактные обьекты нельзя создавать. Нельзя обьявлять абстрактные конструкторы и абстрактные static методы. Любой полкласс абстрактного класса должен или сам реализовать должен быть обьявлен abstract или реализовать все абстрактные методы. Но можно создавать ссылки абстрактного класса (базовый указывает на производный).
Не сочетается с FINAL, PRIVATE, STATIC, NATIVE, STRICTFP, TRANSIENT
Методы обьявленные как final не могут быть переопределены
class A {
final void method() {
}
}
Т.к. методы не будут переопределены компилятор может сделать их inline - встроить (копировать) их байт-коды в точку вызова.
Класс обьявленный как final не может наследоваться. Нельзя одновременно объявлять класс как abstract и final
final class A {
}
Object - специальный класс, все классы унаследованны от него. Его ссылка может указывать на все обьекты (в том числе массивы)
Методы Object доступны во всех наследниках
Object clone() - создает копию
boolean equale(Object obj) - сравнивает
void finalize() - вызывается прежде чем обьект будет переработан сборщиком мусора
Class getClass() - получает класс обьекта во время выполнения
int hashCode() - возврыщает хэш-код связанный с вызовом обьекта
void notify() - возобновляет выполнение потока ожидающего на обьекте вызова
void notifyAll() - возобновляет ввыполнение всех потоков ожидающих на обьекте вызова, вызываетсяавтоматически при println()
String toString() - возвращает строку которая описывает обьект
void wait() - ожидает выполнение на другом потоке
void wait(long millisrconds)
void wait(long millisrconds, int nanoseconds)
getClass(), notify(), notifyAll(), wait() - обьявлены как final, другие можно переопределять
Пакет - набор классов, в разных пакетах могут быть классы с одинаковыми именами, доступ через (.)
package MyPack;
class A {
}
public class B {
public static void main(String args[]) {
}
}
Назвать файл B.java и поместить в каталог MyPack и скомпилировать. Выполнить класс можно командой
java MyPack.B
только находясь в каталоге выше или иметь подходящую установку переменной CLASSPATH, выполнить класс отдельно (команда java B) нельзя
CLASSPATH - устанавливает вершину иерархии классов, можно добавить каталог класса в переменную и он будет выполнеться.
import java.packname.classname
импорт пакетов классов, packname - имя пакета, classname - имя класса
import java.packname.*
* - компилятор должен импортировать полный пакет, все классы (увеличивает время компиляции)
Стандартные классы хранятся пакете с именем Java
основные функции во внутреннем пакте java.lang (НЕЯВНО ИМПОРТИРУЕТЯ для всех программ)
Если имена классов в импортируемых пакетах одинаковые, классы нужно импортировать не через звездочку, а указать имя.
интерфейсы - список переменных и методов которые должны быть реализованы в классе
public interface Name { // спецификатор доступа public или не используется
void method1();
}
Класс должен реализовать все методы своего интерфейса, все переменные интерфейса (!!!) final и static (значение переменных вроде должно быть задано)
Все методы интерфейсов неявно public, если класс сам не public
class A implements Name {
public void method1() {
System.out.println("Hell!");
}
ПРИ реализации метода интерфейса он должен быть обьявлен как public
Можно обьявлять интерфейсные ссылки на обьект (имя_интерфейса ссылка) и они могут указывать на класс который использует интерфейс. Такие ссылки могут указывать на любой класс реализующий этот интерфейс.
(интерфесы медленнее)
пример интерфейсных ссылок:
A ob = new A();
Name ob2 = ob;
Если класс включает интерфейс но не реализует все методы, то он должен быть обьявлен как абстрактный
abstract class A implements Name {
}
интерфейс может наследовать другой интерфейс
interface A extends B {
}
интерфейс может иметь вложенный класс.
public interface IClass {
void doJtest();
class Tester implements IClass {
@Override
public void doJtest() {
System.out.println("Doing test:\n"+this.getClass().getName());
}
};
}
Аннотация @Override информирует компилятор о том, что метод перегружает метод в суперклассе.
Если не использовать аннотацию @Override, то "неправильная" программа скомпилируеются без ошибок, а сам проблемный участок кода станет нереально сложно найти. Использование аннотации @Override заставляет компилятор сразу проверять перегружает ли метод аналогичный в суперклассе.
(Нормальные IDE при переопределении сами вставляют @Override.)
final JLabel label;
class MeaningOfLifeFinder extends SwingWorker<String, Object> {
@Override
public String doInBackground() {
return findTheMeaningOfLife();
}
@Override
protected void done() {
try {
label.setText(get());
} catch (Exception ignore) {
}
}
}
final, static и private методы нельзя переопределить.
...........................................................................................................................
ИСКЛЮЧИТЕЛЬНЫЕ СИТУАЦИИ
когда возникает исключительная ситуация создается обьект описывающий эту ситуацию и вбрасывается в метод вызвавший его. (метод сам обрабатывает исключение или передает ккуда-то еще) В любом случае в некоторой точке исключение захватывается и обрабатывается.
Исключение бывает создаваемое средой java (фундоментальные ошибки - нарушают правила языка или ограничения среды), и сгенерированное вручную.
try{
//блок из которого выбрасывается исключение
}
// Исключение выбрасываемое исполнительной (run-time) системой выбрасывается автоматически
catch(тип_исключения имя_переменной) {
//перехватывает исключение и обрабатывает его
}
finally {
//блок который выполняется перед возвратом из try
//не обязательный блок
}
throw - для выброса исключений
Все типы исключений - классы подкласса Throwable. Подклассы этого класса делятся на две ветви:
Этот класс разделяется на Exception - для ситуаций которые перехватывают программы пользователя, в подклассах этого класса создаются свои классы. У Exception есть подкласс RuntimeException - исключения деления на нуль, индексации массива и т.д.
Вторая ветвь Error - применяется исполнительной системой java для указания ошибок времени выполнения. Например переполнение стека. Эти ошибки как правило катострафичны и не могут обрабатываться программой.
Неотловленные исключения.
Когда возникает ошибка (например деление на ноль) оно должно быть отловлено немедленно. Иначе оно будет перехвачено обработчиком по умолчанию.
Стек вызовов при ошибках отображает тип исключения и функции в которых они.
Класс Throwable переопределяет toString() и обьект-исключение возвращает описание исключения.
class Err {
public static void main(String args[]) {
try{
}
catch(ArithmeticExepcion e) {
System.out.println(e);
}
}
}
выполняется только первый catch чей тип совпадает с типом исключмтельной ситуации, остальные обходятся и продолжается выполнение после блоков try-catch.
В последовательности catch операторов типы в catch подклассы (производные) исключений должны следовать перед суперклассами (родитель). (Т.к. ссылка на родительский может указывать на производый)
Вложенные try
try{
int n = 2/0;
try{
}catch(ArithmeticException e){
}
}catch(ArithmeticException e) {
}
Оператор throw
try{
throw ThrowableInstance; //ThrowableInstance - обьект класса Throwable или его подкласса.
}
Простые типы (int,char) и не Throwable обьекты не могут использоваться.
class A{
static void demo(){
try{
throw new NullPointerException("demo"); // один из стандартных обьектов исключения, два варианта. без параметра и с параметром-строкой, строка отображается при использовании print(); или getMessage()
} catch(NullPointerException e){
throw e; //повторный выброс исключения
}
}
public static main(String args[]){
try{
demo();
} catch(NullPointerException e){
System.out.println("demoo2");
}
}
}
Все исключения выбрасываемые методами за исключением Error, RuntimeException, все другие типы исключений должны быть обьявлены словом throws, без обьявления будет ошибка
static void demo(int i) throws IllegalAccessException {
throw IllegalAccessException("demo");
}
finally - Код из блока finally выполнится в любом случае: при нормальном выходе из try, после обработки исключения или при выходе по команде return.
(Например при обработке файла код его закрытия пишется в try(для нормального) и в catch(для обработки ошибки), а так пишем только один раз в finally)
Написав "catch (Exception e)", мы тем самым говорим системе, что мы хотим ловить все исключения. (ВИДИМО аналог catch(...) в C++)
try{
} finally{
}
Класс java.lang импортирован неявно в java-программы, большинство исключений наследников RuntimeException доступны автоматически и их не нужно включать в throws списко каждого места.
В языке java они называются Некотролируемыми исключениями, потому что компилятор не проверяет выбрасывает или обрабатывает метод эти ислючения. (подклассы Exception) (см таблицу)
Котролируемые исключения - должны быть включены в throws список (см табл)
Для создания собственного подкласса нужно создать класс-наследник Exception (он наследник Throwable и наследует все его методы которые позваляют узнать детали ошибок)
class A extends Exception {
}
=======================================================================================================
М Н О Г О П О Т О Ч Н О С Т Ь - НЕПОЛНОЕ!!!
Однопоточная система - бесконечный опрашивающий стек цикл, чтобы узнать, что делать дальше.
Многопоточная модель устраняет этот цикл. Потоки выгоднее чем процессы.
Чтобы создать поток нужно создать класс наследник Thread и переопределить метод run() в этом методе потоком выполняется операции
Главный поток - в котором начинается работа программы. Когда главный поток завершается, программа завершается.
public class MyThread extends Thread {
super("name"); // имя потока
public void run() {
// некоторое долгое действие, вычисление
long sum=0;
for (int i=0; i<1000; i++) {
sum+=i;
}
System.out.println(sum);
}
}
Чтобы запустить
MyThread t = new MyThread();
t.start();
start() - запускает поток, поток останавливается когда метод run() завершен
Интерфейс Runnable
В Java нету множественного наследования, поэтому пример выше может привести к конфликту. Другой способ:
public class MyRunnable implements Runnable {
public void run() {
// некоторое долгое действие, вычисление
long sum=0;
for (int i=0; i<1000; i++) {
sum+=i;
}
System.out.println(sum);
}
}
Также незначительно меняется процедура запуска потока:
Runnable r = new MyRunnable();
Thread t = new Thread(r, name);
t.start();
Программа завершается когда все потоки завершены. Демон - поток на который программа не обращает внимание, программа всеравно завершается, даже если демон работает. Есть неявные потоки (которые работают во всех программах постоянно) например сборщик мусора java (очищает не используемую память)
Можно так
new Thread(){
// описание
}.start();
при работе с переменными в потоках можно использовать слово volatile для того чтобы компилятор не использовал оптимизацию и провел все действия с переменной, а не так, как после оптимизации (так он может отбросить по его мнению "лишние действия" и сделать не все)
getPriority(); setPriority(); - приоритет процесса, но скорость выполнения неравномерна и нет гарантий выполнения действия в определенное время. Приоритет это int от 1 до 10
Гонка - одну перемнную (метод) могут использовать несколько потоков и её вызовы конфликтуют или в переменную могут заноситься не те данные.
Монитор, семафор, mutex (mutually exclusive lock) - используется, чтобы блокировать одновременный доступ нескольких потоков к одной и той же переменной или методу (чтобы не было гонки). В java сделан через метод synchronized
(Про семофоры надо искать самому подробнее)
Семафор - счетчик количества потоков которые имеют доступ к ресурсу. (если например переменная в нем = 5, то при подключении 5 потоков доступ {переменная i-- при работе потока и i++ при отключении} 6 и дальше закрывается пока один из 5 не прекратит работу)
(Говорят что поток владеет (вошел и т.д.) монитором обьекта, если он внутри метода или блока synchronized)
Метод какого-нить обьекта обьявленный как synchronized, такой метод может выполняться только одним из потоков для одного обьекта (экзепляра) (если такой же метод но другого экзепляра, то он может выполняться одновременно). Пока один поток выполняет synchronized метод никакой поток не может вызвать никакой synchronized метод этого обьекта.
class A {
synchronized void f1(){
}
}
Если нужно использовать чужой класс в котором нету synchronized, то можно
synchronized(obj){
obj.call(msg);
}
obj - обьект метод которого нужно синхронизировать. Вызов метода может одновременно сделать только один поток (как описано выше для метода synchronized).
Thread.currentThread() - ссылка на текущий поток. (писать внутри класса-потока)
Thread.sleep(1000); - приостанавливает поток на 1 сек
setName(); getName() - получить, установить имя потока
в коде что-то типа:
class A {
Thread t;
A(){
t = new Thread(this, name);
}
public void run() {
try{
}catch(InterruptedException e){
}
}
}
s.isAlive() - возвращает true, если поток выполняется и false если нет
try{
obj.s.join(); // join(); (есть дополнительная форма в которой можно задать период ожидания) - метод ждет заверщения потока на котором вызван.
}catch(InterruptedException e){
//
}
wait(); (есть дополнительная форма в которой можно задать период ожидания) notify(); notifyAll();
Чтобы поток не ожидал в цикле (при работе цикла используется процессор) используются эти wait(); .
wait(); // сообщает потоку вызвавшему монитор перейти в режим спячки пока другой поток не вызовет монитор и не выполнить notify();
notify(); // пробуждает первый поток (который вызвал wait();) на том же самом обьекте (запускается поток с большим приоритетом)
notifyAll(); // пробуждает все потоки вызввшие wait();
Взаимодействие между потоками в Java. Wait и notify.
Представим ситуацию, что у нас многопотоковое приложение, написанное на Java. Есть некий класс, выполняющий какое-либо конкретное действие с данными, например, отправку их по почте, а сами данные подготавливаются в другом месте кода в другом потоке. Перед отправкой данных нам необходимо как-то связаться с потоком, подготавливающим данные, дабы поймать момент, когда они будут готовы.
Пример 1. Простой, но неправильный пример
public class DataManager {
private static boolean ready = false;
public void sendData() {
while (!ready) {
// waiting
System.out.println("Waiting for data...");
}
// continue execution and sending data
System.out.println("Sending data...");
}
public void prepareData() {
System.out.println("Data prepared");
ready = true;
}
}
Допустим, что первый поток должен готовить данные, а второй отправлять. Из данного примера видно, что отправляющий поток будет ждать данные в цикле. Это, конечно, будет работать, особенно, если время ожидание мизерное. Но по сути, ожидая данных поток серьезно загрузит процессор, отнимая драгоценные ресурсы на подготовку данных. Правильнее будет каким-то образом приостановить второй поток, пока первый не подготовит данные.
Пример 2. Ожидание с помощью wait() и notifyAll()
public class DataManager {
private static final Object monitor = new Object();
public void sendData() {
synchronized (monitor) {
System.out.println("Waiting for data...");
try {
monitor.wait(); // выбрасывает исключение InterruptedException
} catch (InterruptedException e) {
e.printStackTrace();
}
// continue execution and sending data
System.out.println("Sending data...");
}
}
public void prepareData() {
synchronized (monitor) {
System.out.println("Data prepared");
monitor.notifyAll();
}
}
}
Как видно из данного примера, отправляющий данные поток не циклиться, а вызывает метод wait() у нашего объекта-монитора. Напомню принцип работы синхронизации: как только первый поток попадает в блок synchronized, он становится владельцем объекта monitor и "блокирует" его. Никакой другой поток не сможет попасть в блок, т.е. стать владельцем этого объекта до тех пор, пока поток владелец не "отпустит" монитор, выйдя из блока синхронизации.
Важно! Методы wait(), notify() и notifyAll() должны обязательно находиться внутри блока synchronized, либо внутри synchronized-метода, иначе вы получите Exception. Но возникает вопрос, каким образом второй поток сможет попасть в блок синхронизации, чтобы вызвать notifyAll(), если первый в этот момент будет владельцем monitor'а и будет ждать notify() ? Все просто - как только поток достигает метода wait() он перестает быть владельцем монитора, блокировка снимается, а поток уходит в сон.
Потенциальные проблемы данного кода:
1. Возможна ситуация, когда первый поток подготовил данные раньше, чем второй начал ждать его. В этом случае notifyAll() никого не разбудит и соответственно, когда второй поток дойдет до wait(), процесс остановится навсегда.
2. Существуют в природе так называемые "ложные пробуждения", когда поток просыпается сам по себе, без всяких на то причин.
БЛОКИРОВКА - ошибка взаимоисключения
(неточно)
Если поток вводит монитор в обьект X, а другой поток в Y. Поток в Y пытается вызвать synchronized метод X, то этот поток будет всегда ждать т.к. для доступа к X он должен снять блокировку с Y, чтобы первый поток (вроде c X) мог завершиться.
Это из межпроцессового (не поточного), но возможно то же что и блокировка:
Тупик (deadlock). Классический тупик возникает, если процесс A получает доступ к файлу A и ждет освобождения файла B. Одновременно процесс B, получив доступ к файлу B, ждет освобождения файла A. Оба процесса теперь ждут освобождения ресурсов другого процесса и не освобождают при этом собственный файл. Тупика можно избежать, если ресурсы будут пронумерованы и предоставляться только в восходящем порядке номеров. Кроме того, все ресурсы должны освобождаться сразу после окончания использования.
Или когда один поток пытается два раза захватить монитор.
В Java 1.1 и ранних, устравшие функции для потоков
class T extends Runnable {
Thread t;
T(){
t = new Thread(this);
t.start();
}
public void run() {
}
}
class Main{
public static void main(String args[]){
T thr = new T();
thr.t.suspend(); // остановка потока
thr.t.resume(); // перезапуск потока
thr.t.stop(); // если поток остановлен через stop(); то его нельзя запускать через resume();
}
}
ЭТИ ФУНКЦИИ СТАРЫЕ, МОГУТ ВЫЗВАТЬ ОТКАЗ И ИХ НЕЛЬЗЯ ИСПОЛЬЗОВАТЬ
==================================================================================================================
Поток - абстракция потребляющая или производящая инфу. Связаны с разными устройствами но ведут себя одинаково. Потоки бывают байтовыми символьные.
Чтобы использовать классы потоков нужно импортировать пакет java.io
На верху байтовых потоков два класса InputStream OutputStream. методы read() и write()
На верху символьных Reader Writer
System.in - обьект класса InputStream поток класса System который неявно импортируется java.lang,
System.out System.err - OutputStream
Чтение символов
import java.io.*
class A {
public static void main(String args[])
throws IOException
{
char c;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Введите q для завершения);
do{
c = (char) br.read();
System.out.println(c);
}while(c != 'q');
}
}
Чтение строк
class A{
public static void main(String args[])
throws IOException
{
Bufferedreader br = new BufferedReader(new InputStreamReader(System.in));
String str;
do{
str = br.readLine();
System.out.println(str);
}while(!str.equals("stop"));
}
}
Чтение файла
class A {
public static void main(String args[])
throws IOException
{
int i;
FileInputStream fin;
try{
fin = new FileInputStream(args[0]);
}catch(FileNotFoundException e){
return;
}catch(ArrayIndexOutBoundsException e){
return;
}
do{
i = fin.read();
if(i != -1) System.out.print((char) i);
}while(i != -1);
fin.close();
}
}
//-1 - встретился EOF, запись так же только вместь read(); писать write();
// копирование текстового файла - чтение посимвольно одного и запись в другой
АПЛЕТ
import java.awt.*;
import java.applet.*;
public static class SimpleApplet extends Applet {
public void paint(Graphics g) {
g.drawString("Demo", 20, 20); // строка выводящаяся в окне, 20, 20 - координаты
}
}
<applet code="SimpleApplet" width=200 height=200></applet> - эта закоментированная строчка перед кодом аплета, чтобы компилятор компилировал, как апплет.
transient - переменная не будет запомнена при сериализации (Т.е. при сериализации класс или файл и т.д. становится потоком байт, который можно записать в файл или передать по сети. А если поле класса transient, то это поле не сериализуется. Поле transient при десериализации будет null).
Это для более удобной передачи без использования протоколов.
class A {
}
class B extends A{
}
B b = new B();
if(b instanceof A) // возвращает true если обьект принадлежит классу или класс (стоит на первом месте) является предком класса на втором. (т.е. тип a можно привести к типу A)
strictfp // в java 2 модель вычислений чисел с плавающей точкой облегчена, чтобы использовать старую нужно
strictfp class A {
}
//все элементы буду вычисляться по старому (потому что на разных процессорах по разному)
native // для загрузки dll
public class Demo {
public static void main(String args[]) {
public native void test(); //обьявляем импортируемый метод
static{
System.loadlibrary("DemoLib"); //DemoLib - имя файла с расширением dll
}
}
}
Для реализации метода test() на си нужно использовать JDK утилиту javah.exe для получения .h файлов которые надо включать в си реалтизацию test()
и другие спец действия
аплеты не могут использовать native методы
Метод == сравнивает две различные ссылки
экземпляры типа Void не создаются
gc(); //самостоятельный вызов сборщика мусора, иногда требуется
totalMemory(); //память
freeMemory(); //свободная память
exec(); // запуск других процессов, на разных ОС по разному, относится к классу Process
class A {
public static void main(String args[]) {
Runtime r = Runtime.getRuntime();
Process p = null;
try{
p = r.exec("notepad"); //открывает программу блокнот
p.waitFor(); //программа ждет пока вызываемый не завершится
}catch(Exception e) {
}
System.out.println(p.exitValue()); //возвращает код завершение вызванного процесса
}
}
Runtime - класс с методами
System.currentTimeMillis(); //возвращает время отсчитанное от 1 января 1970 года, используется для вычисления времени выполнения программы (можно использовать разницу во времени)
В свойстве среды Java 2 доступны информация о программе, имя, производитель и т.д.
Вызывая метод System.getProperty(); //можно получить различные переменные среды
class A {
public static void main(String args[]) {
System.out.println(System.getProperty("user.dir")); //путь к каталогу пользователя
}
}
КЛАССЫ С КУЧЕЙ МЕТОДОВ И НЕКОТОРЫЕ МЕТОДЫ java.lang:
Number
Double, Float
isInfinite() //true если число бесконечно велико или мало
isNaN(); // true если значение не число
Byte, Short, Integer, Long
parseShort(); , parseInt();, parseLong(); // преобразование строк
Charecter // класс, оболочка типа char
Boolean //класс, оболчка вокруг bool
Void //класс имеет одно поле TYPE которое содержит ссылку типа Class для типа void экзепляры этого класса не создаются
Process // абстрактный класс инкапсулирует процесс (выплняющуюся программу), используется как суперкласс для типа Runtime
destroy() // заканчивает процесс
exitValue() // возвращает код завершения полученный от подпроцесса
getErroroStream() // Возвращает входной поток, читающий элементы err-потока (выходного потока сообщений об ошибках)
getInputStream() // возвращает входной поток который читает элементы out-поток
getOutputStream() // тоже для выходного
waitFor() // возвращает код метода возвращаемый процессом
Runtime // инкапсулирует среду времени выполнения, нельзя создать обьект, но можно получить ссылку Runtime.getRuntime() - позволяет управлять состоянием JVM
System
Object
Class // Инкапсулирует состояние обьекта или интерфейса, обьекты этого типа нельзя обьявить, создаются самостоятельно во время загрузки классов. Нельзя получитьобьект типа Class. Но можно получить обьект типа Class - getClass(), позволяет получить специфическую инфу о классе
ClassLoader - позволяет создавать наследники этого класса и переопределять методы и как-то по другому загружать классы.
Math - мат методы
Compiler // поддерживает создание сред в которых выполняется байт-код, в нормальном программирование не используется
Package // информация о версии пакета.
java.lang.reflect //информация о программе
java.lang.ref //средство сборки мусора
java.util // коллекции подобно STL в C++
arraycopy() копирование массивов
итераторт позволяет получить доступ к элементам коллекции, перебирая их
a1.iterator() - возвращает ссылку (на первый вроде)
itr.hasNext() - true если следующий элемент существует
itr.next(); - следующий
itr.previous(); - предудыщий
itr.remove() - удаление
import.util.*
class A {
public static void main(String args[]) {
ArrayList a1 = new ArrayList();
a1.add("A");
a1.add("B");
a1.add("C");
Iterator itr = a1.iterator(); //чтение
while(itr.hasNext()) {
Object elem = itr.next();
}
//модификация элементов
ListIterator lItr = a1.listIterator();
while(lItr.hasNext()) {
Object elem = litr.next();
lItr.set(elem);
}
Map // карта отображений, что-то вроде ассоциативного массив с подклассами и кучей методов, в том числе в остсортированных структцрах типа дерева.
Comparator // определяет порядок сортировки вроде
===========================================================
Класс Observable используется для создания подклассов за которыми могут наблюдать другие части вашей программы, когда такой обьект изменяется наблюдающие классы уведомляются об этом.
1) Если обьект изменился должен быть вызван setChanged();
2) Должен быть вызван notifyObservers(); чтобы уведомить наблюдателей относительно изменений
НАБЛЮДАЕМЫЙ ОБЬЕКТ ДОЛЖЕН ВЫЗВАТЬ ОБЯЗАТЕЛЬНО ЭТИ ДВА МЕТОДА
Интерфейс Observer
он определяет один метод, который вызывается при изменении обьекта
void update(Observable observOb, Object arg); // observOb - наблюдаемый обьект
// arg - значение которое пересылается методом notifyObservers(), если не указан то null
Пример:
import java.util.*;
class A implements Observer {
public void update(Observable obj, Object arg) {
System.out.println("Вызван " + ((Integer)arg).intValue());
}
}
class B extends Obsetvable {
void f1(int i) {
setChanged();
notifyObservers(new Integer(i));
try{
Thread.sleep(500);
}catch(InterruptedException e){
}
}
}
class Main{
public static void main(String args[]) {
B b = new B(); // наблюдаемый
A a = new A(); //наблюдатель
b.addObserver(A);
b.f1(3);
}
}
Методы Observable
void addObserver(Observer obj); // добавляет обьект obj к спискуобьектов которые наблюдают вызывающий обьект
clearChanged(); // возвращает состояние обьекта на неизменяемый
countObserver() // возвращает количество обьектов которые наблюдают вызывающий обьект
deleteObserver(Observer obj) // удаляет обьект из списка наблюдающих обьектов
hasChanged() // возвращает true если вызывающий обьект был изменен и false если не был
notifyObserver() // уведомляет всех наблюдателей вызывающего обьекта, что он был изменен с помощью update()
notifyObserver(Observer obj) // тоже но obj передается как второй параметр
setChanged() // вызывается когда обьект инициализирующий обращение изменился
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Сериализация - перевод обьектов в последовательность байтов, потом можно записать в файл подключив (соединив) файл и поток.
FileOutputStream fos = new FileOutpitStream("name");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(new MyClass("Jon", 12.3);
oos.flush();
oos.close();
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Сетевой сокет - соединение
IP - протокол разделяет данные на кусочки и посылает через сеть, не гарантирует доставку
TCP - более высокий уровень протокола, надежно сцепляет и сортирует пакеты, надежен.
UDP - протокол для поддержки быстрой, без установки соединения, но ненадежного соединения.
Сервер - разделяемый ресур, клиент - обьект, который хочет получить доступ к серверу.
Порт - пронумерованный сокет, процесс слушает порт в ожидании соединения, к одному порту могут подключиться много клиентов, каждый сеанс уникален
TCP/IP - резервирует 1024 нижних порта
Дейтаграмма - соединение через udp
Общий принцип - Создается обьект типа сокет, соединяется с потком и в поток пишется/читается инфа, кроме простого вывода текста еще MIME (это инфа о типе передаваемого содержимого) плюс заголовки HTTP
=====================================================
Аплеты
Апплет компилируется, а потом вставляется на страницу, внутри тэга можно указать пусть к аплету на серверы и параметры которые аплет сможет читать (они пишутся с помощью тэга param)
import.java.awt.*;
import java.applet.*;
/*
<applet code="AppletSkel" width=300 height=100>
</applet>
*/
public class AppletSkel extends Applet {
public void init() { // вызывается первым, вызывается однажды
}
public void start() { // вызывается вторым или при перезапуске, вызывается и когда пользователь возращается назад
}
public void stop() { // взывается при перезапуске аплета или переходе к другой странице, следует использовать для остановки ненужных потоков когда пользователь покидает страницу
}
public void destroy() { // вызывается когда аплет завершился, следует освободить ресурсы
}
public void paint(Graphics g) { // вызывается когда окно аплета должно быть прорисованно, вызывается например при свертывании, а потом развертывании окна или при наложнии одного окна на другое
}
}
Когда аплет начинает выполняться:
1 init()
2 start()
3 stop()
Когда завершаться:
stop()
destroy()
Аплет может переопределить метод update() когда требуется прорисовать часть окна аплета. При запуске аплет заполняет фон цветом по умолчанию. Это можно обойти переопределив update()
public void update(Graphics g) {
//повторный показ окна
}
public void paint(Graphics g) {
update(g);
}
....................................................................................................................................
Источник события (например кнопка), когда изменяет свое состояние генерирует обьект описывающий изменение и передает его в блок прослушивания событий зарегистрированный в этом источнике. (это класс, т.е. мой класс наследует этот класс-блок-прослушивание в котором есть методы обработки определенных событий, в этих методах и писать код) . Блоки создаются путем реализации интерфейса.
Для обработки событий awt нужно импортировать. Есть интерфейсы и классы которые нужно наследовать, там и писать обраотку. В метод передается обьект с описанием события. Есть методы удаляющие прослушивание событий, они называются примерно removeMouseListener(this)
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
/*
<applet code="MouseEvent" width=300 height=300>
</applet>
*/
public class MouseEvent extends Applet implements MouseListener, MouseMotionListener {
String msg;
int x, y;
public void init() {
addMouseListener(this);
addMouseMotionListener(this);
}
public void mousePressed(MouseEvent me) {
x = me.getX();
y = me.getY();
repaint();
}
public void paint(Graphics g) {
g.drawString(msg, x, y);
}
}
Класс MouseEvent расширяет аплет и реализует как интерфейс MouseMotionListener, так и MouseListener
Нужно для событий клавиатуры нужно обязательно запросить фокус ввода ( requestFocus(); ) или программа не будет принимать никаких событий клавиатуры.
public class KeyEvents extends Applet implements KeyListener {
String msg;
public void init() {
addKeyListener(this);
requestFocus();
}
pulic void keyTyped(keyEvent ke) {
msg += ke.getKeyChar();
repaint();
}
pulic void keyPressed(keyEvent ke) {
int key = ke.getKeyChar();
switch(key) {
case KeyEvent.VK_F1:
msg += "<F1>";
break;
case KeyEvent.VK_F2:
msg += "<F2>";
break;
case KeyEvent.VK_F3:
msg += "<F3>";
break;
case KeyEvent.PAGE_UP:
msg += "<PAGE_UP>";
break;
case KeyEvent.VK_LEFT:
msg += "<VK_LEFT>";
break;
}
repaint();
}
public void paint(Graphics g) {
g.drawString(msg, 10, 10);
}
}
Класс-адаптер - используется когда нужно обработать только определенное действие, например перетаскивание. Друние события (например события мыши) будут игнорироваться. Такие классы называются например MouseMotionAdapter.
import java.awt.*;
import java.awt.event.*;
imoport java.applet.*;
/*
<applet code="AdapterDemo" width=300 height=300>
</applet>
*/
public class AdapterDemo extends Applet {
public void init() {
addMouseMotionListener(new MyMouseMotionAdapter(this);
}
}
class MyMouseMotionAdapter extends MouseMotionAdapter {
AdapterDemo adapterDemo;
public MyMouseMotionAdapter(AdapterDemo adapterDemo) {
this.adapterDemo = adapterDemo;
}
//Обработка перетаскивания
public void mouseDragged(MouseEvent me) {
adapterDemo.showStatus("Mouse Draged");
}
}
Или с помощью внутреннего класса:
imoprt java.applet.*;
import java.awt.event.*;
/*
<applet code="InnerClassDemo" width=300 height=300>
</applet>
*/
public class InnerClassDemo extends Applet {
public void init() {
addMouseListener(new MyMouseAdapter());
}
class MyMouseAdapter extends MouseAdapter {
public void mousePressed(MouseEvent me) {
showStatus("Hell");
}
}
}
Анонимный внутренний класс - класс которому не назначено имя, можно использовать для упрощения класса-адаптера
imoprt java.applet.*;
import java.awt.event.*;
/*
<applet code="InnerClassDemo" width=300 height=300>
</applet>
*/
public class InnerClassDemo extends Applet {
public void init() {
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent me) {
showStatus("Hell");
}
});
}
}
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
AWT - содержатся в пакете java.awt, для создания окон, кнопок и т.д.
Иерархия классов AWT:
Component
|
Container
MenuContainer / \
Interface Window Panel
\ /
Frame
Component - куча методов, переменных и свойств для работы с окнами.
Container - содержит методы, которые позваляют вкладывать в него Component объекты и Container обьекты (система многоуровнего вкдючения). Отвечает за расположение элементов.
Panel - суперкласс для Applet, этот класс чистое окно без заголовка и т.д., сюда с помощью add() можно добавлять кнопки и т.д., а потом позиционировать их.
Window - окно верхнего уровня
Frame - это и есть нормальное окно, в аплете или нормальной программе
Canvas - окно в котором можно рисовать.
Создание окна:
1) Создать класс и наследовать ему Frame
2) Задать размер setSize(int x, int y); getSize();
3) окно невидимо во фрейме, сначало показать setVisible(true);
4) после завершения работы закрыть перехватить событие windowClosing() интерфейса WindowListener и удалить там окно методом setVisible(false);
Рисование
public class A extends Applet {
public void paint(Graphics g) {
g.drawLine(0, 0, 100, 100); //рисует линию, коорд начала и конца
}
}
drawRect(); //прямоугольник
И куча других функций для других фигур.
Color red = new Color(255, 100, 100); плюс методы разные
По умолчанию обьекты рисуются цветом фона по умолчанию. Добавляются методом setColor()
есть способы создания, добавления и получения списка шрифтов, цвета. Плюс методы управления ими.
//Окно во фрэйме
import java.awt.*;
import java.awt.events.*;
import java.applet.*;
/*
<applet code="AppletFrame" width=300 height=300>
</applet>
*/
class SampleFrame extends Frame {
SampleFrame(String title) {
super(title);
MyWindowAdapter adapter = new MyWindowAdapter(this);
addWindowListener(adapter);
}
public void paint(Graphics g) {
g.drawString("this in frame window", 10, 40);
}
}
class MyWindowAdapter extends WindowAdapter {
SampleFrame sampleFrame;
public MyWindowAdapter(SampleFrame sampleFrame) {
this.sampleFrame = sampleFrame;
}
public void windowClosing(WindowEvent we){
sampleFrame.setVisible(false);
}
}
public class AppletFrame extends Applet {
Frame f;
public void init() {
f = new SampleFrame("A Frame Window");
f.setSize(250, 250);
f.setVisible(true);
}
public void start() {
f.setVisible(true);
}
public void stop() {
f.setVisible(false);
}
public void paint(Graphics g) {
g.drawString("This in a applet window", 10, 25);
}
}
Можно создавать также окна в программе. Метод paint() есть и в программе консольной.
Менеджер компонентов AWT.
Элементы кнопки, флажки и т.д. За исключением флажков все элементы все элементы генерируют события.
Добавляются элементы с помощью add(), удаляются remove() (методы из класс Component)
public class Label extends Applet {
init() {
Label l1 = new Label("myName"); //плюс разные методы, setLabel(); getLabel()'
add(l1);
}
}
В java 1 есть еще способ обработки событий переопределением методов компонента.
...................................................................................................
ИЗОБРАЖЕНИЯ - обьект класса Image, можно создавать, загружать и отображать изображение.
//Создается изображение с помощью метода createImage() из класса Component т.к. изображение, чтобы стало видным, надо нарисовать в окне.
Canvas c = new Canvas();
Image test = new c.createImage(200, 100); //Строим обьект типа Image (меттод возвращает пустой Image)
//Загрузить изображение можно с методом getImage из класса Applet:
Image getImage(URL url); // изображение по адресу
Image getImage(URL url, String name); //изображение по адресу которое имеет имя name
//Просомтреть изображение (выводить на экран) можно методом drawImage() из класса Graphics
boolean drawImage(Image imgObj, int left, int top, ImageObserver imgOb);
imgObj - изображение, которое вывести
left и top - верхний левый угол
imgOb - класс реализующий интерфейс ImageObserver
ImageObserver - может контролировать обьект пока он загружается, все классы AWT реализуют интерфейс ImageObserver
/*
<applet code="InnerClassDemo" width=300 height=300>
<param name="img" value="test.gif">
</applet>
*/
public class A extends Applet {
Image img;
public void init() {
img = getImage(getDocumentBase(), getParameter("img")); //getDocumentBase() - путь к текущему документу, вроде;
//getParameter("img") - значение параметра img
}
punlic void paint(Graphics g) {
g.drawImage(img, 0, 0, this); //this видимо возвращает String - имя класса
}
}
Во время загрузки изображения реализация интерфейса ImageObserver в классе Applet каждый раз вызывает paint() по мере загрузки, поэтому видно как картинка шрузится кусочками
ImageObserver определяет только метод imageUpdate() - его можно переопределить, чтобы например выводить сообщения о ходе загрузки ли индикатор. Еще в классе есть переменные по которым можно узнать состояние загрузки.
Двойная буферизация - рисование изображения вне экрана, а потом вывод. Рисовать вне экрана нужно с помощью обьекта Graphics, getGraphics() возвращает такой обьект.
Canvas c = new Canvas();
Image test = c.createImage();
Graphics gc = test.getGraphics();
gc.setColor(Color.red);
gc.fillRect(0, 0, 200, 100);
//рисовать обьект gc методом drawImage(gc, 0, 0, null)
тут null вместо обьекта-нааблюдателя, чтобы не наблюдать, вроде
MediaTrecker - класс позволяющий загружать изображения методом addImage(); не заботясь о методе imageUpdate() м мерцании изображения
ImageProduser - используется длс создания изображений
класс MemoryImageSource - создает с помомощью метода createImage() изображение из массива целых чисел, которые определяют цвета пикселей.
ImageConsumer - абстрактный интерфейс для обьектов которые хотят получать пиксельные данные изображений.
Класс PixelGrabber - создает массив пикселей из изображения.
На базе этих потребителей/производителей можно создавать фильтры меняющие картинку.
Можно делать анимации из изображений меняя в потоке что-нить.
/////////////////////////////////////////////////////////////////////////////////////
ДОПОЛНИТЕЛЬНЫЕ ПАКЕТЫ JAVA
Ядро java Core API - набор основных классов
Отражение java.lang.reflect с помощью отражений можно анализаровать компоненты и описывать его динамически, во время выполнения. (например во время выполнения, а не компиляции можно определять, какие методы, конструкторы и поля будут в классе). Также позваляет просмотреть и вывести какие в класса методы, поля и т.д.
RMI - Remot Method Invocation - позваляет прогрмамме выполнить метод программы расположенной на другом компе (а может даже и на этом?), лучше читать отдельно.
java.text - форматирование текста
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
Разработка ПО
Java Beans
Эту штуку надо ставить, там форма, кнопки и т.д. Компоненты упакованы в jar. Это уже наборготовых кусочков программ, чтобы поставить надо качать.
swing - аналог AWT только платформонезависимый, т.к. написан на чистом java, удобнее и легче. Можно создавать панель вкладок и множество других панелей.
import java.awt.*;
import java.swing.*;
/*
<applet code="JLabelDemo" width=250 height=250>
</applet>
*/
public class JLabelDemo extends JApplet {
public void init() {
Container pane = getContentPane(); //функция возвращает панель на которой все размещаем
ImageIcon i = new ImageIcon("image.gif"); // создали иконку
JLabel jl = new JLabel("Name", i, JLabel.CENTER); //создаем метку
pane.add(jl); //добавляем метку на панель
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////
Сервлет
Это программа выполняющаяся на сервере, можно обрабатывать POST и GET, использовать куки и устанавливать сеансы.
1) Пользователь вводит URL
2) Браузер генерирует запрос из URL
3) Сервер устанавливает соответствие URL и файла.
4) Возвращается в ответе файл. В ответе указан тип данных в формате MIME
(text/plain text/html)
Раньше использовали CGI, но java есть преимущества. Т.к. раньше выполнялось в пределах одного процесса и писалось на C/C++/Perl
Севлет выполняется в пространстве веб-сервера.
Платформонезависимый, у серверов есть Sevlet API
В каждом сервлете можно переопределить:
0) Серверу посылают URL
0.1) Сервер направляет запрос к сервлету, который извлекает сервлет и динамически загружает в адресное пространство сервера.
1) init() - вызывается при загрузке сервлета в память, параметры инициализации можно переслать сервлету.
2) service() - вызывается для обработки каждого запроса
3) destroy() - вызывается, чтобы освободить ресурсы, алгоритм вызова разный для разных серверов.
Java Servlet Development Kit - набор для разработки сервлетов. Тут есть утилита servletrunner (видимо локальный серв), с которой можно запустить сервлет на компе.
Создание:
1) Создать и компилировать сервлет.
2) Запустить servletrunner (он как локальный сервер)
3) Запустить браузер и ввести адрес сервлета
import java.io.*;
import javax.servlet.*;
public class HelloWorld extends GenericServlets {
public void service(ServletRequest request, ServletResponse response)
throws ServletExeption, IOExeption {
response.setContentType("text/html"); // устанавливает тип ответа, тут html
PrintWrite pw = response.getWrite(); // заполняет pw, все записанное в этот поток отправится вместе с ответом, связывает поток ввода и ответ сервера (?)
pw.println("<B>Hello world!");
pw.close();
}
}
Запустить servletrunner, открыть браузер и ввести http://127.0.0.1:8080/servlet/HelloWorld
Servlet API в пакетах javax.servlet и javax.servlet.http
Эти пакеты пока не часть ядра java
В пакетах определены интерфейсы и классы, их нужно наследовать и переопределять.
Интерфейс Servlet определяет методы init() service(), destroy() другие интерфейсы и классы определяют методы для обработки запросов, получение параметров запроса, получение информации о сервере и т.д.
GenericServlets реализует интерфейсы Servlet и ServletConfig (позволяет получать данныеконфигурации, параметры инитиализации)
--------
Пример сервлета читающего параметры сервлета (это не параметры инициализации) (параметры из запросов post. get). Используется ServletResponse
///PostParameters.htm - файл содержит в форме таблицу с 2-мя метками и 2-мя текстовыми полями. e - employee (служащий), p - phone. Тип запроса post
<html>
<body>
<center>
<form name="Form1" method="post" action="http//:localhost:8080/servlet/PostParametersServlet">
<table>
<tr>
<td><b>Employ</td>
<td><input type=textbox name="e" size="25" value=""></td>
</tr>
<tr>
<td><b>Phone</td>
<td><input type=textbox name="p" size="25" value=""></td>
</tr>
</table>
<input type=submit value="Submit">
</form>
</body>
</html>
///PostParametersServlet.java
import java.io.*;
import java.util.*;
import javax.servlet.*;
public class PostParametersServlet extends GenericServlet {
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException
{
PrintWrite pw = response.getWrite();
Enumeration e = request.getParametersNames(); //getParametersNames() - получить перечисление имен параметров
// перебираем параметры пока перечисление не пусто печатаем их
while(e.hasMoreElements()) {
String pname = (String)e.nextElement();
pw.print(pname + " = ");
String pvalue = request.getParameters(pname); //getParameters() - значение параметра pname
pw.println(pvalue);
}
pw.close();
}
}
------