Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Java_sp.doc
Скачиваний:
14
Добавлен:
29.10.2018
Размер:
1.12 Mб
Скачать

86

1. Жизненный цикл приложения Java. Компиляция. JITкомпиляция. Исполнение. 8

2. Классы. Абстрактные классы. Интерфейсы. Наследование. 10

3. Классы и интерфейсы стандартной библиотеки. Списки. Сортировка. 15

4. Классы и интерфейсы стандартной библиотеки. Ассоциированные массивы. Словари. 19

5. Классы и интерфейсы стандартной библиотеки. Потоки ввода-вывода. Файловый ввод-вывод. 21

6. Параллельные процессы. Синхронизация. 25

7. Параллельные процессы. Управление потоками. 29

8. Параллельные процессы. Управление памятью потока. 35

9. JDBC, драйверы строка соединения, класс DriverManager, интерфейс Connection. 39

Стандартный способ получения соединения - это вызов метода DriverManager.getConnection. Этому методу передается строка, содержащая т.н. "URL". Класс DriverManager, представляющий собой уровень управления в JDBC, пытается найти драйвер, который может соединиться к БД с помощью данного URL. Класс DriverManager содержит список зарегистрированных классов Driver, и при вызове метода getConnection он проверяет каждый драйвер и ищет среди них тот, который "умеет" соединятся с БД, указанной в URL. Метод connect драйвера использует этот URL для установления соединения. 40

jdbc - протокола. Протокол, используемый в JDBC URL - всегда jdbc. 41

<subprotocol> (подпротокола) - это имя драйвера или имя механизма соединения с БД. Подпротокол может поддерживаться одним или несколькими драйверами. Лежащий на поверхности пример подпротокола - это "odbc", отведенный для URL, обозначающих имя источника данных ODBC. Например, для доступа к БД через мост JDBC-ODBC нужно использовать URL такого вида: 41

jdbc:odbc:fred 41

В этом примере подпротокол задан как "odbc", а подимя "fred" является локальным источником данных. 41

<subname> (подимени) - это идентификатор БД. Значение подимени может менятся в зависимости от подпротокола, и может также иметь подподимя с синтаксисом, определяемым разработчиком драйвера. Назначение подимени - это предоставление всей информации, необходимой для поиска БД Например, если БД находится в Интернет, то в состав подимени JDBC-URL должен быть включен сетевой адрес, подчиняющийся следующим соглашениям: 41

//hostname:port/subsubname 41

Предполагая, что "dbnet" - это протокол соединения к хосту в Интернет, JDBC-URL может выглядеть так: 41

10. JDBC, создание SQL запросов, интерфейсы Statement, PreparedStatement 42

Объект Statement используется для выполнения SQL-запросов к БД. Существует три типа объектов Statement. Все три служат как бы конейнерами для выполнения SQL-выражений через данное соединение: Statement, PreparedStatement, наследующий от Statement, и CallableStatement, наследующий от PreparedStatement. Они специализируются на различных типах запросов: Statement используется для выполненияпростых SQL-запросов без параметров; PreparedStatement используется для выполнения прекомпилированных SQL-запросов с или без входных (IN) параметров; CallableStatement используется для вызовов хранимых процедур. 42

Создание объектов Statement 42

Как только соединение с определенной БД установлено, оно может использоваться для выполнения SQL-запросов. Объект Statement создается методом Connection.createStatement, как показано ниже: 42

Интерфейс Statement предоставляет три различных метода выполнения SQL-выражений: executeQuery, executeUpdate и execute, в зависимости от SQL-запроса. 42

Метод executeQuery необходим для запросов, результатом которых является один единственный набор значений, таких как запросов SELECT. 42

Метод executeUpdate используется для выполнения операторов INSERT, UPDATE или DELETE, а также для операторов DDL (Data Definition Language - язык определения данных), например, CREATE TABLE и DROP TABLE. Метод executeUpdate возвращает целое число, показывающее, сколько строк было модифицировано. Для выражений типа CREATE TABLE и DROP TABLE, которые не оперируют над строками, возвращаемое методом executeUpdate значение всегда равно нулю. 42

Метод execute используется, когда операторы SQL возвращают более одного набора данных, более одного счетчика обновлений или и то, и другое. 42

Все методы выполнения SQL-запросов закрывают предыдущий набор результатов (result set) у данного объекта Statement. Это означает, что перед тем как выполнять следующий запрос над тем же объектом Statement, надо завершить обработку результатов предыдущего (ResultSet). 42

Объекты Statement закрываются автоматически с помощью сборщика мусора виртуальной машины Java. Тем не менее рекомендуется закрывать их явно после того, как в них отпадает необходимость. 43

11. JDBC, обработка полученных результатов, интерфейсы ResultSet, ResultSetMetaData. 44

ResultSet содержит все строки, удовлетворяющие условиям в SQL-выражении и предоставляет доступ к данным в этих строках посредством набора get-методов, которые организуют доступ к колонкам текущей строки. Метод ResultSet.next используется для перемещения к следующей строке ResultSet, делая ее текущей. 44

Набор данных результата (result set) является таблицей с заголовками колонок и соответствующих значений, возвращенных запросом. Например, если мы имеем запрос SELECT a, b, c FROM Table1, то набор результата будет в следующей форме: 44

a b c 44

-------- --------- -------- 44

12345 Cupertino CA 44

83472 Redmond WA 44

83492 Boston MA 44

Следующий фрагмент кода демонстрирует выполнение SQL-запроса, который возвращает коллекцию строк, в которой колонка 1 - это int, колонка 2 - String и колонка 3 – вещественное число: 44

java.sql.Statement stmt = conn.createStatement(); 44

ResultSet r = stmt.executeQuery("SELECT a, b, c FROM Table1"); 44

while (r.next()) 44

{ 44

// Напечатать значения в текущей строке. 44

int i = r.getInt("a"); 44

String s = r.getString("b"); 44

float f = r.getFloat("c"); 44

System.out.println("ROW = " + i + " " + s + " " + f); 44

} 44

ResultSet содержит т.н. курсор, который указывает на текущую строку данных. Каждый раз, когда выполняется метод next, курсор перемещается на одну строку вниз. Изначально курсор спозиционирован перед первой строкой, и первый вызов next премещает его на первую строку (она становится текущей). С каждым успешным вызовом next курсор перемещается вниз на одну строку, начиная с самой верхней в ResultSet. 44

Курсор сохраняется до тех пор, пока не закроется объект ResultSet или его родительский объект Statement. 44

В SQL курсор для результирующей таблицы имеет имя. Если БД поддерживает позиционированные обновления или позиционированные удаления, то командам обновления или удаления можно передать в качестве параметра имя курсора. Это имя может быть получено с помощью вызова getCursorName. 44

Заметим, что не все СУБД поддерживают позиционированные обновления или удаления. Чтобы узнать, поддерживает ли данное соединение эти операции или нет, можно вызвать методы DatabaseMetaData.supportsPositionedDelete и supportsPositionedUpdate. 45

Методы getXXX предоставляют доступ к значениям в колонках в текущей строке. В пределах одной строки значения могут быть считаны в любом порядке, но ради обеспечения большей совместимости рекомендуется считывать их подряд слева направо и делать это только один раз. 45

Для указания колонки можно использовать либо ее имя, либо ее номер. Например, если вторая колонка объекта ResultSet rs называется "title" и хранит строковое значение, то извлечь его можно одним из двух способов: 45

String s = rs.getString("title"); 45

String s = rs.getString(2); 45

Колонки нумеруются слева направо, начиная с 1. Имена колонок в вызове методов getXXX нечувствительны к регистру букв. 45

Информацию о колонках в ResultSet можно получить с помощью вызова ResultSet.getMetaData. Возвращаемый объект ResultSetMetaData содержит информацию о количестве, типах и свойствах колонок объекта ResultSet. 45

Если известно имя колонки, но не ее индекс, то для поиска номера колонки можно использовать метод findColumn. 45

Методы getXXX пытаются сконвертировать низкоуровневые данные в типы данных языка Java. Например, метод если метод getXXX - это getString и тип данных в БД - VARCHAR, драйвер JDBC сконвертирует VARCHAR в объект String. Возвращаемым из метода getString значением будет Java-объект String. 45

С помощью ResultSet возможно получать очень большие данные типа LONGVARBINARY или LONGVARCHAR. Методы getBytes и getString возвращают эти данные в виде одного большого куска (вплоть до пределов, которые можно узнать с помощью метода Statement.getMaxFieldSize). Тем не менее, может оказаться удобнее считывать очень большие данные небольшими кусками. Это делается с помощью потоков (java.io.InputStream), которые возвращаются некоторыми методами ResultSet. Обратите внимание на то, что к этим потокам надо обращаться сразу, так как они будут закрыты при следующем вызове getXXX объекта ResultSet. (Такое поведение диктуется низкоуровневой реализацией доступа к большим двоичным объектам) 45

Для того, чтобы определить, равно ли значение колонки NULL или нет, надо сначала считать значение колонки, а затем использовать метод ResultSet.wasNull для выяснения этого факта. Значение true означает, что считанное значение равно NULL. 45

Нет никакой необходимости закрывать ResultSet; это делается автоматически родительским объектом Statement, когда последний закрывается, выполняется повторно или используется для извлечения следующего результата в последовательности нескольких результатов. 45

12. Объектно-реляционное отображение. Создание персистентных классов при помощи JPA 46

Hibernate - это механизм отображения в реляционной базе данных объектов java. 46

<hibernate-mapping package="ru.topcode.hibertest.domain"> 46

<class name="User" table="user_list"> 46

<id name="id" column="UserId"> 46

<generator class="native"/> 46

</id> 46

<property name="name" column="Login"/> 46

<property name="psw"/> 46

</class> 46

</hibernate-mapping> 46

13. Объектно-реляционное отображение. Подключаемы провайдеры персистенции. 49

14. Кастомизация мэппинга персистентных классов на поля и таблички БД. 51

15. Объектно-реляционное отображение. Отображение реляционных связей many-to-many, one-to-many, one-to-one. 52

Обычная связь с другим персистентным классов объявляется используя элемент many-to-one. В реляционных терминах это ассоциация многих к одному. В действительности это просто ссылка на объект. 52

<many-to-one 52

name="propertyName" (1) 52

column="column_name" (2) 52

class="ClassName" (3) 52

cascade="all|none|save-update|delete" (4) 52

outer-join="true|false|auto" (5) 52

update="true|false" (6) 52

insert="true|false" (6) 53

property-ref="propertyNameFromAssociatedClass" (7) 53

access="field|property|ClassName" (8) 53

/> 53

(1) 53

name: Имя свойства. 53

(2) 53

column (необязательно): Имя колонки. 53

(3) 53

class (необязательно - по умолчанию тип поля определяется через рефлексию): Имя ассоциированного класса. 53

(4) 53

cascade (необязательно): Определяет, какая операция будет выполняться каскадом от родительского объекта к ассоциированному. 53

(5) 53

outer-join (необязательно - по умолчанию auto): Задействует извлечение ассоциированных объектов, используя объединения outer-join если опция hibernate.use_outer_join конфигурационного файла включена. 53

(6) 53

update, insert (необязательно - по умолчанию true) определяет то, что отображаемые колонки будут включены в SQL-запросы UPDATE и/или INSERT. Установка обоих свойств в false позволяет задавать значение этого свойства либо из другого свойства, которое отображено в той же колонке/колонках, либо посредством триггера, либо другим приложением. 53

(7) 53

property-ref: (необязательно) Имя ключевого свойства ассоциированного класса. По этому свойству будет происходить связывание (join). Если не указано, то используется первичный ключ ассоциированного класса. 53

(8) 53

access (необязательно - по умолчанию property): Стратегия, которую использует Hibernate для доступа к значению данного поля. 53

Ассоциация "один к одному" с другим персистентным классом можно объявить, используя элемент one-to-one. 53

<one-to-one 53

name="propertyName" (1) 53

class="ClassName" (2) 54

cascade="all|none|save-update|delete" (3) 54

constrained="true|false" (4) 54

outer-join="true|false|auto" (5) 54

property-ref="propertyNameFromAssociatedClass" (6) 54

access="field|property|ClassName" (7) 54

/> 54

(1) 54

name: Имя свойства. 54

(2) 54

class (необязательно - по умолчанию определяется рефлексией исходя из типа поля): Имя ассоциированного класса. 54

(3) 54

cascade (необязательно) определяет какая операция будет выполняться каскадом от родительского объекта к ассоциированному. 54

(4) 54

constrained (необязательно) определяет то, что внешний ключ, ссылающийся на таблицу ассоциированного класса, ограничен первичным ключом этой таблицы. Эта опция влияет на порядок, в котором выполняются каскадные операции save() и delete() (а так же используется утилитой экспортирующей схему - schema export tool). 54

(5) 54

outer-join (необязательно - по умолчанию auto): Задействует извлечение ассоциированных объектов, используя объединения outer-join если опция hibernate.use_outer_join конфигурационного файла включена. 54

(6) 54

property-ref: (необязательно) Имя свойства ассоциированного класса, которое входит в первичный ключ данного класса. Если не указано, то используется первичный ключ ассоциированного класса. 54

(7) 54

access (необязательно, по умолчанию property): Стратегия, которую должен использовать Hibernate для доступа к данному полю. 54

16. Объектно-реляционное отображение. Жизненный цикл персистентных объектов (entity lifecycle) 55

17. Объектно-реляционное отображение. Интерфейс EntityManager. 57

Интерфейс Entity Manager используется для взаимодействия с persistence context. 57

18. Объектно-реляционное отображение. Создание запросов на JPQL, SQL 58

19. Работа с XML в Java. Правильно сформированные (well-formed) и корректные (valid) XML документы 60

20. JAXP, основные группы API. 63

21. Работа с XML документами посредством SAX. 65

22. Работа с XML документами посредством DOM. 67

23. Сравнение SAX и DOM подходов к обработке XML документов. 68

24. JAXB, отображение Java класса, отображаемого на XML. 69

25. Создание JAXB контекста, маршалинг и демаршалинг. 70

26. Сервлеты, создание, жизненный цикл 72

27. HTTP запросы GET, POST, PUT, DELETE, HEAD 74

28. Интерфейс servlet, класс HttpServlet 76

29. Создание REST сервисов, JAX RS 79

30. Связка JAXB и JAX RS, переключение типов возвращаемого контента (xml, json) 80

31. JSP 81

32. JSF 84

33. Оптимизация JVM 85

1. Жизненный цикл приложения Java. Компиляция. JiTкомпиляция. Исполнение.

Программа на языке Java (обычно это файл с расширением .java) компилируется в промежуточный стандартный код, который называется байт-кодом (такие файлы имеют расширение .class). (Это не команды какого-то конкретного процессора, а команды так называемой виртуальной машины Java). Эта компиляция не зависит от типа какого-либо конкретного процессора и архитектуры некоего конкретного компьютера. Затем полученные в результате компиляции байт-коды можно выполнять на любом компьютере, имеющем систему, реализующую JVM (Виртуальная машина Java — это совокупность команд вместе с системой их выполнения.). Описанный процесс графически выглядит так:

Другая особенность Java — все стандартные функции, вызываемые в программе, подключаются к ней только на этапе выполнения, а не включаются в байт-коды. Как говорят специалисты, происходит динамическая компоновка (dynamic binding). Это тоже сильно уменьшает объем откомпилированной программы.

В результате мы получаем платформо-независимый язык, программы на котором исполняются существенно быстрее, чем на интерпретируемых языках (хотя, конечно, существенно медленнее, чем на языках компилируемых, но это обязательная плата за независимость от платформы).

Итак, чтобы откомпилировать какой-то исходный файл (с расширением .java), мы запускаем компилятор javac, указав в параметре командной строки имя исходного файла, например Example: C:\>javac Example.java. Компилятор javac создает файл с именем Example.class, который содержит программу в виде байт-кода. А для действительного выполнения программы следует использовать Java-интерпретатор с именем java. Командная строка запуска интерпретатора выглядит следующим образом: C:\> java Example

2. Классы. Абстрактные классы. Интерфейсы. Наследование.

Классы

Класс - это шаблон поведения объектов определенного типа с заданными параметрами, определяющими состояние. Все экземпляры одного класса имеют один и тот же набор свойств и общее поведение, то есть одинаково реагируют на одинаковые сообщения.

Схема синтаксиса описания Java класса:

[Модификаторы]

class ИмяКласса

[extends ИмяСуперкласса]

[implements ИменаИнтерфейсов]

{

Данные класса;

Методы;

}

где:

Модификаторы — ключевые слова типа static, public и т.п., модифицирующие поведение класса по умолчанию(

public — означает, что данный элемент доступен без каких-либо ограничений;

private — доступ разрешен только из данного класса;

protected — доступ разрешен из данного класса и из всех классов-потомков

без описателя — доступ разрешен из всех классов данного пакета)

ИмяКласса — имя, которое вы присваиваете классу;

ИмяСуперкласса — имя класса, от которого наследуется ваш класс;

ИменаИнтерфейсов — имена интерфейсов, которые реализуются данным классом.

Тело класса, в котором в любом порядке перечисляются поля, методы, вложенные классы и интерфейсы, заключается в фигурные скобки.

При описании поля указывается его тип, затем, через пробел, имя и, может быть, начальное значение после знака равенства, которое можно записать константным выражением.

Описание поля может начинаться с одного или нескольких необязательных модификаторов public, protected, private, static, final, transient (не постоянная переменная класса; типа можно не сохранять значение при записи на диск по каким-то причинам), volatile (для синхронизации разделяемых переменных используется аналогично с synchronized). При описании метода указывается тип возвращаемого им значения или слово void , затем, через пробел, имя метода, потом, в скобках, список параметров. После этого в фигурных скобках расписывается выполняемый метод.

Описание метода может начинаться с модификаторов public, protected, private, abstract, static, final, synchronized, native (машинно зависимые методы), strictfp (ограничить вычисление с вещественными числами с плавающей точкой).

В списке параметров через запятую перечисляются тип и имя каждого параметра. Перед типом какого-либо параметра может стоять модификатор final . Такой параметр нельзя изменять внутри метода. Список параметров может отсутствовать, но круглые скобки сохраняются.

Имя метода, число и типы параметров образуют сигнатуру (signature) метода.

abstract class Pet{

   abstract void voice(); 

}

class Dog extends Pet{

   void voice(){

      System.out.printin("Gav-gav!");

   }

}

class Cat extends Pet{

   void voice () {

      System.out.printin("Miaou!"); 

   }

}

При описании класса Pet мы не можем задать в методе voice () никакой полезный алгоритм, поскольку у всех животных совершенно разные голоса.

В таких случаях мы записываем только заголовок метода и ставим после закрывающей список параметров скобки точку с запятой. Этот метод будет абстрактным (abstract), что необходимо указать компилятору модификатором abstract .

Если класс содержит хоть один абстрактный метод, то создать его экземпляры не удастся. Такой класс становится абстрактным, что обязательно надо указать модификатором abstract.

Чтобы избавиться от "абстрактности", необходимо реализовать код для всех абстрактных методов абстрактного класса-предка.

Пометив метод модификатором final , можно запретить его переопределение в подклассах. Это удобно в целях безопасности. Вы можете быть уверены, что метод выполняет те действия, которые вы задали.

Если при описании класса мы не указываем никакое расширение, т. е. не пишем слово extends и имя класса за ним, как при описании класса Pet , то Java считает этот класс расширением класса object.

Сам же класс object не является ничьим наследником, от него начинается иерархия любых классов Java. В частности, все массивы — прямые наследники класса object .

Поскольку такой класс может содержать только общие свойства всех классов, в него включено лишь несколько самых общих методов, например, метод equals() , сравнивающий данный объект на равенство с объектом, заданным в аргументе, и возвращающий логическое значение. Его можно использовать так:

Object objl = new Dog(), obj 2 = new Cat(); 

if (obj1.equals(obj2)) ...

ссылки можно сравнивать на равенство и неравенство:

obj1 == obj2; obj1 != obj 2;

В этом случае сопоставляются адреса объектов, мы можем узнать, не указывают ли обе ссылки на один и тот же объект.

В классах Java имеются конструкторы.

Конструктор имеется в любом классе. Даже если вы его не написали, компилятор Java сам создаст конструктор по умолчанию (default constructor), который, впрочем, пуст, он не делает ничего, кроме вызова конструктора суперкласса.

Конструктор выполняется автоматически при создании экземпляра класса, после распределения памяти и обнуления полей, но до начала использования создаваемого объекта.

Конструктор не возвращает никакого значения. Поэтому в его описании не пишется даже слово void , но можно задать один из трех модификаторов public , protected или private .

Конструктор не является методом, он даже не считается членом класса. Поэтому его нельзя наследовать или переопределить в подклассе.

Тело конструктора может начинаться:

с вызова одного из конструкторов суперкласса, для этого записывается слово super() с параметрами в скобках, если они нужны;

с вызова другого конструктора того же класса, для этого записывается слово this() с параметрами в скобках, если они нужны.

Если же super() в начале конструктора не указан, то вначале выполняется конструктор суперкласса без аргументов, затем происходит инициализация полей значениями, указанными при их объявлении, а уж потом то, что записано в конструкторе.

C=new MyClass(); (new применяется для выделения памяти массивам и объектам).

Метод main()

Всякая программа, оформленная как приложение (application), должна содержать метод с именем main . Он может быть один на все приложение или содержаться в некоторых классах этого приложения, а может находиться и в каждом классе.

Метод main() записывается как обычный метод, может содержать любые описания и действия, но он обязательно должен быть открытым ( public ), статическим ( static ), не иметь возвращаемого значения ( void ). Его аргументом обязательно должен быть массив строк ( string[] ). По традиции этот массив называют args , хотя имя может быть любым.

Эти особенности возникают из-за того, что метод main() вызывается автоматически исполняющей системой Java в самом начале выполнения приложения. При вызове интерпретатора java указывается класс, где записан метод main() , с которого надо начать выполнение.

class MyClass {

   public static void main(String[] args){  }

}

Классы и их отдельные члены могут быть статическими. В этом случае они помечаются ключевым словом static.

Интерфейсы

Java не поддерживет множественное наследование. Альтернатива множественному наследованию – интерфейс.

Интерфейс (interface), в отличие от класса, содержит только константы  и заголовки методов, без их реализации.

Интерфейс — это набор абстрактных методов, которые не содержат никакого кода. По своему предназначению интерфейсы похожи на абстрактные классы, хотя между ними имеются некоторые существенные различия. Так, например, интерфейсы, в отличие от абстрактных классов, могут быть только public или private. Методы, описанные внутри интерфейсов, всегда доступны (public) и абстрактны (abstract). Данные, декларированные в интерфейсе, изначально имеют атрибуты final, public и static, т. е. неизменяемы.

Использовать нужно не интерфейс, а его реализацию (implementation). Реализация интерфейса — это класс, в котором расписываются методы одного или нескольких интерфейсов. В заголовке класса после его имени или после имени его суперкласса, если он есть, записывается слово implements и, через запятую, перечисляются имена интерфейсов.

interface Voice{

void voice(); 

}

class Dog implements Voice{

  public void voice (){

    System.out.println("Gav-gav!");

  } 

}

class Cat implements Voice{

  public void voice (){

    System.out.println("Miaou!");

  } 

}

Наследование

Классы-потомки имеют возможность не только создавать свои собственные переменные и методы, но и наследовать переменные и методы классов-предков. Классы-потомки принято называть подклассами. Непосредственного предка данного класса называют его суперклассом. класс Dog — подкласс (subclass) класса Pet , а класс Pet — суперкласс (superclass) или надкласс класса Dog .

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]