Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Программирование на Java часть 2

.pdf
Скачиваний:
134
Добавлен:
16.03.2016
Размер:
3.07 Mб
Скачать

Методы getField() и getFields() возвращают только открытые члены данных класса. Если требуется получить все поля некоторого класса нужно использовать методы getDeclaredField() и getDeclaredFields(). Эти методы работают точно также как их аналоги getField() и getFields(), за исключением того, что они возвращают все поля, включая закрытые и защищенные. Чтобы получить значение поля, нужно сначала получить для этого поля объект типа Field затем использовать метод get(). Метод принимает входным параметром ссылку на объект класса.

Class c = obj.getClass(); Field field = c.getField("name");

String nameValue = (String) field.get(obj)

Так же у класса Field имеются специализированные методы для получения значений примитивных типов: getInt(), getFloat(), getByte() и др.. Для установки значения поля, используется метод set().

Class c = obj.getClass(); Field field = c.getField("name"); field.set(obj, "New name");

Для примитивных типов имеются методы setInt(), setFloat(), setByte() и др. Вопрос к читателю, можно ли изменить значение private поля? А private final? Ответ узнаем чуть позже.

3.11.6 Исследование конструкторов класса

Class c = obj.getClass();

Constructor[] constructors = c.getConstructors(); for (Constructor constructor : constructors) {

Class[] paramTypes = constructor.getParameterTypes(); for (Class paramType : paramTypes) {

System.out.print(paramType.getName() + " ");

}

System.out.println();

}

Чтобы получить информацию об открытых конструкторах класса, нужно вызвать метод getConstructors() для объекта Class. Этот метод возвращает массив объектов типа java.lang.reflect.Constructor. С помощью объекта Constructor можно затем получить имя конструктора, модификаторы, типы параметров и генерируемые исключения. Можно также получить по отдельному открытому конструктору, если известны типы его параметров.

Class[] paramTypes = new Class[] { String.class, int.class }; Constructor aConstrct = c.getConstructor(paramTypes);

Методы getConstructor() и getConstructors() возвращают только открытые конструкторы. Если требуется получить все конструкторы класса, включая закрытые можно использовать методы getDeclaredConstructor() и

111

getDeclaredConstructors() эти методы работают точно также, как их аналоги getConstructor() и getConstructors().

3.11.7 Исследование информации о методе, вызов метода.

Class c = obj.getClass();

Method[] methods = c.getMethods(); for (Method method : methods) {

System.out.println("Имя: " + method.getName());

System.out.println("Возвращаемый тип: " + method.getReturnType().get Name());

Class[] paramTypes = method.getParameterTypes(); System.out.print("Типы параметров: ");

for (Class paramType : paramTypes) { System.out.print(" " + paramType.getName());

}

System.out.println();

}

Чтобы получить информацию об открытых методах класса, нужно вызвать метод getMethods() для объекта Class. Этот метод возвращает массив объектов типа java.lang.reflect.Method. Затем с помощью объекта Method можно получить имя метода, тип возвращаемого им значения, типы параметров, модификаторы и генерируемые исключения. Также можно получить информацию по отдельному методу если известны имя метода и типы параметров.

Class c = obj.getClass();

Class[] paramTypes = new Class[] { int.class, String.class};

Method m = c.getMethod("methodA", paramTypes);

Методы getMethod() и getMethods() возвращают только открытые методы, для того чтобы получить все методы класса не зависимо от типа доступа, нужно воспользоватся методами getDeclaredMethod() и getDeclaredMethods(), которые работают точно также как и их аналоги

(getMethod() и getMethods()). Интерфейс Java Reflection Api позволяет динамически вызвать метод, даже если во время компиляции имя этого метода неизвестно (Имена методов класса можно получить методом getMethods() или getDeclaredMethods()). В следующем примере рассмотрим вызов метода зная его имя. Например метод getCalculateRating:

Class c = obj.getClass();

Class[] paramTypes = new Class[] { String.class, int.class };

112

Method method = c.getMethod("getCalculateRating", paramTypes);

Object[] args = new Object[] { new String("First Calculate"), new Integer(10) };

Double d = (Double) method.invoke(obj, args);

В данном примере сначала получаем объект Method по имени метода getCalculateRating, затем вызываем метод invoke() объекта Method, и

получаем результат работы метода. Метод invoke принимает два параметра, первый - это объект, класс которого объявляет или наследует данный метод, а второй - массив значений параметров, которые передаются вызываемому методу. Если метод имеет модификатор доступа private, тогда выше приведѐнный код нужно модифицировать таким образом, для объекта Method

вместо метода getMethod() вызываем getDeclaredMethod(), затем для получения доступа вызываем setAccessible(true).

Method method = c.getDeclaredMethod("getCalculateRating", paramTypes); method.setAccessible(true);

3.11.8 Загрузка и динамическое создание экземпляра класса

Class c = Class.forName("Test");

Object obj = c.newInstance();

Test test = (Test) obj;

С помощью методов Class.forName() и newInstance() объекта Class

можно динамически загружать и создавать экземпляры класса в случае, когда имя класса неизвестно до момента выполнения программы. В приведенном коде мы загружаем класс с помощью метода Class.forName(), передавая имя этого класса. В результате возвращается объект типа Class. Затем мы вызываем метод newInstance() для объекта типа Class, чтобы создать экземпляры объекта исходного класса. Метод newInstance() возвращает объет обобщенного типа Object, поэтому в последней строке мы приводим возвращенный объект к тому типу, который нам нужен.

И напоследок, пример модификации private полей.

import java.lang.reflect.Field; class WithPrivateFinalField {

private int i = 1;

private final String s = "String S"; private String s2 = "String S2";

public String toString() {

return "i = " + i + ", " + s + ", " + s2;

}

}

113

public class ModifyngPrivateFields {

public static void main(String[] args) throws Exception { WithPrivateFinalField pf = new WithPrivateFinalField();

Field f = pf.getClass().getDeclaredField("i"); f.setAccessible(true);

f.setInt(pf, 47); System.out.println(pf);

f = pf.getClass().getDeclaredField("s"); f.setAccessible(true);

f.set(pf, "MODIFY S"); System.out.println(pf);

f = pf.getClass().getDeclaredField("s2"); f.setAccessible(true);

f.set(pf, "MODIFY S2"); System.out.println(pf);

}

}

Из приведѐнного кода видно что private поля можно изменять. Для этого требуется получить объект типа java.lang.reflect.Field с помощью метода getDeclaredField(), вызвать метод setAccessible(true) и с помощью метода set()

устанавливаем значение поля. Учтите что поле final при выполнении данной процедуры не выдаѐт предупреждений, а значение поля остаѐтся прежним, т.е. final поля остаются неизменные.

114

Выводы к главе:

Swing представляет собой набор классов, применяемых для создания графических пользовательских интерфейсов (Graphical User Interface – GUI) современных приложений, в том числе Web-программ.

Swing поддерживает настраиваемые стили.

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

Способ отображения на экране.

Реакция на действия пользователя.

Информация, связанная с данным компонентом.

Компоненты – это независимые элементы, в качестве примеров которых можно привести кнопки или линейные регуляторы.

Контейнер может содержать в себе несколько компонентов и представляет собой специальный тип компонента.

В Swing используется тот же механизм обработки событий, что и в AWT, – это модель делегирования событий.

Согласно модели делегирования, событие является объектом, описывающим изменения состояния источника.

Источник события – это объект, сгенерировавший его. Сгенерировав событие, источник должен передать его всем зарегистрированным обработчикам.

Обработчик событий – это объект, оповещаемый о возникновении события.

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

Расположение компонентов в составе контейнера определяется диспетчером компоновки, связанным с этим контейнером. Диспетчер можно отключить, написав setLayout(null), тогда позиционирование будет ручное, т.е. каждой компоненте нужно задать ее координаты и размеры.

115

ГЛАВА 4. РАЗРАБОТКА ПРИЛОЖЕНИЯ С ИСПОЛЬЗОВАНИЕМ БИБЛИОТЕКИ SWING РАБОТАЮЩЕГО С БАЗОЙ ДАННЫХ MYSQL

Тема 4.1. Примерная структура проекта

Создадим в пакете src несколько подпакетов: by.belhard.dao – реализация DaoInterface by.belhard.entity – классы-сущности by.belhard.helpers – класс для шифрования паролей by.belhard.main – запуск проекта(метод main) by.belhard.mysql – классы для работы с базой данных

by.belhard.user_interface – все классы для визуальной части

Рисунок 4.1 – Структура проекта.

Учебный проект может иметь следующую структуру пользовательского интерфейса(рисунок 4.2).

Рисунок 4.2 – Структура пользовательского интерфейса.

116

При запуске приложения появляется StartFrame, в котором вводятся параметры для соединения с MySQL сервером. При нажатии на кнопку create должна установиться база данных( т.е. создаются все таблицы необходимые для данного проекта). Кнопка delete удаляет базу данных с сервера, connect приводит к вызову LoginFrame, который предназначен для ввода логина и пароля. Если пользователь уже есть в базе данных, то в зависимости от его роли открывается либо AdminFrame, либо UserFrame. Если пользователя ещѐ нет в базе данных, то он нажимает кнопку registration и переходит в

RegistrationFrame.

Тема 4.2. Проектирование базы данных для проекта

В качестве примера будем реализовывать следующее задание: Система Интернет-магазин. Администратор добавляет информацию о

Товаре. Клиент делает и оплачивает Заказ на Товары. Администратор регистрирует Продажу и может занести неплательщиков в «черный список».

Для реализации данного задания необходимо создать 4 таблицы, связанные между собой.

Users

users_id(PK)

login

pass

role

balance

block_status

delete_status

1

User1

1111

1

5000

0

0

2

User2

2222

1

3000

0

0

3

Admin

1234

0

10000

0

0

Goods

goods_id(PK)

 

name

image_path

 

price

description

 

delete_

 

 

 

 

 

 

 

 

 

status

1

 

Computer

good1.jpg

 

1000

Very big computer

0

2

 

Mouse

good2.jpg

 

10

mad skills mouse

0

3

 

Keyboard

good3.jpg

 

15

defender keyboard

0

Orders

 

 

 

 

 

 

 

 

 

orders_id(PK)

 

users_id(FK)

payment

 

delete_status

total_cost

1

 

1

 

processing

0

50

 

2

 

2

 

processing

0

3000

 

3

 

1

 

reject

 

0

150

 

Goods_in_orders

 

 

 

 

 

 

 

orders_id(FK)

 

goods_id(FK)

count

 

 

 

 

1

 

2

 

5

 

 

 

 

 

2

 

1

 

3

 

 

 

 

 

3

 

3

 

10

 

 

 

 

 

 

 

 

 

117

 

 

 

 

Тема 4.3. Классы-сущности

В пакете entity для каждого класса создадим класс-сущность. Имя класса-сущности совпадает с названием таблицы, названия полей совпадают с названиями столбцов, типы должны соответствовать. Для хеширования пароля напишем дополнительный класс Sha1Encryption.

Листинг 4.2

package by.belhard.helpers;

import java.io.UnsupportedEncodingException; import java.security.MessageDigest;

import java.security.NoSuchAlgorithmException; import java.util.Formatter;

public class Sha1Encryption {

public static String encryptPassword(String password)

throws NoSuchAlgorithmException, UnsupportedEncodingException { String sha1 = "";

MessageDigest crypt = MessageDigest.getInstance("SHA-1"); crypt.reset();

crypt.update(password.getBytes("UTF-8")); sha1 = byteToHex(crypt.digest());

return sha1;

}

private static String byteToHex(final byte[] hash) { Formatter formatter = new Formatter();

for (byte b : hash) { formatter.format("%02x", b);

}

String result = formatter.toString(); formatter.close();

return result;

}

}

package by.belhard.entity;

import static by.belhard.helpers.Sha1Encryption.encryptPassword; import java.io.UnsupportedEncodingException;

import java.security.NoSuchAlgorithmException;

118

public class Users {

private int users_id; private String login; private String pass; private int role; private int balance;

private int block_status; private int delete_status;

public Users(int users_id) { this.users_id = users_id; this.login = "";

this.pass = ""; this.role = 1; this.block_status = 0; this.delete_status = 0; this.balance = 0;

}

public Users(int users_id, String login, String pass, int role, int block_status, int balance)

throws NoSuchAlgorithmException, UnsupportedEncodingException { this.users_id = users_id;

this.login = login;

this.pass = encryptPassword(pass); this.role = role;

this.block_status = block_status; this.balance = balance;

}

public Users(String login, String pass, int role, int block_status, int delete_status, int balance)

throws NoSuchAlgorithmException, UnsupportedEncodingException {

this.login = login;

this.pass = encryptPassword(pass); this.role = role;

this.block_status = block_status; this.delete_status = delete_status; this.balance = balance;

}

public Users(String login, int balance) { this.login = login;

119

this.balance = balance;

}

public int getBalance() { return balance;

}

public void setBalance(int balanse) { this.balance = balanse;

}

public int getUsers_id() { return users_id;

}

public void setUsers_id(int users_id) { this.users_id = users_id;

}

public String getLogin() { return login;

}

public void setLogin(String login) { this.login = login;

}

public String getPass() { return pass;

}

public void setPass(String pass) { this.pass = pass;

}

public int getRole() { return role;

}

public void setRole(int role) { this.role = role;

}

public int getBlock_status() { return block_status;

120