Вы находитесь на странице: 1из 104

Блоки

инициализации
Блоки инициализации

Перед выполнением приложения Java загрузчик


классов Java загружает его начальный класс – класс с
методом public static void main(String [] args), – и
верификатор Java проверяет байт-код этого класса.
Затем этот класс инициализируется.

1) Первый вид инициализации класса – это


автоматическая инициализация полей классов в
значения по умолчанию.
Значение по умолчанию для типа char - это символ
‘NUL’, который означает, что это не отображаемый
символ.

2
Блоки инициализации

Пример 1:
public class InitDemo1 {
private static char ch;
private static boolean bb;
private static byte by;
private static int ii;
private static float ff;
private static String str;
private static int[] array;
public static void main(String[] arg){ Console output:
System.out.println(“char: “ + ch); char:
System.out.println(“boolean: “ + bb); boolean: false
System.out.println("byte: "+by); byte: 0
//... int: 0
System.out.println("String: "+str); float: 0.0
System.out.println("Array: "+array); String: null
} Array: null
}
3
Блоки инициализации

2) Второй вид инициализации класса - это явные


инициализаторы полей класса в их начальные
значения (каждое поле класса может явно быть
проинициализировано некоторым значением и
инициализацию можно записать в одну строку).

public class InitDemo2 {


private static char ch = 'A';
private static boolean bb = true;
private static byte by = -56;
private static int ii = 1000;
private static float ff = 1.25e-2F;
private static String str = "Data";
private static int[] array = {0, 1, 2, 3};
// …….
}
4
Блоки инициализации

Компилятор Java автоматически генерирует метод


инициализации класса (внутренний метод с именем
<clinit>) для каждого класса.

Метод гарантированно будет вызываться только один раз,


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

public class InitDemo3 {


//...
private static byte by = 17; Обратное не
private static int ii = 24 * by; допускается
//...
}

5
Блоки инициализации

В выражении инициализации поля класса можно


использовать обращение к статическому методу
(преимущество - повторное использование, если вам нужно
инициализировать поле класса).
public class InitDemo4 {
private static int ii = initSt();
//...
private static int initSt() {
System.out.println("Init ii value");
return 1000;
}
//...
public static void main(String[] arg) {
Console output:
System.out.println(“Main");
System.out.println("int: " + ii); Init ii value
} Main
} int: 1000
6
Блоки инициализации

3) Третий вид инициализации – это статические блоки


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

Ограничения:
оператор return не может использоваться в пределах
статического блока инициализатора;
ключевое слово this не может использоваться в пределах
статического блока инициализатора;
на не статическую переменную нельзя ссылаться из
статического блока инициализатора.

Компилятор Java вставляет код статического блока в метод


инициализации класса (метод <clinit>) после инициализации
полей класса выражением.

7
Блоки инициализации

Пример 2:
public class InitDemo5 {
private static char[] alph;
public static void main(String[] arg) {
System.out.print(Arrays.toString(alph));
}
static {
alph = new char[26];
int i = 0;
for (char c = 'a'; i < alph.length; c++, i++) {
alph[i] = c;
}
}
}

8
Блоки инициализации

Особенности

Класс может иметь любое количество статических


блоков инициализации;

Они могут появляться в любом месте тела класса;

Исполнительная система гарантирует, что статические


блоки инициализации вызываются в том порядке, в
котором они появляются в исходном коде;

Такой блок выполняется только один раз, когда класс


инициализируется или загружается.

9
Блоки инициализации

4) Четвертый вид инициализации – не статические блоки


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

Выглядят :
{
// Любой код, необходимый для инициализации
}

Используются для разделения блока кода между


несколькими конструкторами.

10
Блоки инициализации

Пример 3:

public class Student { public class Student {


private static int numOfStudents; private static int numOfStudents;
//... //...
public Student() { {
//... numOfStudents++;
numOfStudents++; }
}
public Student() {
public Student(String name) { //...
//... }
numOfStudents++;
} public Student(String name) {
} //...
}
}
Вынесение общего
Дублирование
кода в логический
кода
блок

11
Блоки инициализации

Порядок инициализации класса

Инициализация полей класса в значения на умолчанию

Инициализация полей класса выражениями

Выполнение статических блоков инициализации

Если это класс с точкой входа, то выполнение метода


main()

12
Блоки инициализации

Порядок инициализации при создании экземпляра класса

Рекурсивный вызов и выполнение конструкторов


суперклассов

Инициализация полей экземпляра значениями по


умолчанию или начальными значениями

Выполнение логических блоков инициализации

Выполнение тела конструктора класса

13
Блоки инициализации

Пример 4:
public class InitDemo6 {
private int a = 5;
private static int b = 100;
{ a = -5;
System.out.println("Logical block");
}
public InitDemo6() {
a = 10;
System.out.println("Constructor");
}
static { b = -5;
System.out.println("Static block");
Console output:
} Static block
public static void main(String[] arg) { Main
System.out.println("Main"); Logical block
InitDemo6 obj = new InitDemo6(); Constructor
System.out.println("a=" + obj.a); a=10
}
} 14
Блоки инициализации

Инициализация переменной типа final

должна быть инициализирована в той же строке, в


которой и объявлена;
должна быть инициализирована в каждом
конструкторе;
должна быть инициализирована в одном из
логических блоков класса.

Потому что, переменная типа final может быть


инициализирована только один раз.

15
Блоки инициализации

Пример 5:
public class InitDemo7 {
private final int xx = 50;
private final int zz;
private final int yy;
{
zz = 20;
System.out.println("Non-static block");
}
public InitDemo7() {
yy = 30;
System.out.println("Constructor");
}
public static void main(String[] arg) {
System.out.println("Main");
InitDemo7 obj = new InitDemo7();
}
}
16
Пакеты

17
Пакеты

Java пакеты – это механизм группирования классов Java,


которые связаны друг с другом, в один "модуль" (пакет).

Разделение классов на пакеты – улучшает читабельность


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

java

lang util awt

System.class String.class ArrayList.class Map.class Button.class


18
Пакеты

Описание пакета:
package <имя пакета>;

Иерархия пакетов:
package <pk>{.<pk>}N0 ;

Доступ к классу в другом пакете:


com.mypack.Test;

Импортирование классов:
import <pk>{.<pk>}N0.<имя класса>|*;

19
Пакеты

Пример 6:

package com.epam.test;
Импорт всех
import com.epam.teststuds.*; классов

public class Main {


public static void main(String[] arg) {
Student student = new Student();
}
}

20
Пакеты
Статический импорт

Статический импорт позволяет ссылаться на


статические элементы одного класса в другом без
указания полного пути (т.е. удалить шаблонное
повторение имени класса).

Когда необходимо использовать статический импорт?


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

Например,
import static java.lang.Math.PI;
или
import static java.lang.Math.*;
21
Пакеты

Пример 7:

package com.nau.test;
import static java.lang.Math.*;
public class Main {
public static void main(String[] arg) {
double r = 3;
System.out.println(2 * PI * r);
System.out.println( floor( cos(PI) ) );
}
}
Без указания
принадлежности
классу

22
Пакеты

Организация пакетов

Соглашения об именовании пакетов


Компании должны использовать свои
зарезервированные доменные имена в Интернете,
чтобы с них начинать имена пакетов. Например,
com.epam.test.

Если доменное имя в Интернет содержит


недопустимый символ (например, дефис), то нужно
заменить его подчеркиванием;
Если компонент доменного имени начинается с цифры
или содержит зарезервированное ключевое слово Java,
то нужно добавить подчеркивание в имя компонента.

23
Пакеты

Пакеты тесно связаны со структурой каталогов,


используемой для хранения классов.

Например, класс MyClass4 пакета


com.zzz.project1.subproject2 хранится в
"$BASE_DIR\com\zzz\project1\subproject2\MyClas
s4.class",
где "$BASE_DIR" - обозначает базовый каталог пакетов.
24
Пакеты

Базовый каталог ($BASE_DIR) может быть


расположен в любом месте файловой системы.

Компилятор и система исполнения Java должны быть


проинформированы о локализации $BASE_DIR,
чтобы найти классы.

Достигается это с помощью переменной среды


окружения виртуальной машины называемой
CLASSPATH.

CLASSPATH похож на переменную PATH среды


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

25
Пакеты

При создании пакета всегда следует руководствоваться


простым правилом: называть его именем простым, но
отражающим смысл, логику поведения и
функциональность объединенных в нем классов.
Например,
by.bsu.eun.administration.constants
by.bsu.eun.administration.dbhelpers
by.bsu.eun.common.constants
by.bsu.eun.common.dbhelpers.annboard
by.bsu.eun.common.dbhelpers.courses
by.bsu.eun.common.dbhelpers.guestbook
by.bsu.eun.common.dbhelpers.learnres
by.bsu.eun.common.dbhelpers.messages
by.bsu.eun.common.dbhelpers.news
by.bsu.eun.common.dbhelpers.prepinfo
by.bsu.eun.common.dbhelpers.statistics
by.bsu.eun.common.dbhelpers.subjectmark
by.bsu.eun.common.dbhelpers.subjects
26
Архивирование
java-программ
Архивирование java
java--программ

Java Archive (JAR) – это независимый от платформы формат


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

Достоинства:
Сжатие данных (с помощью алгоритма ZIP);
Легкость в распространении (передача одного большого
файла по сети вместо множества мелких файлов идет
быстрее и более эффективно);
Аутентификация: JAR-файл может быть подписан
цифровой подписью автора.

Среда исполнения Java (JRE) или Java-приложения могут


загружать классы из jar-файла непосредственно, без
необходимости явного (предварительного)
распаковывания jar-файла.
28
Архивирование java
java--программ

Для поддержки таких функций JAR, как:


специфицирование точки входа в java-программу;
создание цифровой подписи;
контролирование версий программы
используется файл, называемым манифестом
манифестом.

Манифест – это специальный файл (имя по


умолчанию - MANIFEST.MF), находящийся в
директории "META-INF" и содержащий информацию
о файлах, находящихся в jar-файле.

29
Архивирование java
java--программ

Например,

1. Manifest-Version: 1.0
2. Created-By: 1.7.0_06 (Oracle Corporation)
3. Main-Class: MyPackage.Main
4.
Атрибут,
Пустая строка определяющий класс с
(обязательно) методом main()

Если jar-файл имеет точку входа, он является


исполнительной jar-программой, которую можно запустить
из командной строки:
java -jar <имя файла>.jar

30
Архивирование java
java--программ

Создание jar-файла

В состав JDK входит утилита jar.exe, с помощью которой и


происходит упаковывание приложений Java:
jar <ключи> <имя jar-файла> <имя главного класса> <список классов>

Ключи:
c – создать новый JAR-файл;
f – имя JAR-файла указывается первым в списке;
e – включить в манифест атрибут Main-Class, имя которого
указывается вторым в списке;
v – выводить информацию о всех своих действиях.

31
Архивирование java
java--программ

Например,

jar cvfe app.jar demo.Main certification/ExamQuestion.class


exam/AnnualExam.class demo/Main.class

32
Документирование
кода
Документирование кода

В языке Java используются блочные и однострочные


комментарии /* */ и //, аналогичные комментариям,
применяемым в C++.
Введен также новый вид комментария /** */, который может
содержать дескрипторы вида:

@author – задает сведения об авторе;


@version – задает номер версии класса;
@exception – задает имя класса исключения;
@param – описывает параметры, передаваемые методу;
@return – описывает тип, возвращаемый методом;
@deprecated – указывает, что метод устаревший и у него есть
более совершенный аналог;
@since – с какой версии метод (член класса) присутствует;
@throws – описывает исключение, генерируемое методом;
@see – что следует посмотреть дополнительно.
Документирование кода
Пример 3:
public class User {
/**
* personal user's code /**
*/ * @param numericCode the numericCode
to set
private int numericCode;
* parameter numericCode to set
/** */
* user's password public void setNumericCode(int
numericCode) {
*/ this.numericCode = numericCode;
private String password; }
/**
/**
* @return the password
* see also chapter #3 "Classes" * return the password
*/ */
public String getPassword() {
public User() { return password;
password = "default"; }
/**
}
* @param password the password to set
/** * parameter password to set
* @return the numericCode */
public void setPassword(String
* return the numericCode password) {
*/ this.password = password;
public int getNumericCode() { }
}
return numericCode;
}
Документирование кода
Результат:
docJava

class User
java.lang.Object
docJava.User

public class User


extends java.lang.Object

Filed Summary
private int numericCode
personal user’s code
private password
java.lang.String user’s password

Constructor Summary
User()
see also chapter #3 “Classes”

Method Summary
int getNumericCode ()

java.lang.String getPassword ()

void setNumericCode(int numericCode)


parameter numericCode to set
void setPassword(java.lang.String password)
parameter password to set
Реализация
принципа ООП:
наследование
Реализация принципа ООП: наследование

Наследование – это возможность создавать классы со


свойства, общими для набора связанных элементов.

Такие классы могут быть унаследованы другими


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

Например,
Класс – новый автомобиль (Car); Car
Класс – подержанный автомобиль
(пробег, функция вычисления
стоимости с учетом пробега) UsedCar

38
Реализация принципа ООП: наследование

Преимущества наследования: многократное


использование.

После того, как поведение (метод) определяется в


суперклассе, это поведение автоматически
наследуется всеми подклассами (таким образом, вы
пишете метод только один раз и он может быть
использован всеми подклассами);
После того, как набор свойств (поля) определен в
суперклассе, этот же набор свойств наследуется всеми
подклассами (класс и его дочерние классы разделяют
общий набор свойств);
Подклассу нужно только реализовать различия между
собой и родителем.

39
Реализация принципа ООП: наследование

Существуют две формы наследования:


Одиночное (один родительский класс);
Множественное (два и более родительских классов).
В Java реализовано только одиночное наследование.

Цепочки наследования
40
Реализация принципа ООП: наследование

РЕАЛИЗАЦИЯ НАСЛЕДОВАНИЯ

{<доступ>}02 class <имя подкласса> extends <имя суперкласса> {


<тело подкласса>
}

В зависимости от прав доступа к элементам суперкласса


подкласс:
наследует открытые (public) и защищенные (protected)
элементы вне зависимости в одном или разных пакетах они
определены;
наследует элементы package-private, если они определены
в одном пакете;
закрытые элементы суперкласса (private) и конструкторы не
наследуются.

41
Реализация принципа ООП: наследование

Что вы можете сделать в подклассе?

В отношении полей:
Унаследованные поля могут быть использованы
непосредственно (напрямую), как и любые другие поля;

Вы можете объявить поле в подклассе с тем же именем, что


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

Вы можете объявить новые поля в подклассе, которых нет в


суперклассе.

42
Реализация принципа ООП: наследование

Что вы можете сделать в подклассе?

В отношении методов:
Унаследованные методы могут быть использованы
непосредственно (напрямую), как они есть;

Вы можете написать в подклассе новый метод экземпляра,


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

Вы можете написать в подклассе новый метод класса


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

Вы можете объявить новые методы в подклассе, которых


нет суперклассе.
43
Реализация принципа ООП: наследование

Что вы можете сделать в подклассе?

В отношении конструкторов:
Вы можете написать конструктор подкласса, который
вызывает конструктор суперкласса, неявно или с
помощью ключевого слова super.

Примечание: Обычно явный вызов конструктора


суперкласса в теле конструктора подкласса
используется для инициализации закрытых
элементов суперкласса:
super(<список аргументов>);

44
Реализация принципа ООП: наследование

Пример 8: инициализации закрытых элементов суперкласса,


class Base {
private int a, b;
Base(int a, int b) { this.a = a; this.b = b; }
}
class Derived extends Base {
private int c; Явное обращение к
Derived (int a, int b, int c) { конструктору суперкласса
super(a, b); должно быть первым
this.c = c; оператором
}
}
public class Demo {
public static void main(String [] s) {
Derived obj = new Derived(1, 2, 3);
}
} 45
Реализация принципа ООП: наследование

Соглашение:
при создании объекта подкласса конструкторы всех классов
вызываются в порядке их подчиненности – от суперкласса
к подклассу. Такие вызовы называются цепочками
конструкторов.

Поэтому явное обращение к конструктору суперкласса


должно быть первым оператором конструктора
подкласса;

Если конструктор подкласса не вызывает явно ни один из


конструкторов суперкласса, то автоматически вызывается
конструктор по умолчанию суперкласса.

Однако, если в суперклассе нет конструктора по


умолчанию, а конструктор подкласса явно не вызывает
никакого другого конструктора суперкласса, то
компилятор Java выдает сообщение об ошибке.
46
Реализация принципа ООП: наследование

ПЕРЕОПРЕДЕЛЕНИЕ МЕТОДОВ

Метод экземпляра подкласса с той же сигнатурой (имя,


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

При переопределении метода можно использовать


аннотацию @Override, которая указывает компилятору, что
это переопределяемый метод суперкласса (если компилятор
обнаруживает, что этот метод не существует ни в одном из
суперклассов, то он будет генерировать ошибку).

47
Реализация принципа ООП: наследование

Пример 9: переопределения методов:


class Base {
void show() { System.out.println("Base"); }
}
class Derived extends Base {
@Override
void show() { System.out.println("Derived"); }
}
public class Demo1 {
public static void main(String[] args) {
Base base = new Base();
Derived obj = new Derived();
base.show(); Вывод консоли:
obj.show(); Base
} Derived
}
48
Реализация принципа ООП: наследование

Если необходимо вызвать не переопределенный метод


суперкласса, то используется ключевое слово super:
class Base {
void show() { System.out.println("Information from Base"); }
}
class Derived extends Base {
@Override
void show() {
super.show();
System.out.println("Information from Derived"); }
}
public class Demo2 {
public static void main(String[] args) {
Derived obj = new Derived();
obj.show();
} Вывод консоли:
} Information from Base
Information from Derived
49
Реализация принципа ООП: наследование

СОКРЫТИЕ (ЗАТЕНЕНИЕ) ПОЛЕЙ

В подклассе: если поле имеет тоже имя, что и поле в


суперклассе, то оно скрывает поле суперкласса, даже
если их типы различаются.

Для обращения к полю суперкласса используется


ключевое слово super.

Не рекомендуются скрытые поля, так как это


делает код трудно читаемым!

50
Реализация принципа ООП: наследование

Пример 10: затенения:


class Vehicle {
protected int maxSpeed = 230;
public void printSpeed() {
System.out.println("Max Speed = " + maxSpeed); }
}
class Bicycle extends Vehicle {
protected int maxSpeed = 50;
public void showSpeed() {
System.out.println("Max Speed = " + maxSpeed); }
}
class Demo3 {
public static void main(String[] args) {
Bicycle bicycle = new Bicycle();
bicycle.printSpeed(); Console output:
bicycle.showSpeed(); Max Speed = 230
} Max Speed = 50
} 51
Реализация принципа ООП: наследование

Пример 11: обращения к полю суперкласса при его затенении:


class Vehicle {
protected int maxSpeed = 230;
}
class Bicycle extends Vehicle {
protected int maxSpeed = 50;
public void showSpeed() {
System.out.println(super.maxSpeed);
System.out.println(maxSpeed);
}
}
class Demo3 {
public static void main(String[] args) {
Bicycle bicycle = new Bicycle();
bicycle.showSpeed(); Console output:
} 230
} 50
52
Реализация принципа ООП: наследование

При использовании ключевого слова super


обращение всегда происходит к
ближайшему суперклассу.

ЗАПРЕЩЕНИЕ ПЕРЕОПРЕДЕЛЕНИЯ
МЕТОДА
Для отмены возможности переопределения
метода перед его описанием используется
модификатор final
(компилятор допускает переопределение
такого метода, однако во время выполнения
возникнет «Ошибка исполнения»).

53
Класс Object
Реализация принципа ООП: наследование

В корне иерархии классов находится класс


java.lang.Object, который является наиболее общим
из всех классов.

Каждый класс имеет класс Object в качестве


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

55
Реализация принципа ООП: наследование

class СustomСlass {
Класс без методов и полей
}
public class Demo5 {
public static void main(String[] arg) {
СustomСlass myClass = new СustomСlass();
myClass.
}
}

Унаследованные
методы класса
Object
Реализация принципа ООП: наследование

class СustomСlass extends Object {


Явное наследование Object
}
public class Demo5 {
public static void main(String[] arg) {
СustomСlass myClass = new СustomСlass();
myClass.
}
}

Унаследованные
методы класса
Object
Реализация принципа ООП: наследование

Методы класса Object


Название Описание
clone() Создание клона объекта
equals(Object obj) Сравнение двух объектов
finalize() Выполнение завершающей работы перед
уничтожением объекта сборщиком мусора
hashCode() Генерация уникального идентификатора объекта
toString() Возвращение строки символов с описанием объекта
(автоматически вызывается методами print() и
println())
wait() Перевод поток в состояние ожидания
notify() Возобновление (уведомление) одного из потоков,
вызвавших метод wait() на этом же объекте
notifyAll() Возобновление (уведомление) всех потоков,
вызвавших метод wait() на этом же объекте
getClass() Возвращает описание класса объекта
58
Реализация принципа ООП: наследование

1) Метод toString
Определение:
public String toString()
Возвращает строковое представление объекта.

Результат должен быть кратким, но информативным


представлением объекта;
Рекомендуется, чтобы все подклассы переопределяли этот
метод;
У класса Object этот метод возвращает строку, состоящую
из имени класса, плюс символ "@" и беззнаковое
шестнадцатеричное представление хэш-кода объекта:
getClass().getName() + '@' + Integer.toHexString(hashCode())

59
Реализация принципа ООП: наследование

Пример 12:

package testtest;

class СustomСlass { }

public class Demo6 {


public static void main(String[] arg) {
СustomСlass myClass = new СustomСlass();
System.out.println(myClass);
}
} Console output:
testtest.СustomСlass@15e83f9

60
Реализация принципа ООП: наследование

Пример 13: переопределение метода toString():

package testtest;
class СustomСlass {
@Override
public String toString(){
return "This is CustomClass";
}
}
public class Demo6 {
public static void main(String[] arg) {
СustomСlass myClass = new СustomСlass();
System.out.println(myClass);
}
} Console output:
This is CustomClass
61
Реализация принципа ООП: наследование

2) Метод equals
Определение:
public boolean equals(Object obj)
Реализует отношение эквивалентности на двух
объектах (т.е. на не нулевых ссылках).

У класса Object этот метод возвращает true, если и


только если ссылки х и у относятся к одному и тому
же объекту (х == у).

62
Реализация принципа ООП: наследование

Свойства эквивалентности

рефлексия: для любого ненулевого значения ссылки х,


x.equals(х) должно возвращать true;

симметричность: для любых ненулевых значений ссылок х и


у, x.equals(у) должно возвращать true, если и только если
y.equals(х) возвращает true;

переносимость: для любых ненулевые значений ссылок х, у, и


z если x.equals(у) возвращает true и y.equals(z) возвращает true,
тогда x.equals(z) должно вернуться true;

согласованность: для любых ненулевых значений ссылок х и


у многочисленные вызовы x.equals(у) последовательно
возвращают true или false, если только нет информации об
изменении объектов, используемых в сравнении;
для любого ненулевого значения ссылки х x.equals(null) должно
вернуть false.

63
Реализация принципа ООП: наследование

Пример 14:
class Point {
protected int x;
protected int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null || this.getClass() != obj.getClass())
return false;
Point other = (Point) obj;
if (this.x != other.x)
return false;
return (this.y == other.y);
}
}
64
Реализация принципа ООП: наследование

Продолжение примера 14,

public class Demo7 {


public static void main(String[] arg) {
Point point_1 = new Point(5, -5);
Point point_2 = point_1;
Point point_3 = new Point(5, -5);
Point point_4 = new Point(5, 5);
System.out.println(point_1.equals(point_2));
System.out.println(point_1.equals(point_3));
System.out.println(point_1.equals(point_4));
}
} Console output:
true
true
false
65
Реализация принципа ООП: наследование

3) Метод hashCode
Определение:
public int hashCode()
Возвращает значение хэш-кода объекта.

Хэш-функция - это любая функция, которая может


быть использована для отображения цифровых
данных произвольного размера в цифровые данные
фиксированного размера.

Значения, возвращаемые хэш-функцией, называют:


хэш-значения, хэш-коды, хэш-суммы или просто хэши.

Этот метод поддерживается для работы коллекции,


например HashMap.
66
Реализация принципа ООП: наследование

Соглашения по хэш-коду

Когда метод хэш-кода вызывается на том же объекте несколько раз


во время исполнения Java-приложения, он должен возвращать тоже
число, если только не представлена информация об изменении
объекта;

Если два объекта равны в соответствии с методом equals(Object),


то при вызове метода хэш-кода на каждом из этих двух объектов, он
должен выдавать один и тот же результат;

Если два объекта неравны в соответствии с методом equals(Object),


то рекомендуется производить различные результат.

У класса Object этот метод вычисляет хэш-код


посредством преобразования внутреннего адреса объекта в
целое число.
67
Реализация принципа ООП: наследование

Console output:
1484678
Пример 15: для класса Point: 1484678
22052786
public class Demo8 { 32487478
public static void main(String[] arg) {
Point point_1 = new Point(5, -5);
Point point_2 = point_1;
Point point_3 = new Point(5, -5);
Point point_4 = new Point(5, 5);
System.out.println(point_1.hashCode());
System.out.println(point_2.hashCode());
System.out.println(point_3.hashCode());
System.out.println(point_4.hashCode())
}
}
68
Реализация принципа ООП: наследование

Рекомендации по вычислению хэш-кода

Сохранить некоторое ненулевое значение литерала, допустим,


17, в переменной типа int, называемой result;

Для каждого значимого поля f в вашем объекте (то поле,


которое учитывается в методе сравнения), выполните
следующие действия :
Вычислить хэш-код с типа int для каждого поля:
Если поле является boolean, вычислить (f ? 1 : 0);
Если поле является byte, char, short или int, вычислить
(int)f;
Если поле long, вычислить (int) (f ^ (f >>> 32));
Если поле float, вычислить Float.floatToIntBits(f);
Если поле double, вычислить Double.doubleToLongBits(f), а
затем как для long;
69
Реализация принципа ООП: наследование

Продолжение рекомендаций по вычислению хэш-кода

Если поле является ссылкой на объект и метод equals()


этого класса сравнивает поле рекурсивно, то рекурсивно
вызывайте и метод хэш-код на этом поле. Если значение
поля равно null, то традиционно возвращают нулевое
значение;
Если поле является массивом, то рассматривать его как,
если бы каждый элемент был отдельным полем
(вычислить хэш-код для каждого элемента с
применением этих правил рекурсивно, и объединить эти
значения).

Объедините вычисленные хэш коды на шаге в result


следующим образом:
result = 31 * result + c;
Возвращение результата.
70
Реализация принципа ООП: наследование

Пример 16:

public class Student {


private String name;
private long phone;
private int age;
// ….
@Override
public int hashCode() {
int result = 17;
result = 31 * result + name.hashCode();
result = 31 * result + (int) (phone ^ (phone >>> 32));
result = 31 * result + age;
return result;
}
}

71
Реализация принципа ООП: наследование

Продолжение примера 16,

public class Demo9 {


public static void main(String[] arg) {
Student stud_1 = new Student("Peter", 5558956L, 20);
Student stud_2 = new Student("Ivan", 9876543L, 18);
Student stud_3 = new Student("Dasha", 5558956L, 20);
System.out.println(stud_1.hashCode());
System.out.println(stud_2.hashCode());
System.out.println(stud_3.hashCode());
}
} Console output:
1160475683
-1786389060
-1015000986

72
Реализация принципа ООП: наследование

ИНИЦИАЛИЗАЦИЯ С УЧЕТОМ НАСЛЕДОВАНИЯ

class SuperClass { }

class SubClass extends SuperClass { }

public class Main{


public static void main(String[] arg) {
SubClass c = new SubClass();
}
}

73
Реализация
принципа ООП:
полиморфизм
Реализация принципа ООП: полиморфизм

Полиморфизм является способностью объекта принимать


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

Подклассы класса могут


определить своё
собственные уникальное
поведения и все же
разделять некоторую
функциональность
родительского класса

75
Реализация принципа ООП: полиморфизм

ПОЛИМОРФИЗМ

Специализированный Универсальный

Перегрузка/ Подтипный
Переопределение

Параметрический
Принудительное
приведение
Операторы Ковариантность

Функции Контравариантность
Расширяющее

Сужающее
Обобщение
76
Реализация принципа ООП: полиморфизм

ДОСТОИНСТВА ПОЛИМОРФИЗМА
Повторное использование;
Надежность:
Более модульная структура;
Гибкость в расширении.

ПОЗДНЕЕ СВЯЗЫВАНИЕ
Проявляется в возможности вызова переопределенного
метода подкласса через ссылку на суперкласс
(т.е. определение варианта вызываемого метода происходит во
время выполнения и основывается на типе объекта).

77
Реализация принципа ООП: полиморфизм

Пример 17:

class Cat {
public void move() {
System.out.println("Cat move");
}
}
class BritishCat extends Cat {
@Override
public void move(){
System.out.println("British cat move");
}
}
class PersianCat extends Cat {
@Override
public void move(){
System.out.println("Persian cat move");
}
}
78
Реализация принципа ООП: полиморфизм

Продолжение примера 17,

public class Main {


public static void main(String[] arg) {
Cat[] myCats = { new Cat(), new BritishCat(),
new PersianCat() };
for (Cat cat : myCats) {
cat.move();
}
} Console output:
} Cat move
British cat move
Persian cat move

79
Реализация принципа ООП: полиморфизм

Пример 18: полиморфизм

80
Реализация принципа ООП: полиморфизм

Продолжение примера 18,

81
Реализация принципа ООП: полиморфизм

Продолжение примера 18,

Console output:

82
Реализация принципа ООП: полиморфизм

ВЫВОДЫ:

Суперклассы и подклассы образуют иерархию по степени увеличения


специализации.

Такая иерархия позволяет подклассу определять собственные методы


при сохранении единообразия интерфейса.

Суперкласс может определять общую форму методов, которые будут


использоваться всеми его подклассами.

Тип объектной ссылки определяет разновидность объектов, на


которые через нее можно ссылаться.

Через ссылку на суперкласс можно вызывать только унаследованные


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

83
Реализация принципа ООП: полиморфизм

Преобразования и приведения типов


В Java приведение типов объектов - это когда ссылка на
объект может быть приведена к типу другой ссылки на
объект. Приведение возможно к своему типу класса или к
одному из его подклассов, или суперклассов, или
интерфейсов:
( ReferenceType )RelationalExpression
Например,
Object obj = "abracadabra";
String str = (String)obj;

Если вы пытаетесь выполнить нисходящее


приведение класса, но объект не этого типа, то
происходит ошибка типа ClassCastException
84
Реализация принципа ООП: полиморфизм

Пример 19:

public class Main {


public static void main(String[] arg) {
Cat myCat = new BritishCat(); OK!
BritishCat myCat2 = (BritishCat)myCat;
PersianCat myCat3 = (PersianCat)myCat;
}
} Runtime error
ClassCastException!

Во избежание такой ошибки можно проверить


корректность приведения с помощью
оператора instanceof.
85
Реализация принципа ООП: полиморфизм

ОПЕРАТОР instanceof

Оператора instanceof вырабатывает true, если значение


RelationalExpression не нулевое (null) и может быть
приведено к ReferenceType не выбрасывая
ClassCastException.
В противном случае результат - false.

Например,
if (myCat instanceof PersianCat) {
System.out.println("Persian cat!");
PersianCat myCat3 = (PersianCat) myCat;
} else {
System.out.println("Not Persian cat!");
}
86
Реализация принципа ООП: полиморфизм

FINAL-КЛАССЫ

Если класс объявить как final, то он не может иметь подклассы.


final class Cat { //…}

final class Cat {


//...
}
Это полезно при
class BritishCat extends Cat {
создании
//... неизменяемого
} класса.
Не может быть Например, как класс
суперклассом String.

87
Реализация принципа ООП: полиморфизм

ОСОБЕННОСТИ МОДИФИКАТОРА PROTECTED

Модификатор доступа protected указывает, что элемент


может быть доступен только в его собственном пакете и в
подклассе в другом пакете.

При переопределении
метода можно изменить
модификатор доступа.
Однако, он не должен
стать более
ограничивающим.
Например, public менее
ограничивающий, чем
protected.

88
Реализация принципа ООП: полиморфизм

Пример 20:
package com.nau.basic_transport;
class Vehicle {
protected int maxSpeed = 230;
protected void showSpeed() {
System.out.println(maxSpeed);
}
}

package com.nau.derived_transport;
import com.nau.basic_transport.Vehicle;
class Bicycle extends Vehicle {
public void showSpeed() {
System.out.println(maxSpeed);
}
} Изменение области
видимости
89
Реализация принципа ООП: полиморфизм

Продолжение примера 20,


package com.nau.test_transport;
import com.nau.basic_transport.Vehicle;
import com.nau.derived_transport.Bicycle;
class Demo {
public static void main(String[] args) {
Vehicle vehicle = new Vehicle();
Bicycle bicycle = new Bicycle();
System.out.println(vehicle.maxSpeed); // ошибка
System.out.println(bicycle.maxSpeed); // ошибка
vehicle.showSpeed(); // ошибка
bicycle.showSpeed();
}
}

90
Абстрактные
классы

91
Абстрактные классы

Зачем нужны абстрактные типы данных

Группировка родственных операций и данных


Упрощение за счет построения более высокого уровня
абстракции
Возможность моделировать сущности реального мира
Изоляция сложности. Упрощение за счет сокрытия деталей
реализации
Повышение удобочитаемости и понятности кода
Ограничение влияния изменений
Локальность изменений кода

Следствие: снижение сложности!

92
Абстрактные классы

Абстрактный класс – это класс, который объявлен как


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

Можно сказать, что это класс, который определяет


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

abstract class Vehicle {


protected void move() {
System.out.println("Vehicle move");
}
}
93
Абстрактные классы

Абстрактный метод – это метод, который объявлен без


реализации (без тела, и заканчивается точкой с запятой),
например:
public abstract void move();

Особенности:
Если класс включает абстрактные методы, то он
обязательно должен быть объявлен как абстрактный;
Если абстрактный класс – это суперкласс, то подкласс
обеспечивает реализацию всех абстрактных методов
своего родительского класса;
Если подкласс не обеспечивает реализацию всех
абстрактных методов своего родительского класса, то он
также должен быть объявлен как абстрактный.

94
Абстрактные классы

Пример 21:

abstract class Animal {


public abstract void move();
} Подкласс должен обеспечить
class Reptiles extends Animal { реализацию метода move() или
} быть абстрактным

abstract class Animal {


public abstract void move();
}
abstract class Reptiles extends Animal { // ОК
}
Подкласс
объявлен
абстрактным 95
Абстрактные классы

abstract class Animal {


public abstract void move(); Абстрактный метод
}
abstract class Reptiles extends Animal { Абстрактный класс
}
class Boa extends Reptiles {
@Override
public void move(){
System.out.println("Boa move"); Реализация метода
}
}
public class Main {
Ссылке на абстрактный
public static void main(String[] arg) {
класс можно присваивать
Animal myAnimal = new Boa(); объект подкласса,
myAnimal.move(); реализующего его
} абстрактные методы
}

96
Абстрактные классы

Пример 22: public abstract class GraphicObject {


//абстрактный метод
public abstract void draw();
//движение центра фигуры
public void moveTo(int x, int y) { }
}
class Circle extends GraphicObject {
public void draw(){
//рисуем круг
}
}
class Runner {
public static void main(String[] args){
// можно объявить ссылку
GraphicObject mng;
//mng = new GraphicObject();
//нельзя создать объект!
mng = new Circle();
mng.draw();
}
}
Архитектурный
шаблон MVC

98
Архитектурный шаблон MVC

MVC — это шаблон, который описывает способ построения


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

99
Архитектурный шаблон MVC

Пример 1: Модель

package com.epam.model;

public class CalculateModel {


private int value;

public int getValue() {


return value;
}

public void setValue(int value) {


this.value = value;
}

public void incrementValue() {


++value;
}
}
100
Архитектурный шаблон MVC

Продолжение примера 1: Представление

package com.epam.view;
public class CalculateView {
public static final String INPUT_INT_DATA =
"Enter an integer = ";
public static final String WRONG_INPUT_INT_DATA =
"Wrong input! Repeat please! ";
public static final String OUR_INT = "Increment result = ";
public void printMessage(String message) {
System.out.print(message);
}
public void printMessageAndResult(String message, int value) {
System.out.println(message + value);
}
}
101
Архитектурный шаблон MVC

Продолжение примера 1: Контроллер


package com.epam.controller;
import com.epam.model.CalculateModel;
import com.epam.view.CalculateView;
import com.epam.service.InputUtility;
public class CalculateController {
private CalculateModel model;
private CalculateView view;
public CalculateController(CalculateModel model,
CalculateView view) {
this.model = model; this.view = view;
}
public void calculate() {
model.setValue(InputUtility.inputIntValueWithScanner(view));
model.incrementValue();
view.printMessageAndResult(view.OUR_INT,
model.getValue());
} } 102
Архитектурный шаблон MVC

Продолжение примера 1: Утилитный класс

import com.epam.view.CalculateView;
import java.util.Scanner;
public class InputUtility {
private static Scanner sc = new Scanner(System.in);
public static int inputIntValueWithScanner(
CalculateView view) {
view.printMessage(view.INPUT_INT_DATA);
while( !sc.hasNextInt()) {
view.printMessage(view.WRONG_INPUT_INT_DATA +
view.INPUT_INT_DATA);
sc.next();
}
return sc.nextInt();
}
}
103
Архитектурный шаблон MVC

Продолжение примера 1: Запуск программы

import com.epam.controller.CalculateController;
import com.epam.model.CalculateModel;
import com.epam.view.CalculateView;
public class MVCMain {
public static void main(String[] args) {
CalculateView view = new CalculateView();
CalculateModel model = new CalculateModel();
CalculateController controller =
new CalculateController(model, view);
controller.calculate();
}
}
Вывод в консоли:
Wrong input! Repeat please! Enter an integer = 12.7
Wrong input! Repeat please! Enter an integer = 44
Increment result = 45
104

Вам также может понравиться