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

Урок 1. Знакомство с Java.

Методы «Print» и «PrintIn»

Типы языков программирования

Процедурный Функциональный Объектно-ориентированный

Задачи разбиваются на шаги и Все решение описывается при Решение проблемы производится при помощи
решаются шаг за шагом помощи функций функций и структур данных, описанных в классах.
Из каждого класса можно создать объект, у которого
будет набор свойств и методов

Транслятор

Выполняет перевод или трансляцию


нашего написанного кода в машинный
код – электрические сигналы

Компилятор Интерпретатор

Читает текст на языке программирования от начала до конца, Читает исходную программу по частям, сразу
создавая эквивалентную программу на машинном языке выполняя соответствующие действия

Написанная программа
Начало работы компилятора

Работа интерпретатора и [Если есть необходимость] [Если есть необходимость] [Если есть необходимость]
Написанная программа
выполнение машинного кода Работа интерпретатора и Работа интерпретатора и Работа интерпретатора и
выполнение машинного кода выполнение машинного кода выполнение машинного кода
Конец работы компилятора

Машинный код, который можно запустить/выполнить

Пример в Java
Write once, run anywhere – лозунг Java

Посылаем файл в компилятор javac (java Compilator).


Сохраняем файл с расширением .java JVM (Java Virtual Machine) – выполняет машинный код.
Написанный код На выходе получаем byte code, который находится в файле с расширением .class.
Source file - Human.java Для выполнения кода JVM использует интерпретатор
Human.class

NOTE! Из-за того, что в итоге JVM использует интерпретатор, Java считается скорее интерпретируемым языком.

Java код не зависим от операционной системы.

Из-за того, что на выходе используется байт-код, код не зависит от операционной системы. А вот JVM полностью зависит от операционной системы. То есть
если используешь windows, нужно использовать JVM для windows. И тд. Код при этом остается одинаковым, он не зависим от операционной системы.

Новые методы (функции)


‘Методами в Java называются функции’

System.out.print(“Welcome to the first lesson!”);

Выводит на дисплей (экран) необходимую информацию.


(между скобками) – параметр метода

System.out.println(“Добро пожаловать!”);

Выводит на дисплей (экран) необходимую информацию и


переводит курсор на следующую строку.

(между скобками) – параметр метода

4. Слева список проектов. Расширяем 5. Под Source Packages находится наш пакет. 6. Все изменения (переименовывание.
1. New project 2. Java application. Next. 3. Choose name and where to save. Finish удаление) делаются через refactor
проект, который мы создали Переименовываем его.

7. Расширяем пакет Lesson1


8. Убираем серые буквы – «комментарии». 8. У нас есть Package и Public class (Test1). 9. Между фигурными кавычками method Main пишем 10. Нажимаем shift+f6 – запускаем программу
Под ним наш класс (наше приложение, программа)
Они сейчас не нужны. [class будет описан позже – что и зачем нужен] System.out.print("Welcome to the first lesson!");
Тоже переименуем в Test1
Текст который мы хотим напечатать должен быть между
скобками и двойными кавычками (“”)]
После каждого выражения (statement) нужно ставить
точку с запятой– это значит, что выражение завершено.

В class должен быть method Main.


Он записывается так: public static void main(String[] args) {our code}
Для чего нужен method Main:
Это стартовая точка в выполнении (запуске) программы. То есть если не будет метода Main –
программа не будет выполнима.
В программе выполняется все, что находится между фигурными скобками {} метода Main.
Поэтому все methods (System.out.print и тд) пишем между этими скобками.

11. Чтобы после текста курсор перешел на следующую 12. Под методом println добавляем еще строку с просто
строку – поменяй на System.out.println print. Как видно, можно писать несколько методов и они 13. Нужна пустая строка – используй принтлн и ничего не
13. Для форматирования можно использовать пробелы
срабатывают один за другим. по краям, если нужен пробел или отступ. пиши между кавычками
Урок 2. Примитивные типы данных. Понятия «переменная». Системы счисления.

Метафора контейнера

Для крупы Для масла Для соли Для сыра

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

Типы данных (Data type)


Переменные (Variables)
«Разновидность еды и как ее можно использовать»
«Контейнеры»
Множество допустимых значений этих данных, а Именованная область памяти, адрес которой можно
также совокупность операций над ними использовать для осуществления доступа к данным и
манипуляций над ними в ходе выполнения программы

5 + Составные части переменной

a = 3 - [число]
Сколько памяти (бит) занимает в
памяти компьютера значение ‘a’

0 / Тип Размер Значение Имя

-2 х
Очень связаны

a = 5 [число] Сколько памяти (бит) занимает в


памяти компьютера значение ‘a’
Множество Совокупность
допустимых операций над Значение
Имя переменной Тип переменной Размер переменной
значений ними переменной

Типы данных в Java (Data type)

Ссылочные (reference)
Простые (primitive)
(о них потом)

Численные (Numeric) Символьный (character) Логический (Boolean)

char boolean
Целые (integers) Дробные (floating point)

byte short int long float double

int – дефолтный тип данных для целочисленных


Double считается дефолтным. То есть, если в Java встретится
типов данных в Java. То есть просто напиши «5» -
выражение 3,4 + 2.0, оба будут восприняты как Double
Java воспримет это как int
Пример в NetBeans

1) Создадим пакет «lesson 2». Наводим 3) Создаем новый джава класс под 4) Назовем его PrimitiveDataTypes.
5) Сейчас у нас есть класс PrimitiveDataTypes. В его фигурных
курсор на Source packages. 2) Назовем его «Lesson2». Finish новым пакетом. Правой кнопкой на Finish
скобках нужно создать method main.
New. Java package. пакет Lesson 2 и Java class
Пишем: public static void main(String[] args) {
}
Наши методы пишем между этими фигурными кавычками

Рассматриваем типы целых данных


Теперь рассмотрим тип данных long
2) Пишем между фигурными кавычками: Теперь рассмотрим тип данных short Пишем: long l1 = 1000; все норм
1) Пишем между фигурными кавычками: Теперь рассмотрим тип данных int
byte b1 = 100: Пишем: short s1 = 5; Пишем: longl2 = 10000000000;
byte b1 = 10: Пишем: int i1 = 500;
Выбивает ошибку. Почему? Потому, что диапазон short s2 = -10; Выдает ошибку. Потому что в конце числа типа данных long нужно добавить
int – дефолтный тип данных для
значения байта - -128;127. Смотри таблицу ниже short s3 = 0; букву «L», как подтверждение, что мы используем именно этот тип данных.
целочисленных типов данных в Java
Если не дописать L, компилятор решит, что это int и выбьет ошибку, если
значение больше разрешенного для int. Хоть мы и пишем в начале Long.
NOTE: Автор всегда пишет L в конце long.

Зачем использовать разные типы данных

Разные типы данных занимают разное место. Если значение маленькое, нет смысла использовать long – он занимает много
места. Это как разные передачи в авто, или хранить каждый кусочек сахара в огромной коробке.

Рассматриваем типы дробных данных

Float Double

32 byte 64 byte

Double считается дефолтным. То есть, если в Java встретится выражение 3,4 + 2.0, оба будут восприняты как Double.
Из-за большего размера, Double более точный чем Float (помешается в 2 раза больше символов после запятой)

3.2) Тонкий момент о float


1) Рассмотрим тип данных float 2) Рассмотрим тип данных double 3.1) Тонкий момент о float
Но, теперь напишем f4 = 20.0;
Пишем: float f1 = 3.14; Пишем:double d1 = 5,5D; Пишем float f3 = 20; не выдает ошибки, даже без знака
Выбивается ошибка , потому что воспринимается как дробное и относит к
Выбивает ошибку, потому что чтобы использовать Float нужно дописывать F в конце double d2 = 67,65; F в конце. Потому что 20 – это число и по дефолту оно
типу данных double. Возникает ошибка, что мы не может задать значение
– по умолчанию все дроби считаются double, поэтому Java ругается, почему число Оба подходят – можно не писать D в конце, потому что принадлежит типу данных int. И int находится внутри
типа данных double переменной типа данных float. Для исправления
double под float. Чтобы избежать ошибки нужно уточнять буквой F double и так дефолтный. Лучше просто не писать D float, поэтому нет никакой ошибки.
должны дописать букву F в конце.
Note: Авто всегда пишет F в конце float

Рассматриваем тип данных char

Символ – просто из юникода (один символ всех языков, цифры, знаки препинания тд)

1) Рассмотрим тип данных char


Пишем: char c1 = ‘a’; 3) Третий способ –
2) Второй способ –
char c2 = ‘A’ char c6 = ‘\u1234’;
char c5 = 300;
char c3 = ‘7’ Обязательно 4 цифры. Тоже используется порядковый номер
Без кавычек. Означает использование 300 знака в юникоде.
Символ должен быть в одинарных кавычках и один! юникода. Здесь используется 16-ричная система счисления.
Например даже пробел – один символ. два пробела – не подходит

Рассматриваем тип данных boolean

1) Рассмотрим тип данных boolean


Пишем: boolean bool1 = true;
boolean bool2 = false;
Никакие другие значения принять нельзя – только true и false

Как выводить значение на экран

1) Пишем: System.out.println(b1);
В отличии от текста - без двойных кавычек! Если написать в кавычках
System.out.println(“b1”); он напечатает просто b1, а не значение.

Системы счислений

Считать с помощью калькулятора

10-ричная (DEC) 2-ичная (BIN) 8-ричная (OCT) 16-ричная (HEX)

Самая обычная {0-9} {0-1} {0-7} {0-9;-A-F}


Урок 3. Арифметические и логические операторы

Операторы
Операторы – те операции, которые можно выполнить с определенными типами данных. Не все операторы подходят для всех типов данных
(не все операции можно выполнить со всеми типами данных – каждый контейнер предусматривает свои операции )

Типы операторов

Арифметические Присваивания Сравнения Логические


(arithmetic) (assignment) (relational) (logical)

Первый пример

1) Создаем переменную 2) Если следующая переменная тоже равняется 5, 4) Также можно задавать переменные на одной строке.
int a = 5; мы можем так и записать int b = 5; 3) А если переменная b в два раза больше a, мы
через запятую, не указывая тип каждый раз
Или написать int b = a; можем записать intb = a*2;
int x = 1, y =2, z=3;

Арифметические (arithmetic) операторы

+ -
Сложение Вычитание

1) Создаем переменные 3) Еще один способ.


2) Пишем: System.out.println(a+b); 1) Пишем: System.out.println(b-a);
int a = 5; int b = 10 Создаем переменную: int c = a+b; 2) Еще один способ.
Java считает a+b и выводит на экран Java считает b-a и выводит на экран
И пишем: System.out.println(с); Создаем переменную: int c = b-a;
И пишем: System.out.println(с);

* /
Умножение Деление

2) Пишем: System.out.println(a*b); 3) Еще один способ. 1) Создаем переменные 2) Создаем переменную 3) Должно получиться 3.333…. 4) Пишем: System.out.println(b/a).
Java считает a*b и выводит на экран Создаем переменную: int c = a*b; int a = 10; int b = 3 int с = a/b Но в результате выводится только 3. В результате дробь также отсекается, потому
И пишем: System.out.println(с); Потому что int это тип целых данных. что в исходнике переменные int.
В итоге дробь просто отсекается (не округляется)

5) Теперь создадим переменные 6) Создадим переменную 7) В итоге получаем число с дробью. 8) Пишем: System.out.println(b/a).
double a=11; double b=3; double c = a/b; Остаток остается на своем месте. Тоже остаток на месте.
Потому что double работает с числами

%
Процент (остаток от деления?)

1) Вернемся к int. Как узнать 2) Создаем переменные 3) первое выведет целую 4) Результат – 3 поместилось 3 5) То же самое работает с 5) Создаем переменную: 6) Когда находим остаток от меньшего к
остаток если мы делим int. int целаячасть = a/b; часть, второе - остаток раза в 11 и осталось еще 2. дробями. Создаем: double c = a%b; большему. Например, 1.3%5.
Пишем переменные: int остаток = a%b; System.out.println(целаячасть); double a = 5.5; В итоге получаем тот же 2.0 1.3 нельзя разделить на 5 частей, так что
int a=11; int b=3; System.out.println(остаток); double b = 3.5 Выводится остаток .0 потому что double остаток 1.3, деление не произошло.
работает только с дробями И так для всех меньших чисел

++ --
Unary

Оператор ‘+’ обязывает использовать 2 операнды (5+5).


Операторы ‘++’ и ‘– ‘нуждаются только в одной операнде. Например 5++. Поэтому называется Unary.

++ --
К значению переменной добавляем 1. От значения переменной отнимаем 1
а=5 а=5
а++ = 6 а-- = 4

Prefix notation Postfix notation Prefix notation Postfix notation

++a a++ --a a--

Пример

1) Создаем 2) int z = x – ++y 3) int z = x – y++; 4) Если вывести на экран просто ‘y’, если где-то в переменной указано y++, ++y etc, то на экран
int x = 5; Здесь мы сначала добавляем 1 к ‘y ‘. Потому что он стоит перед ‘y’. АЗдесь сначала отнимаем ‘y’ от ‘x’. А потом добавляем к ‘y’ 1,
int y = 3; выйдет не ‘y’ а подсчитанное y++, ++y etc.
потом отнимем получившееся от ‘x’. Получаем 1. но ‘y’ уже отнят. Результат – просто 2. Причина: Java считает строка за строкой все изменения переменной и выводит конечный
результат этих изменений. А не первоначальное значение этой переменной

Как считаются Unary выражения

Пример с ++

Выражение Как срабатывает выражение


x = 3; y = 5
1) z = y-x 5-3 = 2
(Потом увеличиваем x на 1. В данном случае это не влияет на результат так
[Сначала используем первоначальное значение икса
2) z = y-x++ 5–3 как мы уже использовали x. Но Java запоминает это изменение х и в =2
(3), так как ++ в конце, а не в начале]
дальнейшем в коде будет считать x как x++ (3+1) = 4)

(Сначала увеличиваем значение x на 1 так как ++ стоит перед x. Помним, что x был
3) z = y-++x 5- =0
уже увеличен на 1 в предыдущем выражении. То есть х = 4. Еще + 1 = 5)

Пример с --

Выражение Как срабатывает выражение


x = 10; y = 5
1) z = x-y 10-5 = 5

2) z = --х-y [-- стоит перед X поэтому сначала =4


9-5
изменяет его значение x=10-1 = 9]

(Из-за того, что – стоит после переменной мы сначала используем старое значение (помним, что
3) z = x-- -y значение x было уменьшено на 1 в прошлом выражении и теперь равняется 9). 9-5 =4
Но Java запоминает это изменение х и в дальнейшем в коде будет считать x как --x (9-1) = 8)

Алгоритм Пример (a=5)


Если ++/-- стоит после переменной – используй в этом выражении нынешнее значение переменной без изменений a= 6; a = 5; a = 4; а = 5 [но уже нигде не используется]
Если ++/-- стоит до переменной – сначала измени нынешнее значение переменной а потом считай выражение. ++a - --a - a-- + a++ =
И помни, что с каждым появлением ++/-- исходное значение меняется, даже если в выражении переменная не была изменена 6 – 5 – 5 + 4 [последние ++ учитываются уже] = 0
Урок 3. Арифметические и логические операторы page 2

Операторы присваивания
=
Присваивание

3) Пишем 4) Пробуем наоборот. 5) Пример с дробями 5) Но если меняем наоборот:


2) Как программа считает уравнение long a = 100L; int b = a; double d1 = 1.23;
1) Это оператор присваивания, а не равенства! long a = 100L; int b = 10; a= b; float f1 = 3.14F
a=b=c=18. Выдает ошибку – нельзя переменной типа данных int
Означает, что переменной х присваивается Нет никаких проблем, потому, что любой Int double d1 = f1; float f2 = d1;
Оператор присвоения всегда начинает работать справа. присвоить значение переменной типа данных long. Выдает ошибку – та же логика.
значение 5: помещается в Long. Точно так же Short помещается в Никаких проблем.
С становится равна 18, b равняется 18, a становится равна 18. Потому, что не все long поместятся в int (даже если по
int x = 5 Int и Byte помещается в Short. То есть меньшие типы
факту помещается, компилятор не срабатывает) данных могут присваиваться большим.
Точно также не все Int можно вместить в Short, не все Также никаких проблем, если пишем:
Short можно вместить в Byte. Long a = 100L; short s = 50; long d = s

6) Но во float и double влезают все


целые числа, даже long.

+= -= *= /=
Выполни операцию и присвой значение
1) Пишем int a = 3
2) Более удобный способ записывать это выражение: 3) Логично, что a+=1то же
a = a+3 Вместо a = a+3 самое, что a++/++a
Выводим а на экран – получится 6 Пишем a+=3
Почему? Программа пошагово запоминает Значит, сначала прибавь, потом присвой.
значение а. Сначала 3, потом 3+3. И Прибавь к значению а 3 и потом присвой получившееся а.
выводит последнее значение в памяти

>; >=; <; <=; ==; !=


Операторы сравнения
1) Пишем int a = 3; int b = 5; 3) То же самое с >= (больше или 4) Также можно в boolean просто 5) Если = это знак присвоения, то 6) Интересный момент. Еще один
Если мы напишем a>b ответ может быть равно), < (меньше), <= (меньше записывать значения, без знак равенства это ==. Например: способ - в sout можно написать сразу 7) != это оператор неравенства.
только true или false. или равно) переменных
boolean b3 = a==b a==b без кавычек. Результат тот же. с!=b значит c не равен b
То есть мы можем использовать
переменную boolean:
boolean b1 = a>b;
Выводим на экран – получаем false Но, если мы напишем в soat a=b. То мы
в этом выражении присваиваем a
значение b, а не делаем логическое
выражение boolean.

2) Второй способ – просто написать


То есть Java строчка за строчкой решает код
в soat без кавычек a>b
и запоминает все изменения и в конце
выводит результат всех изменений,
последнее значение изменений

&& (and); || (or) !


Логические операторы Знак отрицания

1)Не все операторы работают со всеми переменными. 1) Пример: 2) Пишем: 3) Другой пример: 4) А если мы хотим придать
Например: a = true boolean a = true; int a = 10; переменной с значение
boolean a = true; b = !a (false) boolean b = false; int b = 5; противоположное a>b?
boolean b = false; То есть принимает System.out.println(!a); boolean c = a>b; Пишем выражение в скобках и
С boolean используются только логические операторы and и or. противоположное значение: Ответ – False (не true - false) sout - true ставим ! перед ним.
Мы не можем использовать a+-*/b, или сравнить a и b. !true = false В этом случае: !(a>b)
Также and и or нельзя использовать с цифрами – только с boolean !false = true

2) Сравним and и or.


Оба работают только с boolean (true или false)

and or 5) Пример с short circuit (смотри слева and / or)


And возвращает true только Or возвращает true если как минимум
один критерий удовлетворяется (имеет 2) А что если те же переменные, но мы 3) А что если те же переменные, но в
когда удовлетворяются (имеют 1) Пишем:
значение true) (если выполняется поменяем с на c ++: boolean поменять > на <.
значение true) все критерии int a = 10;
больше – тоже ок) boolean e = a<b && c++==d boolean e = a>b && c++==d
объединенные and. int b = 50;
[a меньше b, Java подсчитывает [a не больше b и это &&, значит уже на этом
int c = 0;
Например переменная «машина»: дальше, видит, что с не равно d, после этапе Java прекращает подсчет и выводит
Например переменная «поступление» int d = 100;
И быстрая; И красивая, И ест мало бензина этого запоминает, что с увеличилось на false. До c++ Java не доходит, поэтому ++ не
ИЛИ Химия; ИЛИ физика boolean e = a<b && c==d
Быстрая – true; 1 (но это уже не влияет на результат) и срабатывает и с остается 0]
Химия – false; [a меньше b, Java подсчитывает
Красивая – true; выводит false]
Физика – true; дальше, видит, что с не равно d и
Ест мало бензина – false; Выводим е = false
Вместе выражение – true потому, что как выводит false]
Вместе выражение – false, потому что Выводим с = 1 (увеличилось на 1, ++
минимум одно условие правдивое Result - False
нужно, чтобы удовлетворялись все сработало, потому что Java просчитала
все уравнение до конца)
То есть: То есть:
b1 (true) && b2 (true) && b3 (true) Result – true b1 (false) && b2 (true) && b3 (false) Result – true
b1 (true) && b2 (true) && b3 (false) Result - false b1 (false) && b2 (true) && b3 (true) Result – true
b1 (false) && b2 (false) && b3 (false) Result - false

4) Поработаем с or. Пишем: 5) Еще пример с or. Меняем > на <.


Примеры в Netbeans int a = 10; boolean e = a<b || ++ c==d
int b = 50; [a меньше b, Java сразу видит, что значение
Boolean x = true;
Boolean x = false; int c = 99; выражения – true и выводит его, игнорируя
Boolean y = false;
Boolean y = false; int d = 100; концовку выражения. То есть до ++c Java не
Boolean Z = true;
Boolean Z = true; boolean e = a>b || ++ c==d доходит, поэтому ++ не срабатывает и с
Boolean result = x&&y&&z
Boolean result = x||y||z [a не больше b, с увеличивается на 1 остается 99]. True и c = 99
Результат предсказуемо false
Результат предсказуемо true (потому что ++ спереди c) и равняется d (100
= 100)]. True и с =100

Важный момент – эти операторы считаются short circuit. То есть когда Java натыкается на
первое значение, после которого результат уже известен – Java сразу дает результат, пропуская
оставшиеся переменные. битвайс & (and) и битвайс | (or)
Например, boolean result = x&&y&&z&& (смотри пример выше слева). Java дойдя до у видит,
что у - false а значит результат уже false, поэтому z пропускается и Java сразу переходит к
следующему выражению. 6) Допустим, мы пишем выражение, в котором обязательно, 7) В чем разница.
8) Такой же пример, но с &.
чтобы второе выражение выполнялось. Для этого есть Используя битвайс операторы & и | Java доходит до конца
boolean e = a>b & c++==d
операторы битвайс & (and) и битвайс | (or). выражения, даже если все понятно раньше. То есть в выражении:
Понятно, что e – false еще после a>b, но Java
В целом логика у них такая же, как у && и || boolean e = a<b |++ c==d
прорабатывает выражение до конца и
& будет true только если все компоненты true. Значение true понятно сразу после a<b, но Java продолжает
запоминает, ч то с увеличилось на 1.
| будет true если хотя бы один компонент будет true подсчитывать, доходит до ++с и запоминает, что c увеличилась на 1.

9) Еще одно отличие – эти and (&) и or (|) могут работать с 10) А в битвайс логика операций &| с цифрами есть. Например: 11) Проведем такой же эксперимент, но с |
числами. a = 10; b = 5; Что означает a&b (10&5)? 101
Обычные && и || не работают с числами. Например Это побитовые операции. Переводим на калькуляторе 10 и 5 в битовое число 0
int a = 10 |
(=2-чное =бинарное). Получается 1010&101 010
int b = 50. _____
В битах сигнал 0 = false, а 1 = true. Запишем их один под другим (добавим к 101 111
1
sout (a&&(||)b) – не имеет смысла, как вывести на экран ноль впереди – это ни на что не влияет, но уравнивает количество знаков). А 1
10 и (или) 50? Здесь нет логики.. дальше решаем уравнение, как если это логическое выражение – Смотрим, что значит 1111 в 10-чной
в операция && значение true будет только, если все значения true. Здесь системе – 15. Проверяем в NetBeans
сравниваем цифру с цифрой под ней. Если бы было 1 и 1 ( true и true) то в
результате тоже было бы 1 (true) . Но здесь во всех 4-х случаях 1-0. Поэтому в
результате 0000.
101
0
&
010
_____
000
1
0

^ (битвайс exclusive or)


1) ^ возвращает true только когда только одна операнда true.
То есть в случае true ^ true ^ true - возвращает false.
В случае false ^ false ^ false – будет true

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

3) Если перенесем ++ в конец: 4) Что касается приоритетов операторов


1)В целом обычные математические правила: 2) Если нужно изменить порядок 5) Таблица приоритета операторов – в какой 6) Еще пример:
int c = (a++ – b)*2; =16 логических (boolean операторов and и or).
Пишем исполнения, можно использовать последовательности они должны выполняться, boolean b1 = false
Сначала используем а в выражении,
Урок 4. Понятия «класс» и «объект». Знакомство со ссылочными типами данных

Метафора чертежа и дома


Метафора банкового счета

Класс (class) Объект (object).


По правилам банка у счета должны быть 3 элемента. Создаем аккаунты по шаблону
Bank account: My account: Your account: His account:
1) Id 1) Id; 1 1) Id: 2 1) Id: 3
Это чертеж. Сам по себе он физически 2) Name 2) Name: Zaur 2) Name: Mike 2) Name: Ivan
А это дом - реальный физический объект созданный по чертежу. В 3) Balance
ничего не представляет. Это модель того, данном случае результат (или экземпляр) чертежа это дом. По 3) Balance: 15$ 3) Balance: 30$ 3) Balance: 10$
что планируем создать. одному чертежу можно построить нужное количество домов. Это еще не аккаунт сам по себе, а только шаблон.
Чертеж, модель – это класс (class) Дом это объект (object).
Объект – это результат (производное, экземпляр) класса. То есть класс по сути перечень правил, атрибутов,
А объект это производное класса – экземпляр класса.
действий, которые могут выполняться

Преимущества использования классов.

1) Одна из самых сложных задач для программиста – дробление кода. То есть если 2) Реюзинг – у дома точно не одна стена. То есть по классу Wall мы будем создавать несколько объектов
код сложный, мы стараемся разбить его на более мелкие части. класса Wall. То же самое для дверей, окон и т.д. То есть создав раз класс, можно использовать его
несколько раз, причем не только в классе House, а и в каком-то другом классе тоже.
Дробление Class House

Class Floor Class Roof

Class Door Class Wall Class Window


В каждой составляющей будет меньше кода, а чем меньше кода, тем легче написать программу. Потом
все классы можно объединить в один Class House. Потом, если нужно будет изменить класс Floor, нам
не нужно будет менять весь большой class House, только его составляющую class Floor.

Structure of Java class


В порядке записи в программе
2) Statement import 3) Class declarations and definitions
1) The package statement
Идет между package и class. Например “import java.util.*” То есть сам наш класс (а иногда и несколько),
Всегда идет на первом месте. Пишем, перед тем, как создать класс.
Не обязателен для компиляции кода (раньше мы его не
Например «package lesson3». Что означает рассмотрим позже.
писали)? Что означает рассмотрим позже. В него входит (нет определенного порядка)

Variables - переменные
Methods (Behavior) Constructors Comments
(еще называются State – состояние класса)
Методы производят действия, которые Конструктор позволяет создавать Отделенные // не
Переменные содержат информацию учитываются Java и
об атрибутах. Это состояние класса. нам необходимы – объект класса. (Позже будем
действия с переменными, или не говорить более подробно) становятся серыми
Например:
int a = 3; double b = 5.5; связанные с переменными. О методах
Переменные содержат значения - в поговорим на следующем уроке.
данном случае числа.

Important about spelling


2) Java восприимчива к регистру – если написать
1) В Java есть зарезервированные системные слова. 3) Переменные int ABC и int abc и int Abc считаются разными.
system.out.println с маленькой – выбьет ошибку,
Например, нельзя назвать переменную «Класс» Но лучше так не делать т.к. можно запутаться.
System dдолжно быть с большой. System.out.println

3) Class declarations and definitions


Правила записи и пользования

1) Название файла и название класса (записывается как “public class 2) В одном package можно создать несколько classes с разными именами. Но 3) Возможет вариант, что в файле не будет public 4) Создадим 2 класса – public и обычный. В каждом создадим метод public static void main.
Test10”) всегда одинаковы, иначе выбьет ошибку. остальные классы записываются как просто “class”. Например: “class Test11”. (а не class – только обычные classes. В этом случае имя Помним, что именно с него начинается запуск программы. Но их тут два, то есть с чего
“public class Test10” который совпадает с названием файла). В package может быть файла должно совпадать с одним из classes. запустится программа здесь? Ответ – Java выведет окно и скажет, что в файле несколько main
только один “public class” – что это такое рассмотрим дальше. классов и попросит выбрать, какой мы считаем main сейчас.

4.1) В итоге выводится только результат кода 5) Оставляем в программе только 6) Раньше мы писали переменные между фигурными скобками 7) Reference переменные. Если примитивных переменных было 8
написанного в фигурных скобках метода main который package lesson4; метода main. Но по факту их можно также писать и вне фигурных
типов, то reference – бесконечное количество. Позже подробнее.
мы выбрали. Второй метод main игнорируется. public class Test10. скобок main, но в фигурных скобках class. При этом написании есть
Одним из самых распространенных типов данных reference – String.
Пробуем запустить – не запускается, потому что какая-то разница, будет объяснено позже. Но логика та же – String – строка. Тип данных чем-то похож на char. Но в char
нет метода main. Классы являются executable переменная и ее значение.
используют 1 символ в одинарных кавычках, а здесь сколько угодно
только когда в них есть метод main.
символов (можно и 1) в двойных кавычках.

Создание класса BankAccount

1) Создаем файл BankAccount 2) Первая переменная в нашем примере с


3) Следующая переменная – имя. Для 4) Последняя переменная – баланс.
банковским аккаунтом – Id. Id это число, поэтому
этого нужна строка (набор символов), Она может быть с дробью, поэтому
создаем переменную int Id; Заметим, что мы тут
создаем переменную String Name; создаем переменную double balance;
не пишем значение переменных.

Создание объекта BankAccount

1) Дальше создаем объект. Для этого пишем ниже 2) BankAccount это название класса. А любой класс в Java это тоже тип данных переменной (референсный). Именно 3) За new всегда следует вызов конструктора. New означает, 3.1) Потом будет объяснено более подробно. Но
метод main. Внутри него пишем такое выражение: поэтому референсных типов данных бесконечное количество – потому что можно создать бесконечное количество что сейчас будет создаваться новый объект. вкратце - конструктор это механизм с помощью
BancAccount bA = new BankAccount(); классов. [то есть с помощью классов мы можем создать собственный кастомизированный тип данных] BankAccount bA = new BankAccount(); которого мы можем создавать объекты. То есть если
Значение объяснит позже. Учитывая, что это тип данных, мы записываем его точно так же как примитивные типы данных. Сравни: нас есть класс BankAccount без объекта он нам не
int a = 5; BankAccount bA = new BankAccount (); нужен (зачем чертеж если не строить дома). То есть
Объект носит имя bA. каждого класса есть конструктор
Этот участок кода создает
BankAccount Ba = new BankAccount(); Адрес объекта в
где-то в памяти объект
памяти присваивается
Значение переменной. В данном случае – класса BankAccount
Тип данных переменной Имя переменной этой переменной bA
вызов конструктора – создание объекта

4) Difference between primitive and reference data types 5) Чтобы соответствовать примеру сверху переименуем 6) Присвоим Id, name и balance объекту
переменные с bA и создадим несколько новых объектов: MyAccount. Как это сделать? Пишем ниже:
BankAccount MyAccount = new BankAccount(); MyAccount.id=1;
Primitive data types Reference data types
BankAccount YourAccount = new BankAccount(); MyAccount.name=“Zaur”;
BankAccount HisAccount = new BankAccount(); MyAccount.balance=12.35;
Int a = 10; BankAccount bA = new BankAccount ();
Поэтому
10 это значение int a. То есть bA содержит в себе не значение, а указатель на область памяти в называется
int a содержит в себе 10. которой расположен объект. В данном примере – F375 ссылочным
(reference)
а bA
5 F375 Таким образом мы создали в памяти 3 объекта
Область памяти в которой (три раза написано new – три объекта)
расположен объект:
1) Id; 1
2) Name: Zaur
3) Balance: 15$

7) MyAccount.Id это переменная. Это не просто переменная Id а 8. Попробуем вывести sout(HisAccount.balance).


9) Как говорили раньше, переменные которые 10) Допишем переменные для других объектов. Эти
переменная id объекта MyAccount. Поэтому когда выводим на Реультат – 0.0, потому что мы еще не задали
записываются внутри class, но не внутри метода переменные уже созданы в памяти, но пока мы их не
экран, пишем в soat (MyAccount.Id). Результат – 1. значение, а 0.0 это дефолтное значение double.
main нельзя вывести напрямую на экран, указав записали, их значение еще не задано. Но для каждого
Дефолтные значения типов данных: эти переменные в sout. Например объекта класса BankAccount будет свой id, name и balance.
Primitive Reference System.out.println(id) Поэтому эти переменные (id, name и balance записанные в
К этим переменным можно обращаться (и classe, но не в методе main) называются instance variable.
выводить на экран) с помощью объектов: (переменные пример/образец)
System.out.println(MyAccount.id)
То же самое можно сделать для переменных
MyAccount.name и MyAccount.balance

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

1) В этом же файле создаем второй class (конечно обычный, а не 2) Переносим все, что было в методе main в 3) Выводим на экран одну из переменных. Ничего не поменялось, все
public class). Назовем class BankAccountTest. предыдущем классе в новый класс. Удаляем класс работает как прежде, Хоть у нас два класса и instance переменные
Внутри фигурных скобок создаем метод main. main и содержимое из предыдущего класса. находятся в другом классе. То есть первый класс работает, как шаблон
банковского счета, а во втором мы проводим операции

Как итог - короткий алгоритм создания объекта

1) У нас есть класс BankAccount и


Урок 5. Создание объектов. Понятие «конструктор». Объявление и вызов методов.

Что такое метод Метод

Метод отображает поведение класса, его состояние, его behavior. В других языках иногда называется функция. Если класс просто Что делает метод
описывает характеристики будущего объекта с помощью переменных (как чертеж), то метод производит какие-то действия (это
функция, это операция) – метод обрабатывает наши переменные и дает какой-то output значение.
x, y, z Result
Функция
Пример: Класс «Машина»
F(x,y,z)
Input (параметры метода) Output

Метод принимает какие-то переменные


(какие-то значения) внутрь себя. X,y,z будем Метод что-то делает с этими значениями На выходе дает нам результат. Result
называть Input метода. Также будем (Что именно – зависит от того, какой это будем называть Output метода
называть «параметрами метода». метод)

Переменными класса машина могут Метод это «как едет машина», «тормозит
быть «цвет», «мотор», «скорость» и тд. машина», «набирает скорость машина».

Структура метода (на примере уже знакомого psvm)

Access modifier Non-access modifier(s) Return type


Parameter (s) Body (Тело метода)
Имя метода (name)
Необязательныe элементы структуры метода (будем рассматривать То, что заключено в круглые скобки. Сами круглые
позже). Пишем их только тогда, когда они нам нужны. Обязательный элемент структуры метода.. Это тип данных, Обязательный элемент. В фигурных скобках идет наш код –
который имеет output нашего метода (int, double etc). Это то, что Тоже обязательный. Сами скобки – обязательный элемент, но внутри фигурных
все, что мы хотим выполнить. Здесь описываем всю
возвращает нам метод, что является его output придумываем имя, если сами скобок можно не писать параметры, если нет
функциональность метода, все что будет происходить внутри
Void – особенный return type, значит ‘пустота’, то есть метод создаем метод. необходимости (просто оставляем () ).
него, для чего конкретно он нам нужен.
ничего не возвращает (есть разница, что считается return, а что
нет, об этом потом)

Пример создания метода в NetBeans


1) Создадим первый метод. Он будет складывать 3 2) Начинаем с первого обязательного элемента – return
3) Далее пишем имя нашего 4) Дальше идет Parametr(s). Открываем круглые скобки (). И записываем наш Input – наши переменные, которые примет метод. В
целочисленных числа, которые мы будем ему преподносить. type. Пишем тип данных, который мы получим в итоге. метода. Можем выбрать данном случае мы запишем 3 параметра – 3 переменные, которые мы будем вставлять в метод, чтобы получить их сумму.
То есть input – 3 числа, функция – сложить вместе 3 числа, Здесь мы складываем целые числа, поэтому return type
любое имя, например summa. Мы решили, что они будут целочисленными, поэтому параметры (переменные) будут у нас типа данных int.
output – результат сложения 3 чисел. - int
Обрати внимание, как записываем параметры: тип данных и имя переменной. Отделяются друг от друга запятой. (int a; int b; int c.)

5) Начинаем создавать тело метода. Открываем 6) Теперь мы должны показать output, так как у этого метода есть output, то есть он на 7) Важно! return type всегда должен совпадать с тем, что нам в
фигурные скобки. В скобах пишем. Int result = a+b+c; 8) Обрати внимание, что Return result находится на последнем
выходе показывает сумму. Мы пишем такое выражение: return result; итоге возвращает метод. Здесь наверху return type – int, и месте. Это всегда должно быть последним выражением
Это означает, что в итоге метод будет возвращать переменную result (то есть переменная result которая указана в выражении return ниже метода (нельзя после него дописывать условия)
переменная result это output нашего метода), которая равна a+b+c. тоже int. Они всегда должны совпадать!

НЕТ ДА

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

Вызов метода (Method call)


Как использовать метод

1) Чтобы использовать метод, нужно его 2) Перед тем, как вызвать метод summa внутри метода Main, нужно 3) Пишем tA.summa. В круглых скобках указываем параметры метода через
2.1) [Рассуждение] Класс это чертеж с некими условиями. То есть в классе Test
вызвать в методе Main. Создадим новый создать объект класса Test 11 (Потому что метод summa принадлежит запятую (введенные параметры иногда называют аргументами. Важно!
11 у нас есть чертеж с условиями метода summa. Когда в классе Test 12 мы
класс test12 и создадим метод Main. классу Test 11). Нужно такое же количество параметров и такого же типа, как указано в
создаем объект класса Test11 (до есть ‘дом’ по чертежу класса Test11) в
Пишем Test11 tA = new Test11(); [напомним, tA – референсная методе – в этом примере три параметра типа int)
памяти автоматически создается участок памяти с этим объектом. Создаются
переменная, ссылающаяся на участок памяти с объектом Test11 t] tA.summa(1, 2, 3);
ли автоматически какие-то параметры или даже решение, но с дефолтным
значением? 0+0+0 = 0? Как это было с классом Student? Что создается
автоматически здесь?. Ответ: Можно воспринимать summa чем-то типа
одной инстанс переменной. Когда мы создали класс tA.summa создался в
памяти участок памяти с методом summa для объекта tA (возможно с
дефолтными значениями). Чтобы придать значения, как и с инстанс
переменными, пишем tA.summa (придаем значения)

4) Запускаем программу. Ничего не выходит на 4.1) [Рассуждение] То есть выражение tA.summa(1, 2, 3); только выполняет метод с заданными значениями, не выводя значение на экран. То есть tA.summa(1, 5) Что является output метода summa? Тип данных int.
экран. Потому что метод обработался, получил 2, 3) это не переменная, как может показаться, а как бы цельная формула, то есть скорее сродни “a+b+c”. Поэтому нужно создать еще переменную int и ей
результат, но мы нигде не писали, что сумма Как доказательство, если вписать tA.summa в soat, Java выбьет ошибку – то есть это не переменная. Чтобы вывести сумму нужно либо вписать все выражение в присвоить значение tA.summa(1, 2, 3);
должна быть выведена на экран. soat(tA.summa(1, 2, 3). Либо создать переменную int SummaTrehChisel = tA.summa(1, 2, 3) И вывести на экран эту переменную soat (SummaTrhChisel).
Точно так же было с формулами. Если пишешь просто a+b+c; Java не выведет ничего на экран. Чтобы вывести на экран нужно создать переменную int A1 = a+b+c
и выводить на экран переменную soat (A1). Либо вписывать в soat всю формулу soat (a+b+c). Ответ: просто tA. summa не выводится на экран, потому, что у нас
нет переменной tA.summa – только tA.summa (с введенными аргументами по параметрам метода). Если просто ввести tA.summa Java просто не найдет такую
переменную – у нас нет метода summa без параметров. То есть tA.summa(1, 2, 3) это все же переменная (все же не думаю, это скорее как формула которая
работает с переменными), но только с введенными параметрами, чтобы соблюсти условия. Точно так же, как и MeAccount.Balance с предыдущей страницы –
переменная. Только tA.summa(1, 2, 3) не надо присваивать значения с помощью “=”, мы их присваиваем, вписывая значения в параметры. В этом смысле
tA.summa(1, 2, 3) чем-то напоминает формулу – мы можем создать переменную int и присвоить ей tA.summa(1, 2, 3) . Также в объекте мы можем создать
много таких переменных int с разными параметрами tA.summa (параметры). А с инстанс переменными можно задать только одно значение переменной
MeAccount.Balance в одном объекте. То есть это что-то среднее между инстанс переменной и своего рода формулой (инстанс формула, скажем)

6) То есть метод выполняется и его значение присваивается int 7) То есть: Алгоритм вызова метода:
SummatrehChisel. Выводим на экран soat (SummatrehChisel) и 8) Вывести на экран можно не создавая отдельную
1) Создать объект в новом классе;
получаем правильный результат. переменную, а просто вписав tA.summa(1, 2, 3) в Soat.
2) Написать:

1) Создать переменную того же return type как и в 2) Переменной назначаем output нашего метода.
методе (Название переменной любое) a) Пишем имя метода (summa)
b) в круглых скобках пишем параметры через запятую (важно! нужно такое
же количество параметров, как указано в методе – в этом примере 3)

Как срабатывает метод - алгоритм

1) Java видит, что метод summa принадлежит объекту tA. 2) Объект tA – какого типа данных? Test 11 3) Поднимаемся к классу Test 11. Java компилятор находит нужный 4) После этого Java обращается к телу метода и 5) Спускаемся назад. После получения результата
Значит мы должны искать метод Summa в классе Test 11 метод по имени (Summa) и по параметрам (3 переменных Int и там и видит int result = (a+b+c). Java заменяет выражение tA.summa(1, 2, 3); заменяется ответом и
там значит правильный метод – поэтому надо писать правильное параметры на аргументы и выдает результат. soat выводит его на экран
количество и тип переменных)

6) Еще один важный момент. Это не переменная, как в прошлом уроке. Это скорее как формула. То есть
она не обязательно должна быть одна. После того, как создал объект, можно создать много tA.summa(a, b,
c) с разными числами. Не создавая каждый раз новый объект - tA, tB etc. Думай об этом как об обычной
формуле, типа a+b+c. У нас есть оператор + и мы можем его использовать сколько захотим, а не один раз.
А метод, это как созданный самостоятельно под свои нужды оператор.

Еще один пример

2) И создадим в этом же классе 3 метода 3) Второй метод такой же, но с отрицательным значением.
1) Создадим класс Car. Добавим instance переменные:
1-й метод. Увеличивает скорость авто на определенное количество и int tormoz(int acceleration){ 4) Третий метод будет выдавать информацию о том, какая у нас машина (какой цвет, какой
String color;
показывает ее на экране. Пишем по стандартному алгоритму: speed-=acceleration; мотор, с какой скоростью сейчас едет).
String engine;
int gaz(int acceleration){ Return speed;} В данном случае нам не нужно, чтобы метод имел output.Если не нужен output используем
int speed;
speed+= acceleration; return type void (void – «пустота»). То есть наш метод ничего не возвращает. В параметрах (в
return speed; } фигурных скобах () ) мы ничего не указываем, потому, что нам ничего не нужно знать – мы
То есть показатель speed из instance переменных с помощью этого просто выводим на экран информацию о цвете, моторе и скорости:
метода увеличивается на значение acceleration и принимает значение void ShowInfo (){
получившейся суммы [+= это складываем и присваиваем]. Sout (“цвет - ” + color + “. мотор - ” + engine + “. скорость - ” + speed) }
То есть если speed 10, а acceleration 5, то в итоге speed становится 15.

Запомнить! Вывод на экран ничего не возвращает, а просто


печатает. Поэтому вывод на экран это не output.
Output это когда мы имеем что-то на руках, после того, как наш
метод завершает обработку. Учитывая, что при void ничего не
возвращается, в случае void мы не пишем строчку return. В случае void этот стейтмент return не пишем

5) Теперь вызываем эти методы. 6) Придадим значения нашим 7) Мы хотим вывести на экран инфо о машине. 8) Теперь мы хотим прибавить скорость на 20. Пишем ниже:
Создаем новый класс CarTest. 9) А теперь резко тормозим на 80. Пишем ниже:
instance variables. Используем объект С1 и метод Show.Info: У метода С1.gaz(20);
Создаем метод Main. В методе Main C1.tormoz(80);
C1.color = “white”; нет параметров, оставляем круглые скобки И после этого метода копируем и вставляем метод ShowInfo:
создаем объект класса Car. и снова выводим на экран:
C1.engine = “V6” пустыми. C1.ShowInfo();
Car C1 = new Car (); C1.ShowInfo();
C1.speed = 60; C1.ShowInfo(); Здесь как в обычных операциях Java делает все пошагово - выводит на
Выполняем и получаем правильный результат. экран, добавляет 20, выводит на экран новое значение.
Урок 5. Создание объектов. Понятие «конструктор». Объявление и вызов методов.
Page 2
Конструктор (Constructor)

Основная цель конструктора – создание объекта

Тип данных
Car - название класса, объект которого мы создаем. Производное название переменной типа Здесь происходит создание нового объекта. Типа, «новый» Это параметр. Если нет необходимости – оставляем
Помним, что любой класс в Java это тип данных. данных Car. Этой переменной объект класса Car. Важно! Название конструктора (Car) пустым. Когда использовать – читай ниже
присваивается значение участка в памяти, всегда совпадает с именем класса (Car)
где будет храниться наш объект.

Этой переменной Car C1 присваивается значение участка


Здесь создается участок памяти с информацией об объекте
памяти с объектом – ссылка на участок памяти с объектом в
по всем его параметрам: color – null, engine - null
16-чной системе исчисления

Типы конструкторов

На самом деле нужно создавать конструктор и в изначальном классе, по которому будет создаваться объект (Car) – он как бы связывается с конструктором new [название класса] ();
в другом классе, в котором мы хотим создать объект (CarTest) и передает ему информацию. Но раньше мы его не писали – мы писали только инстанс переменные. Почему?

Потому что Java всегда автоматически создает дефолтный конструктор в классе, не выводя его на экран. Но
также можно создать вручную user-defined конструктор. В чем их разница – смотри ниже.

Default User defined


Создается автоматически, если пользователь не создаст конструктор в классе самостоятельно. Если мы создаем конструктор сами, Java не будет создавать дефолтный конструктор.
Записывается так:
Сar () {} • Создается нами
Видим, что внутри круглых скобок нет никаких параметров, и внутри фигурных (внутри тела) у него • Может быть с параметрами, или без
пусто. Напишем мы его, или нет, без разницы – Java создаст его автоматически. • Тело может быть пустым, или нет
По факту, если вручную написать дефолтный конструктор Сar () {} он
• Создается компилятором
считается все равно user defined, потому, что мы его создали сами.
• Всегда без параметров
• Тело всегда пустое

User defined конструктор

1) Рассмотрим пример, когда нужен


2) Создаем user-defined конструктор. Допустим, 4) Теперь мы хотим, чтобы в момент создания объекта мы могли сразу определить цвет и
user defined конструктор. Удалим 3) Выводим на экран 5) После того, как мы создали user defined
мы хотим при создании объекта Car иметь мотор машины. То есть пишешь конструктор и сразу в параметрах указываешь значения.
значения у инстанс переменных. System.out.println(car1.engine); Получаем конструктор, в классе CarTest конструктор
возможность сказать, какого цвета и с каким а) Для этого в параметрах конструктора класса Car пишем то, какие данные мы будем
дефолтный null, потому что наши инстанс выдает ошибку. Потому, что в классе Car
мотором мы хотим машину. вписывать, создавая объект в класса TestCar (логично – тоже две String переменные).
переменные без значений и в методе main уже нет конструктора без параметров.
Создаем класс CarTest. В классе CarTest создаем b) А в теле пишем, что именно мы хотим сделать с этими переменными – присвоить инстанс
мы не задали значения. Нужно вписать параметры.
объект класса Car: переменным конструктора Car значения, которые мы будем вписывать, создавая объект в
Car car1 = new Car (); CarTest. (Понятно, что типы данных должны совпадать)
Car(String cvet, String motor) {
color = cvet;
engine = motor; }

6) Вписываем значения: yellow и V6 7) Выводим на экран Car1.color и Car1.engine. Все 8) Еще один момент. В user-defined конструкторе не обязательно писать и 9) Запускаем программу и на экран выводится “Obect 10) Еще пример. В тело можно вписать значения инстанс перем
работает правильно. параметры и тело. Параметры могут быть пустые, а в тело можно писать is created”. Как работает программа. При запуске Java Вместо того, чтобы вписывать их в инстанс переменные. Напр
любые условия. Например soat с определенным текстом. Уберем также в видит объект Car1, переходит в класс Car и смотрит,
классе CarTest параметры. что есть в теле, что нужно сделать – вывести на экран Car(){
“object is created”. color = “blue”
engine = “V12”}
String color;
String engine;

11) Выведем в классе CarTest sout (car1.color) и 12) Создадим новый объект в классе CarTest: 13) Естественно в методе main можно поменять 14) Теперь создадим конструктор, который будет использовать два Создадим 2 объекта в классе CarTest.
(car1.engine). Выводит правильные значения. Car car2 = new Car (); значение : параметра (color, engine), будет придавать им при создании объекта Car car1 = new Car (“black”, ) Запускаем
Sout(car2.color) Car2.color = “red”; определенные значения и выводить эту инфу на экран. программу – все работает
Sout(car2.engine) Car2.engine = “V6”; Пишем в классе Car
Видим. что у второго объекта такие же результаты. В таком случае переменные получат последнее Car (String cvet, String motor){
назначенное значение (по сути, как с дефолтными color = cvet;
или измененными значениями инстанс переменных, engine = motor;
просто другой способ их поменять) Soat (“Цвет машины” + color + “ Мотор машины” + engine)

Чем отличается метод от конструктора

Можно заметить, что если создать user defined конструктор, он очень напоминает методы. Даже функция такая же, можно
вписать все условия в конструктор (как и в метод) и в объекте просто вписывать значения

Method
Constructor
• Всегда имеет return type [кроме Void] • Никогда не имеет return type
• Можно придумать бесчисленное • Имя конструктора должно совпадать с
разнообразие имен именем класса

Как превратить конструктор в метод - пример

1) Тот же класс файл. Конструктор имеет 2 параметра. Если просто дописать спереди Void -
конструктор превратится в метод (который ничего не возвращает, просто выводит на экран)

Void Car (String cvet, String motor){


color = cvet; 2) Также в классе CarTest нужно удалить
engine = motor; параметры конструктора new car1 и new
Soat(color + engine);} car2 – так как конструктор с
То есть как конструктор он перестает существовать – это уже метод. Но для работы объекта в параметрами уже не существует.
другом классе CarTest нам нужен здесь конструктор – как только этот конструктор перестал быть
конструктором, Java создала тут дефолтный конструктор.

Еще пример -
Здесь мы самостоятельно создаем два класса Car3 и BancAccount (по сути две кастомные референсные переменные под наши потребности) с конструкторами. В паблик методе создаем 3 инстанс переменные (1 стринг и две инстанс
переменные референсных переменных Car3 и BancAccount, которые мы только что создали). И метод в котором выводятся на экран все эти переменные. В отдельном тестовом классе создаем тестовый объект Human, задаем все значения его
инстанс переменным (стринг и две созданные нами референсые переменные – интересно что вручную пришлось скобки параметров писать). И вызываем метод.

3) Создадим ниже класс с конструктором


1) Новый файл. Создадим новый класс сразу: 2) Впишем этому классу конструктор: 4) Вернемся к public class Human. 5) Теперь создадим метод в классе Human,
class BankAccount {
class Car3{ Car3 (String c, String e){ Запишем инстанс переменные, который будет выводить информацию об имени
String color; color = c; характеризирующие этого человека. человека, моторе его машины, и о его балансе.
BankAccount(int id2, double balance2){
String engine;} engine = e;} String name; Мы только выводим инфу, поэтому используем
id = id2;
Car3 car; void (нет никакого return).
balance = balance2; }
BankAccount bA; void info (){
sout (“Имя: ” + name + “цвет машины: ” + car.color
int id;
+ “баланс банковского счета:” + bA.balance)
double balance;}
}

6) У нас нет метода main поэтому программа еще не запустится. Создаем отдельный класс 7) Выводим на экран – все сработало 8) Весь код для наглядности
class HumanTest {
psvm {
Human H = new Human (); {создали объект}
[далее придаем значения трем переменным объекта]
H.name = "David";
H.car = new Car3 (“red”, “V6”);
[так как это объект, мы создаем новый объект здесь]
H.bA = new BankAccount (18, 200.5);
[то же самое - так как это объект, мы создаем новый объект здесь]
h.info();
[Выводим на экран]
}}
Урок 6. Перезагрузка методов и конструкторов (overloading). Ключевое слово this.

Method Overloading

1) В одном классе вписываем сразу 2) Но эти методы в принципе делают одно и то Теперь мы знаем, что метод show выводит на экран, а что
много void методов, которые же – выводят на экран. особенно если их много. 3) Если создать метод с таким же параметром
именно он выведет зависит от того, что мы напишем в
только выводят на экран Чтобы избежать нужен метод overloading. void show(int a) и void show(int i1), Java выбьет
параметре. Создадим новый класс для проверки, все ли
переменную из параметра. Этот метод позволяет назвать все эти методы работает. Работает. Потому что Java ищет нужный метод по ошибку, потому что не может их различить –
одним именем (Например show) одинаковое название и тип данных переменной.
названию И по параметру – указав нужный параметр Java
понимает, какой метод выбрать.

Перезагруженные методы - имеют одинаковые имена и разный список параметров [по ходу под методами имеют
в виду и конструкторы – потом в были примеры в том числе и в конструкторах с теми же правилами].
Разный список параметров

Разный по типам данных Разный по количеству


void method (int a, String b) {} void method (int a, int b) {} Разный по порядку
void method (double a, boolean b) {} void method (int a, int b, int c) {} void method (int a, String b) {}
void method (String a, int b) {}

Rules of Overloading
Метод является overloaded только когда у них одинаковое имя и разный список
параметров. Ничего больше на них не влияет (ни return type, ни access modifier)

Return type может быть одинаковый и различный. Access modifier может быть одинаковый и различный.
void method (int a, String b) {} Методы, отличающиеся только return type, или access
public void method (int a, int b) {} modifier не считаются overloaded (Compile ERROR)
void method (double a, boolean b) {} private void method (int a, int b, int c) {}
int method (long a) {return 5;} public void method (int a, String b) {}
public int method (long a) {return 5;} private void method (int a, String b) {}
Про access modifiers поговорим позже. Они public String method (int a, String b) {return “a”;}
У первых двух примеров одинаковый
отвечают за видимость. Одинаковые access Выбивает ошибку, потому что с одинаковым именем и
return type, у последнего разный.
modifiers во всех предыдущих примерах, вот параметрами Java не понятно, какой из них выбрать.
пример разных.

Виды ошибок в Java

Runtime ошибки
Ошибка компилятора

Когда вводишь в int переменную Например деление на ноль. Компилятору норм,


string значение, например. синтаксически все ок, число делим на число, но
Ошибки в синстаксе и семантике. после запуска программы выбьешь ошибку..

Пример 2 (с Constructor overloaded)

1) Создаем конструктор, чтобы при создании


2) А что если у нас новый рабочий и у него еще нет 3) Создадим еще третий конструкт со всеми значениями
объекта можно было сразу вписать все инстанс
значения “Id”. В общем первый конструкт уже не 4) вызовем все три конструктора
переменные как атрибуты конструктора объекта
подойдет. Но можно создать overloaded конструкт только
с теми переменными, которые нужны для новых рабочих,
а от того, какие параметры мы используем, Java сама
поймет, какой из конструкторов мы имеем в виду.

Constructor overloaded (вся та же логика)


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

Разный список параметров


Такая же логика как и с method overloaded, см выше

Rules of Overloading

Такая же логика с method overloaded, см выше.


Конструкторы отличны только по Access
Тоже могут быть разные Access modifier. В отличии от методов ничего не говорим о return
modifier не считаются overloaded
type потому что их нет у конструкторов.

В примере Employee выше один и тот же код переписывается несколько раз, что
занимает место. Есть способ использовать код из одного конструктора в другом.
This

1) Это исходный код класса Employee. 2) По факту эти конструкторы частично повторяют друг 3) Как мы видим, выдает ошибку. Потому что есть 4) Еще правило – this statement должен быть 5) В итоге можно использовать несколько this в одном классе.
Тут много повторений. друга и например в первый конструкт можно вписать правило – конструктор не может вызывать внутри себя первым в конструкторе. Поставишь не на первом, По той же логике как и использование методов внутри
второй (вызывать второй конструкт в первом). свой оверлоадед конструктор по имени класса. Для выбьет ошибку. методов – стэк и Last in, First out. Значение как бы прыгает из
Второй конструктор задает string и int. Первый задает этого есть слово this. Теперь работает. одного class в другой class.
string, int и еще один int. Тогда задачу эти переменных
в теле конструктора 1 можно заменить конструктором
2, вписав значения в параметры как на картинке?

То есть с помощью this мы вписали второй конструктор в первый (а


значит если удалить второй конструктор то выбьет ошибку -
проверено). Когда мы пишем this мы говорим джава искать еще
один конструктор с подходящими параметрами и вставить в него
указанные в параметрах значения (в данном случае surname2, age2
в конструктор 3 с параметрами String surname3, int id3)

2й способ – более простой

1) Сначала пишем самый большой конструктор, 2) А потом в первом конструкторе используем


который включает в себя наибольшее количество this и вписываем все переменные которые
меньших конструкторов. нужны, а вместо тех, что не нужны просто
вписываем дефолтные значения.
Урок 7. Понятие “package”. Модификаторы видимости (access modifiers)

Package

В пакете (package) хранятся классы (classes)

Также в пакете может быть другой подпакет, потом еще подпакет, а уже потом – класс.
Например: package SRC – “под”package Homework – “под” package Lesson6 – class sum, class Student

Основные цели пакета

Защита доступа (access protection) Управление набором возможных имен (Namespace management) Хранение связанных классов в одном месте (keeping related classes in one place)

Об этом позже, но вкратце – возможность сделать так, чтобы элементы Имена переменных могут быть одинаковыми в разных пакетах, но В одном пакете мы обычно держим связанные по смыслу классы (в пакете
класса В пакета 1 не были видны в классе С пакета 3 – класс C не может внутри одного пакета переменные должны быть разные. Если есть дом – все о доме и тд). Поэтому statement package всегда на первом месте в
использовать элементы класса B. Но мог использовать элементы класса А переменная В в двух пакетах сразу, мы можем указать правильный, коде – чтобы понимать о чем речь. + package statement всегда один.
пакета 1 (то есть отдельным классам можно настроить разный доступ) уточнив переменную В какого пакета мы имеем в виду.

Пример. Создадим в одном пакете два разных класса (отдельными А если у нас есть класс B, который находится подпапке P2, папки P1. и класс A, который
А если попытаемся создать объект класса Employee из другого пакета то
страницами). В классе А создадим объект класса В. Видим, что все находится просто в папке P1. Чтобы обратиться к классу B из классаA, нужно указывать
выбьет ошибку. Потому что другой пакет. Чтобы вызвать класс из другого
работает, для класса A доступен класс B. (хоть они на разных весь адрес для класса А, указав обе папки в котором он находится – P1.P2.B. Потому что
пакета нужно указывать полное имя, вместе с пакетом (плюс у класса
страницах – они в одном пакете). А если попытаемся создать объект адрес у класса A отличается – P1.A. Мне кажется, не нужно указывать полный адрес
Employee должен быть public дописано перед названием – об этом потом)
класса Employee из другого пакета то выбьет ошибку. только если папки не отличаются.

Контроллер доступа (Access modifier)

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

У каких элементов какие модифаеры

+ У классов есть еще какие-то внутренние классы (мы их в этом курсе не рассматриваем – все
классы, которые мы пишем внешние) у которых могут быть другие модифаеры)

Типы access modifier

Public

Видно всем из всех классов и из всех пакетов

1) Видно всем. Этот класс (или просто какой-то элемент)


2) Допишем инстанс переменной, методу и 3) Создадим psvm ниже. Создаем конструкт. 4) В другом классе другого пакета все тоже
можно использовать в других классах и даже пакетах. 4) В другом классе этого же
конструкты public. Теперь эти элементы Конструкт видит паблик переменные, работает. Помним, что надо писать полный
пакета все тоже работает
должны быть видны повсюду. методы и конструкты выше. адрес класса из другого пакета.

Private

Private элемент виден только внутри этого класса. Другие классы в


этом пакете и классы в других пакетах не видят эти элементы.

1) просто поменяем в исходном классе public а private 2) На этой же странице но в другом классе компилятор 3) точно так же в классах этого и других пакетов
выдает уже ошибки

(default)

Существует, когда мы его не пишем. При default access modifier элемент виден только внутри этого пакета.

1) Пример с классами. Работаем в lesson6. Оба класса HomeworkTest и HumanTest с default модифаером. Но класс
HomeworkTest доступен (он в этом же пакете), а HumanTest – нет (он в другом пакете)

protected
Protected и deafult модифаеры похожы. То есть протектед виден для всех классов пакета + для все
«производных этого класса» даже если они в других классах. Подробнее позже.

Понятие “наследование”
Java объектно-ориентированный язык. В нем важно понятие наследование. Коротко – есть класс прародитель А и него есть производные классы B, C, D, E и
тд. Также можно создать класс F и при создании указать, что он производное A и он окажется в структуре класса прародителя А.

Короткая схема-итог

Важно!
Ниже double result – не инстанс переменная, а переменная которая принадлежит методу. Эти
переменные называются локальными, у них не может быть access modifiers
Урок 8. Модификаторы “final” и “static”. Понятие “константа”

Non-access modifiers

Final Abstract
Static
будем рассматривать позже

Final

Variable (constant) Class


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

Пример Variable Final Modifier

1. Здесь компилятор выдает ошибку, потому что а с 4) Еще интересный момент. Файнал переменной нельзя задавать
модифаером final, а потом мы его умножаем на 2. Final переменные должны быть инициализированны до их использования
значение в объекте. Логика – Java не важно, что ты задаешь то же
То есть это read only – можем прочитать, но не можем значение. Учитывая, что это файнал переменная, Java считает, что
поменять 2. При определении переменной 3) В каждом конструкторе (если переменная не static) этой переменной нельзя задавать значение вообще.
Если инстанс переменной добавить без Можно не задавать значение файнал инстанс переменной,
заданного значения (то есть значение - но тогда в каждом конструкторе надо будет задать значение,
дефолт) дописать final – выбьет ошибку. иначе выбивает ошибку, что значение не задано.

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


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

Где можно использовать final variable

В инстанс переменных В локальных переменных В параметрах метода (и конструкта?)


(смотри пример выше) То есть внутри метода (и конструкта?). Значит, что мы не можем уже поменять эту b. Нужно сразу задавать значение потому что Означает, что s становится константой и внутри уже нельзя поменять
локальная переменная (так еще и файнал) не имеет дефолтного значения. ее значение. То есть нельзя потом написать s++, например. То есть
ps Но в отличии от интснс, здесь можно написать файнал переменная А, а потом задать А значение с новой строчки мы внутри параметра говорим, что s константа и когда мы придаем
значение s в объекте она становится файнал.

Константы референсных типов данных

final Car car = new Car ():


Здесь переменная car ссылается на участок памяти. Когда мы пишем final, этот участок
памяти становится константой, то есть адрес уже не может быть изменен. То есть
референсная переменная car уже не может ссылаться на какой-то другой объект.

Но мы можем менять «внутренности» объекта. Например задать car.color = red.


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

Здесь один класс Car о машине. Ниже класс Human о человеке. У него есть инстанс переменная string name. Создаем машину-объект по классу-чертежу Car: Если разбить на 3 класса то становится более понятно 2) Все это было бы невозможно, если бы Car был final. То есть нельзя
Car(); (не в методе мейн - по сути это инстанс объект класса human. Никаких проблем, с - это тоже переменная, хоть и референсная. Сразу создается участок обратить переменную «с» на другую машину (поменять адрес, создать
памяти с инстанс переменными c.color и с.engine). новый участок памяти для него). Но мотор поменять можно, это не
меняет адрес переменной «с».
метод мейн. Создаем в нем объект Human h1 (автоматически создается инстанс переменная h1.name и копия всего содержимого класса Car (h1.c.color и
ine)). (То есть получается, что у нас есть класс-чертеж Человек, при создании объекта которого автоматически создаются переменные Имя и референтная
ная Машина, в которой заложены переменные Машина.цвет и Машина.мотор. Другими словами мы встроили класс в класс? Типа того. Становится более
понятно, если разбить это все на три класса – смотри скриншот справа)

еняем машину («работаем с другой машиной»). Создаем объект h1.c = new Car(); [создается новый участок памяти для этого объекта]. Прошло время и для
та мы снова меняем машину – пишем снова h1.c = new Car(); [снова создается новый участок памяти для этого объекта. Переменная h1.c ссылается сразу на
а? Ответ – нет, поводок не может быть привязан к трем собакам, одна референтная переменная не может ссылаться на три объекта, только на один. То есть
а предыдущие объекты удаляются и создается новый объект, новый участок памяти каждый раз мы пишем new Car] Все три машины получают дефолтные
ue и V6 (я так понимаю, что первые две машины уже не связаны с переменной и могут быть удалены garbage collectorom). Но тут можно поменять значение
h1.c.engine=“V8”.

Static

1) Создаем новый класс студент. и конструкт который задает эти 2) Мы хотим, чтобы была переменная, которая увеличивается на один, 3) Создаем 3 студента. Запускаем программу, но в count++ сработала отдельно 4) Если мы хотим инстанс переменную (по другому objec
значение инстанс переменным (кажется вот этот паттерн с задачей когда мы добавляем нового студента. То есть каждый раз, когда мы для каждого конструкта с нуля, поэтому в результате для каждого count превратить в класс переменную (class variable), нужно п
значений инстанс переменным используется именно с конструкторами) используем конструкт переменная должна быть ++. Создаем инстанс поменялся с нуля на единицу. Потому что инстанс переменные создаются для поставить static. Теперь она принадлежит не отдельным о
переменную count и в конструкте добавляем count++. каждого объекта со своими дефолтными значениями – они не меняются, если их всему классу, поэтому изменения этой переменной сохраня
+ выведм на экран, что «количество … студентов создано» значение поменять в другом объекте. статические переменные хранятся не в участке памяти об
участке памяти класса.

Static
может присваиваться

variable method

Самое главное, что статик присваивается всему + у статик такие же дефолтные значение как у
классу в целом, а не каким-то объектам. инстанс

Логический вывод – учитывая, что статик переменная принадлежит


классу, для нее нет необходимости создавать объект.

1) То есть, чтобы вывести на экран sout(name), нужно указывать name 2) А чтобы вывести на экран static count, нужно указывать перед статик 3) Но. Если мы упоминаем статик переменную внутри его класса, то 4) Хотя, нет никакой ошибки, если использовать статик
какого объекта мы имеем в виду – st1.name. переменной название класса – ведь она принадлежит классу в целом указывать класс не нужно – просто пишешь sout (count) (типа и так переменную с каким-то объектом: st1.count etc. Результат будет
(указать sout (Student.count) понятно, какой класс мы имеем в виду – мы у себя в родном классе) тот же. Но это нехороший тон, потому что с помощью объекта мы
вызываем элементы, принадлежащие объекту.
Урок 9. Разновидности переменных и пределы их видимости

1) Создаем такой класс. То есть, перекрасив машину цена возрастает на 1000

Типы переменных (в зависимости от пределов видимости) –


касается и примитывных и референсных

ные Параметра Инстанс переменные Статик


Статические переменные принадлежат всему классу – она общая для все
Например, String color3 из public void changeColor(String color3){}. Область видимости Переменные, которые принадлежат объекту. Каждый объект класса будет иметь эти
метода. Например, int cena = 5000; доступная/заметная. Как и инстанс переменные, можем написать где уго
параметра по сути такая же, как и с локальными, но, учитывая, что мы ее создаем в самом переменные. Инстанс переменные могут быть и в классах и в методах.
дания в методе до конца метода (фигурных Статик более заметный, чем инстанс, потому что для статик даже не
е переменной cena другой переменной вне начале метода, параметр можно использовать на протяжении всего метода.. То есть ее мы
получится – ее там не видно. можем использовать и с самого начала, а локальную – только с места ее создания. Но
о не инстанс и не параметры?] . Они нужны написать String color3 вне метода мы не можем, потому что ее там не видно.
конструкторе/методе (и создать условия
структора эти переменные не видны.
This
В конструкторах. когда мы приравниваем значение параметров инстанс переменным, возникает ситуация, когда мы создаем слишком
много переменных. Но по факту в таком случае параметрам можно давать такое название, как и инстанс переменным (потому что области
ЭУ объекта car нет переменных String color3 и int cena, потому что они находятся видимости этих переменных не совпадают. Параметры видны только в методе.[хотя они пересекаются так как инстанс переменную видно
внутри метода. А вот инстанс переменные могут быть и в классах и в методах. отовсюду]). Но в таком случае перед инстанс переменными в конструкте нужно дописывать “this.”
Потому что this. с переменными и методами означает, что эти переменная или метод принадлежат этому объекту (когда они будут
Локальные переменные (и кажется параметры ) имеют промежуточный характер.. Также не созданы). То есть создаем объект класса Car, this.color это переменная принадлежащая классу (инстанс переменная копия которой
имеют аксесс модифаеров, потому что видны только в рамках метода и так. создана для класса), а обычная car – переменная из параметра.

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


не только в методах, но и в переменных.. Допускается, потому что эти переменные не пересекаются. Точно так же и с методами. Например, вызываем метод в методе. Можно просто написать название метода
ременных в конструкторе Changecolor, а можно написать this.Changecolor (в этом случае нет разницы). Потому что мы имеем в виду объект
(в этом случае метод) этого объекта. This означает принадлежность объекту (когда он будет создан).

тных значений. В примере выше


Так тоже можно, локальные тоже не пересекаются. А вот назвать
ь не определена. Надо сначала
boolean a нельзя, потому что a есть в параметрах.
том использовать.
Логично, что нельзя использовать this для обращения к переменным и методам внутри static метода,
или при присваивании значения static переменной. (потому что this указывает на принадлежность
объекту, а статик принадлежит классу в целом, а не объекту.)

Также нельзя использовать this в статик


То есть здесь нельзя присвоить static int count =
методах. Потому что статик метод
this.a [просто a тоже нельзя писать]. Потому что
принадлежит всему классу, а не
возможно мы используем static int count до
конкретному объекту и тоже может быть
создания хоть одного объекта (static int count
вызван не создавая объект
существует вне зависимости от того, создан ли
объект)

Не является ошибочным обращение с помощью this к static элементам.

[То есть в статик методе/конструкте нельзя обращаться, а в обычном можно? но типа плохой тон]
Здесь, хотя this означает, что мы меняем count конкретного созданного объекта, в этом случае она
статик и поэтому меняется общая для всех переменная count. Но так лучше не писать.

1) создаем метод который просто выводит стринг на экран. 2) В методе мейн создаем объект класса кар и выводим 3 В этом объекте используем метод changeColor и 4) А теперь выводим на экран цвет машины этого Почему? Потому что метод ch
на экран цвет этого объекта (в параметре мы вписали вписываем блэк. Выводится «ред», «блэк». То есть соат объекта. Все равно выводится изначальный ред (ред, переменной String color. А зна
«ред»). Выводится на экран «ред» до метода вывел ред, соат после метода вывел блек блек, ред – 3 соат, один из них в методе) сути здесь совпадения названи
могли бы быть разными? он
переменными параметра и
переменной в параметре м
потому что «color в пар
переменной.» Это значит, что е
по имени (color), то использу
метода (и параметра) А не
(границы) пересекаются. И на
переменной метода. Чтобы ис
нужно в методе дописать this
видим ред. Потому что в данн
вообще не используется.
переменную this.car, парам
Создавая объект мы вписали з
трижды и вывелась (д

Идентификаторы в Java
По сути названия переменных, методов и тд. Правила одинаковы
и распространяются на всех, не важно метод, переменная и т.д.
Правила

2) Должен начинаться с прописной или 3) Символы валют и _ могут быть в любой части 4) нельзя называть идентификаторы зарезервированными
1) Длина не ограничена
заглавной буквы, с символов валют или _ идентификатора, а цифры везде, кроме начала словами. Зарезервированные слова отмечаются синим.

С большой – считается как новое слово, поэтому можно. Но


лучше не надо

Референсные переменные конечно не зарезевированы,


поэтому String можно использовать

У программистов есть условные правила названия индентификаторов. Например:


1) переменные – с маленькой буквы int a;
2) класс – с большой буквы class Car;
3) Метод – какой-то глагол showColor; если два слова, то второе обычно с большой буквы, для читабельности.
Или с андерскором show_color.
4) Константы тоже с большой буквы final int X = 3; несколько буквы – пиши все буквы с большой final int XYZ;

Жизненный цикл объектов

1) Создаем класс. Потом второй класс. Во втором классе пишем три конструктора, 2) конец жизни объекта
чтобы создать объекты. На этапе создания переменной Student st# создается адрес 3) а как происходит отмирание объекта? Есть механизм, который называется
а) если например напишем Student st3 = null; То есть мы вписали дефолтное Garbage collector. Это механизм, который удаляет объекты из памяти нашего
на участок памяти с информацией. Это начало жизни объекта. значение, мы обнули его адрес памяти. Рас адреса нет, значит это просто
У третьего только создаем переменную с именем – то есть у него мы не создаем конструктора. Для экономии памяти.
переменная которая никуда не ссылается.
объект (здесь нет обращения к конструктору). У последнего объекта тоже создается а) Мы можем определить, какие объекты будут пригодны для
Урок 10. Понятия import и import static. использование комментариев

1) Есть два пакета, в каждом по классу. Мы хотим использовать 2) Для этого и придумали стейтмент import. Он позволяет
класс B в классе A – нужно писать полное название p2.B b1 (b1 – импортировать класс в программу и использовать не полное
название переменной). Писать полное название не всегда удобно. название класса, а обычное. Просто пишем import p2.B; Теперь этот
Особенно используя множество классов из множества пакетов. класс можно использовать по короткому имени

3) мы можем указать полное имя класса, чтобы его 4) Или можно использовать
1) Используем для примера класс car из одного из прошлых уроков. Используем класс car в новосозданном классе a. 2) Используем короткую версию обращения = используовтаь. (помним, что метод(конструктор) в import statement
конечно выдает ошибку. другом пакете должен быть public – на первом фоте
здесь он не паблик но автор потом исправил)

5) Используем еще класс из этого пакета. 6) Вот что получилось 7) А еще можно импортировать весь пакет lesson9 (а
8) импорт ен вставляет код из класса, а позволяет
не классы отдельно). Просто import Lesson9.*; .*
пользоваться кодом из другого пакета (то есть на
значит что импортируем все классы пакета
размер класса не имеет влияния)

9) Еще один пример. У нас есть два пакета с классами


10. Импортируем оба пакета. Что получается. Java выдает 11. А что если попытаться импортировать классы с
с одинаковыми названиями Student и car.
ошибку, когда мы используем короткие имена. В этом одинаковым названием из двух пакетов (lesson8.student и
случае даже с импортом нужно писать полное имя. lesson9.student). Компилятор выбьет ошибку.

Еще примеры

1) Работаем в классе А, импортируем класс Student. Мы хотим вывести на 2) попробуем вывести статическую переменную с. Все срабатывает, мы 3) Еще момент, импорт стейтмент работает для всех классов
экран переменную z. Помним, что ее надо сделать паблик. можем вывести статическую переменную в этом объекте, но помним, что на странице. (если дописать еще один класс на странице, в
она не принадлежит объекту. Поэтому используя статическую нем тоже доступны импортированные классы.)
переменную в другом классе лучше использовать имя класса в записи
(Student.c). Без имени класса, просто написав sout (c) вывести не
получится, потому что в этом объекте нет такой переменной

4) Еще момент, любой пакет, который мы создаем импортирует системный пакет со всеми техническими
предустановленными классами. Например, когда мы создаем объект класс, мы используем
импортированный класс Стринг из этого технического пакета. Он как будто всегда написан, но его не
видно. 2я картинка – как бы выглядело полное имя для класса стринг – очень долго.

Импорт с подпакетами

1) Есть два пакета. Один с классом. Другой с классом и с 2) Поэтому чтобы использовать класс с не по
подпакетом с другим классом. Допустим мы импортировали пакет полному имени, нужно написать либо
p2 и попытались использовать класс с. Выбьет ошибку. import p2.p3.*;
То есть этот импорт импортирует только папку p2, но не папку з3 import p2.p3.c;
То есть импортировать класс С.

или

static import – чем отличается от обычного import

1) Чтобы в класса А использовать статическую переменную а по


2) Точно так же импортируются все 3) Если мы хотим импортировать все статические элементы класса, можно 4) Если в классе уже есть статическая переменная с таким же названием как и
короткому имени, нужно импортировтаь статическую переменную класса
статические элементы (методы и тд) вписать статик импорт каждой статической переменной, или записать импортированная статическая переменная, то java будет искать переменную
а. Как это делается – ниже. Если бы был обычный импорт, нужно было ы
еще указывать имя класса для переменной а (смотрите выше) статический импорт название пакета.название класса.*; сначала в своем классе и только потом в импортированном. Приоритет отдается
переменной из своего класса, импортированная переменная игнорируется
(выводится именно 99).
Урок 11 Использование примитивных и ссылочных типов данных при вызове метода

Аргументы методов

Primitive data types

Что можем поставить вместо параметров метода и как это будет отражаться на коде

Дописываем метод, который увеличивает


дробное число в два раза. А увеличился в Создаем еще один класс, в нем метод мейн
и объект класса employee Подставим зарплату в метод uveichitel и
два раза, вернули значение а Запускаем программу – зарплата студента
посмотрим что произойдет – увеличится зп в два
осталась 100.55. А дабл д стала 201.1.
раза или нет. Чтобы сравнить с реальной
зарплатой работника выведем и ее.

Разберем как действовал метод схематично

При создании объекта емп1 создается ссылка на


участок памяти (объект) по имени Иван с зп
100.55

В методе увеличитель параметр увеличивается в два раза. Вместо параметра подставлено значение
праметра сэлери. Важно – мы подставили именно значение. Когда вставляем в параметр метода
переменную примитивного типа данных, то вставляется значение. То есть а принимает значение 100 ,55*2 и
возвращает метод именно значение а. С сэлери ничего не произошло, значение сэлери не меняется. Еще раз
– подставить саму переменную сэлери в параметр метода мы не можем – только ее значение.

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

Создаем еще один метод zp2. В этот раз в параметре не нужен инт, Можем использовать этот метод. В результате сама переменная
потому что у нас уже есть переменная зарплата, мы просто будем зарплата увеличивается в два раза.
увеличивать ее в два раза. Здесь мы работаем с самой зп, не просто
с ее значением как в предыдущем примере.

Reference data types

Изобразим создание студентов Пишем метод, который поменяет Для этого надо написать метод,
Создаем метод мейн и двух студентов
визуально. St1 ссылается на этот ссылки на эти объекты. Чтобы ст1 который в параметре принимает два
объект (квадратик) ссылался на Петра а ст2 на Ивана. объекта класса студент. Меняется То есть сначала мы ссылаем
Поменять местами. местами с помощью третьей Ивана.
переменной Ст3. Ст3 присваиваем Потом Ст1 на Петра.
значение ст1. Ст1 – присваиваем Потом Ст2 на ст3, который ссы
значение Ст2. Ст2 – Ст1. Ивана.
В итоге Ст1 должен ссылаться на Петра
а Ст2 на Ивана.

Попробуем создать метод войд


(ничего не возвращает) своп. Проверяем сработало ли. Выводим на экран имя Рассмотрим графически. Смотрим как работает Рассмотрим по строчке. В методе свап создается
Он еще поменял метод на статик. Использовал
ст1и имя ст2. Но ничего не сработало. Все метод свап. Когда подставляем референс тип переменная с3 которая ссылается на ст1*, на
его в методе мейн.
осталось как было. Почему? данных внутрь параметра, подставляется не сам копию. Пока разницы нет, ст1 и ст1* ссылаются
референс, а его копия. пока на один объект.

То есть когда здесь мы подставили в спвап


референс ст1 и ст2, подставилась не ст1 а его
копия (ст1*) и тперь две переменные ссылаются
на объект (как два поводка на собачке)

Дальше с1 начинает ссылаться на на копию ст2*.


Ст2* ссылается на петр, значит ст1* тоже. ст1*
Дальше ст2* (потому что внутри (метода?) Что происходит, когда заканчивается метод свап?
больше не ссылается на Ивана, потому что работают только копии) ссылается на с3 , которая
переменная может ссылаться только на один Сс3 – локальная переменная, область видимости
ссылается на объект Иван. И больше не до конца параметров метода свап, вне метода с3
объект. Внутри метода свап да, копии поменялись
ссылается на Петр, теряет эту связь. не видна. с1 и с2 – параметры метода, их область
В итоге ст1, с3 и ст2* ссылаются на Иван. А ст1* и местами. Но эти переменные исчезнут после того
видимости ограничена параметрами метода
ст2ссылаются на Петр. как закроются фигурные скобки.
Свап. То есть они все не видны. Остаются только
переменные в методе мейн. Ст1 и ст2. Их копии
ст1* и ст2* и локальная переменная с3
перестают существовать на этой строке. Поэтому вывод: когда в параметр метода
подставляется референсный тип данных, в параметр
подставляются копии этих референсов. В этих случаях
лучше рисовать такой рисунок, чтобы избегать
путаницы.
Остаются только ст1 и ст2 которые как ссылались на
изначальные объекты так и ссылаются. В итоге метод ничего
не сделал. Вот если бы мы внутри метода свап попытались
вывести , все сработает. Просто переменная перестает
существовать после того как закрываются фигурные скобки.

Затем с1.нейм (то есть ст2* в данном


случае) меняем на василий.

Оба и ст2 и ст2* ссылаются на объект Петр,


отим поменять имя одному поэтому с помощью копии ст2* меняем имя
ем метод ченджнейм. (потом Работаем со студентом ст2, который сейчас объекта на Василий.
н дописал статик) Петр. Попробуем поменять на Василий.
Рисуем схему на всякий, чтобы посмотреть,
Используем метод.
как оно сработает. Что происходит кода Метод ченджнейм заканчивается. Из-за того что ст2* (в
подставляем этот референс ст2 в метод данном случае с1) это параметр, по прекращению
ченджнейм? Создается копия ст2* которая метода параметр перестает существовать. Но объект
тоже ссылается на этот объект. уже поменял название. Все сработало, выводится
измененное имя Василий. То есть с помощью
референса мы можем менять элементы объекта (с
помощью копий – потому что когда в параметре
указаны референсные типы данных, используются
вместо прараметров их копии.) Еще раз – с помощью
копий мы можем изменять элементы, но не можем
менять сам объект (я так понял, что поменять ссылку
на объект мы не можем, смотри выше первая попытка,
Урок 12 Конструкции «if» и «if else». Ternary оператор

Flow control

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

Selection Looping

Повторение конкретных действий, о них позже.

If Switch

О нем позже
If

красным то, что обязательно, жирным - необязательно, но


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

Здесь в if условие (обязательно должно быть логическое Здесь условие не соблюдается – на экран
условие), а в фигурных скобках – что сделать, если условие ничего не выводится. Нет – пропускается
соблюдается код написанный в фигурных скобках

Варианты использования If

1) 2)

1) Если true – выполняется что в скобках, Код с else – идет после if. Дополнительное условие. Еще правило –
если false – не выполняется ничего else сам без if не работает, только с if.

1) Важно. Если не используешь фигурные скобки то if и else относятся только к первому 2) Вот здесь оба выражения относятся к else . Писать так
стейтменту после них (типа относится к первой строчке после). то есть в данном случае «привет всегда. (нужно писать код в фигурных кавычках всегда, чтобы
всем» пишется не зависимо от значения а – меньше оно или больше 20. Чтобы избегать не было путаницы, даже если это только одна строчка и она
путаницы – всегда используй круглые кавычки. автоматически относится к if или else. Тем не менее, если
условие после if else стейтментов только в одну строчку автор
дальше в курсе не ставит кавычки. Хотя все же советует
ставить кавычки, чтобы избежать путаницы, всегда)

3) Пример. Можно прямо вписать в if false и 4) Еще пример (не знаю к чему)
тогда всегда будет использоваться else. Это
тоже логическое утверждение

6) Этот пример выдает ошибку. If и else разделяет


5) И еще пример. Так как первая строчка после if или else относится к лишний sout. Нужно или удалить, или взять в кавычки.
if или else, то если нет кавычек после if – этот sout относится к
стейтменту и не напечатается. Есть кавычки после if – это
законченный стейтмент, никак не влияет на sout, sout выводится.

3)
4)

Еще дополнительное условие(я)


Тут есть внутренний if – то есть if внутри if.
Называется nested if (вложенный/встроенный if)

3) Правильный вариант со скобками.


1. проверяем мотор у первой машины
мотор больше чем у второй? да. Поэтому
3) Следующий пример. Условия обычно связаны, но заходим в следующие фигурные скобки для
писать сколько хочешь
это не обязательно. Добавляем переменную булеан.
условий внутреннего if и else.
2) Меняем на 500. Везде false , выполняется else. Здесь выполняется последний элс иф 1) Идея простая – это обычный if else, но формула условия первого if – другой else if.
Если не будет else – только else if – тогда ничего не Сначала рассмотрим этот вариант. Если не расставить скобки часто сложно понять какой else
будет выведено относится к какаому if. Поэтому нужно ставить скобки! Совет – всегда определить самый
внутренний if и else – они между собой пара.

2. количество дверей у первой машины больше чем у


второй? 4 больше 5? нет, поэтому выполняется else.
3. Последний else не выполняется. Учитывая что
первый if - true, мы выполняем то что внутри фигурных
скобок (внутренние if и else)

2) А внешний if пара с внешним. Если много


внутренних if , разобраться вообще бывает сложно.
= == Я так понимаю, что тут скорее о примитивных типахданных

То есть с булеанами – когда мы присваиваем значение, используй =, когда мы задаем условие == (потому что в случае == есть
условие, логическое утверждение с ответом да, или нет. А с просто = мы утверждаем что что-то равняется чему-то)

В булеан всегда используем == (потому что просто = это А здесь уже логическая ошибка – в if присваивается Так можно писать, b придается значение фолс, if – б, значит Здесь ошибка компилятора, в if всегда должно быть
присваивание а не равно). То есть здесь b приравнивается значение b, а не дается условие что это b. Компилятор не false, значит условие не выполняется.. логическое утверждение (булеан) с ответом правда или
false,, а в if сказано условие, что b – true. То есть if – false, ругается, но здесь логическая ошибка. ложь, а не утверждение типа И присваивается 10.
условие в скобках не віполнится.
Я так понимаю, что с референсными типами данных сложнее, там
equals
используется метод equals, о котором позже, и здесь только превью.

Но если в примитивных == норм использовать, то в референсных это не очень правильно.


То есть S1 == S2 – false, а equals– true (потому что содержимое одинаковое)
Потому что референсные переменные ссылаются на адреса объектов в памяти.
Это string. А если ты создаешь свой класс, то нужно самому объяснять джаве, какие
два объекта считаются равными (по цвету, по двигателю и тд)

(о методе equals будет потом, кажется там объяснят)

У этих объектов, если они созданы по отдельности, адреса всегда разные. То есть всегда false, даже
если у объекта те же значения (red и V4). (То есть, если записать c1.color == c2.color то выбьет ошибку,
потому что мы сравниваем не значения цветов? (о методе equals будет потом, кажется там объяснят)
Вот если написать Car c4 = c1; это значит что обе переменные ссылаются на один
объект. Тогда С4 == С1 будет правильным выражением.

Нам нужно, чтобы две машины считались одинаковыми если у них совпадает цвет и мотор. Для этого
используется equals. Он существует по дефолту, даже если его не создать (рассмотрим потом.)

Но в дз уже нужно было использовать метлод иквалс. Короче говоря логика с референсными
Сегодня рассмотрим только в контексте стринг. Равніми считаются те, у которіх количество букв переменными такая. Сравниваем каждую инстанс переменную этого объекта отдельно. Если
одинаково и они совпадают по порядку с собой. это стринг – пишем метод иквалс. Синтаксис: if (st1.name.equals(st2.name)). Выше пример из
домашнего задания. Если инстанс переменная объекта содержит примитивные данные
(например, число), используем обычный ==. Пример: st1.grade == st2.grade && st1.course ==
st2.course

Пример с локальными переменными

1) Пишем метод, который находит наибольшее число из тех, 2) Создаем объект и вызываем метод. 3) Можно добавлять локальные переменные
которые мы вставляем в параметры этого метода.

Здесь а видно только внутри фигурных скобок, в


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

Еще один пример

2) Чтобы избежать этого нужно написать else в котором str принимает любое значение (даже если просто
1) Выбивает ошибку что str может быть не определена.. Какое бы
null, или что либо еще.. Когда есть else, компилятор уверен, что все условия учтены, даже если не сработает if,
значение не прияла а, она будет подходить для какого-то if. И в
есть else, чтобы покрыть все варианты (то есть мы знаем что наш код еще на первом скриншоте был хорошим
каждом if есть свое значение (привет или пока)
и сработает, но тут нам приходиться обхитрить джава с помощью этого else)

Ternary operator

Используется не очень часто, но удобен. Первая – условия, потом


знак вопроса, потом значение если true и значение если false.

То есть как еще один вид записи (кстати удобный – смотри схему
выше, как строить и что значит).
Урок 13 Конструкция «switch»

Позволяет выбирать один из путей по которому пойдет программа. В отличии от if, switch
показывает больше чем два пути по которому может пойти программа.
Синтаксис:

3) В switch пишется в круглых скобках, что будет сравниваться.

Дальше условия для кейсов

Дальше брейк – означает, что мы покидаем стейтмент switch (если не использовать брейк, он будет выполнять все условия, пока не найдет
следующий брейк или не закончится тело свитча). Смотри ниже – убрали все брейки и выполнились все условия (включая брейк)

1) Сначала зададим в стейтменте if, потом в switch. Пишем 2) Теперь пишем то же самое но с switch стейтментом. Дефолт срабатывает, когда не срабатывает ни один кейс. дефолт не обязателен. Если нет дефолта и ни один кейс не сработает – ничего не
программу, которая выводит информацию, как учится студент. С if Выдало ошибку с дабл грейд и он поменял выйдет на экран. Дефолт можно написать где угодно, можно в середине, если пишешь в середине, после него нужно писать брейк. Но дефолт
код работает, но для такой простой логики код слишком большой. переменные на int (потом объяснит) смотрится всегда в последний момент, если кейсы не сработают. Дефолт может быть только один.

Еще пример

1) Рассмотрим дни недели когда и как работает работник. 2) Как работает. Условие понедельник? Он запоминает
(Внимание – он забыл написать брейк после воскресенья, понедельник, проскакивает остальные дни до операции и
исправил потом). Для определенных значений (с пн по пт) выполняет операцию. Условие вторник? проскакивает дни до
код одинаковый. Можно сократить. Убираем брейк и саму выполнения операции. Проскакивает, потому что нет брейка
операцию кроме пятницы (последней в списке с одинаковым
кодом?).

Не обязательно только int – все типы указанные выше. Ни один другой примитивный (лонг,
булеан, дабл и флоат), ни один референcный не подходит.
B должно быть соответствие в кейсах типу данных свита (нельзя чтобы везде был инт а в
одном кейсе стринг. или даже если в свитче байт а в кейсе инт – инт не помещается в байт,
должно быть соответствие)

1) Можно использовать выражение, но чтобы результат был подходящего типа


данных (DenNedeli*3 в итоге получается все равно int, значит подходит.) 2) Плюс вообще требуются константные выражения (то есть уже заданные, которые уже не
3) А выражения типа а=5. а*б и тд – то компилятор не уверен, что эти
поменяются – то есть 3, 3+1, привет – все эти подходят).
значения не поменяются, поэтому выбивает ошибку.

4) Можно исправить если дописать перед этими переменными


файнал (значит они уже не поменяются) 5) Но вот так будет ошибка, она не считает а*б константной
Урок 14 Классический цикл «for». Выражения «break» и «continue»

Циклы в Java (loop)

Допустим нам надо вывести на экран что-то 10 раз. Можно


скопипастить. Но это не практично. Для этого нужны циклы.

Типы циклов

Regular for (или просто for) While Do while foreach

Сегодня только об этом. Удобен когда мы точно знаем


Синтаксис for
сколько раз нужно что-то повторить.

Пример с циклом for

Update
Здесь увеличение int i на Update выполняется после первого
выполнения того что в теле. И выполняется пока condition верен.

Initialization
Здесь Int i = 1. Работает один раз. Мы создали переменную ,
назначили ей 1 и больше не возвращаемся.
Condition (условие)
До каких пор будет выводиться на экран (пока и не будет меньше равен 10). Здесь
Expression идет проверка – int меньше или равно 10? Это условие булеан, должно всегда
Дальше в фигурных скобках тело цикла for (sout отвечать на да, нет. Если да, то все что написано в теле выполняется.
«урок номер 14»). Вывело надпись на экран 10 раз

Еще примеры

2) Здесь с самого начала условие не


1) Логично выводится от 1 до 10 выполнилось и ничего не выводится на экран

Компоненты цикла for

Update
Condition
то это значение только раз 3) i = 5, 5 меньше
йту? - да) 1) Нельзя вписывать несколько условий через запятую (типа меньше 20 и меньше 15) 1) Через запятую можно Update разные переменные. То 2) в Update стейтменте можно даже вызвать другой метод. Увеличь i на 1 – стало
ю надо объявлять до forа 2) Можно использовать булевые операторы внутри Condition стейтмента. то есть несколько есть ниже в Update увеличиваем и i и j ++ метод статик чтобы не создавать объект. 10 – вывел. Но
условий через &&. Оба условия должны выполняться чтобы Condition был true

ько внутри цикла for. закрыты

дного типа через запятую


Еще примеры

Нужно вывести все четные от 1 до 30

Unreachable statement
Пример со statement if
Java не позволяет писать код с unreachable statement

Здесь sout как бы тоже unreachable, до него компилятор не дойдет,


он никогда не напечатается, но компилятор не ругается. if – своего
рода исключение из правил unreachable statement

Sout здесь – unreachable statement, до него Java никогда не Тоже – Java сама обнаружила что statement unreachable
дойдет, так как условие – false. Так же как и и=и+2

Пример с встроенным for в тело if

Если а больше 10 то пусть срабатывает for. Здесь можно убрать скобки и в итоге все сработает все
равно – и первое и второе предложение относится к if (но лучше всегда ставь скобки)
Loop statements

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

1) Мы хотим, чтобы когда i становится 7, 2) Добавляем в тело for a if с break. 1) Хотим выводить от 1 до 100, но не хотим выводить 87. Continue
чтобы луп прекращал свою работу. Когда i равняется 7 – break. значит, что мы доходим до этого interation (единичное выполнение
цикла) и пропускаем его, просто не выполняя. Доходим до 87,
пропускаем и переходим сразу на 88
2) Еще пример. Внутри for можно вписывать много разных условий.
a) 10 не выведется.
b) Дальше оператор который показывал остаток тут i%55==0, то есть
при делении на 55 остаток равен 0. Целый остаток здесь почему-то
54 (по моему логично было бы 56, чтобы не было целого остатка и в
итоге получился ноль – перечитать про остаток) 55 не выведется.
Когда доходим до 55 луп заканчивается. И остановится на 54.
Nested for

Задача, вывести минуту времени 00:00 до 00:59 к 01:00и 1:01


Для этого используем nested for

а) Этот код с использованием так называемых лейблов (я так понимаю, что о лейблах ниже, а этот соут с текстом – еще не лейблы прост
понятнее, где конец где начало лупа. Скорее как введение).
Получилось. Первый for называется outer b) Как работает код. Код узнает, каким будет первое число (час), заходит в условие, печатает «начало аутер лупа» , доходит до лупа с минут
for, второй – inner for. Тут простая логика. условия по минутам, учтывая условие с часом (1:1 до 1:59). двигается дальше, печатает аутер лупа и возвращается к первому

Labels

Пример - хотим сделать так, чтобы был брейк, когда минута доходит до 30

2) Для этого используем лейблы. Пишутся большими буквами. Пишем OUTER перед началом первого
1) Это немного не то. Хотим создать код, чтобы внешний луп прекращал
лупа. А потом пишем INNER перед началом внутреннего лупа.
существование, когда минута доходит до 30. То есть 1-30 и все.
А потом делаем break outer лупа, если хотим, чтобы минута дошла до 30 и на этом все закончилось. Без
уточнения брейк срабатывает внутри лупа, который ты пишешь.

3) Попробуем сделать так, чтобы минута со значением 20 никогда не


выходила. Используем continue. Но конечно это применяется ко Цель labels– управление внешними лупами
всем часам. То есть пропускаются 20 и продолжаются 21. А мы
хотим, чтобы дошло 19 и перескакивало на следующий час. Поэтому
нужно уточнить и дописать OUTER
Урок 15 Циклы «while» и «do while»

While loop

В while лупе мы заранее НЕ знаем количество повторений. Очень похоже на for, только переменные
задаются отдельно, в скобках только условие, а update не в круглых а в фигурных скобках.

Синтаксис while лупа

Condition. Конечно отвечает на true или false. Если true – стейтменты будут обработаны
(важно! пишем условие которое должно быть true. Смотри пример 3)

Пример с казино:
Условие – есть деньги? Есть, выполняем стейтменты , играем в казино, проверяем –
есть деньги? если есть выполняем стейтменты, пока не закончатся деньги.

Пример 1. С выводом на экран чисел от 1 до 10


Пример 2. С казино

1) Вот так выглядит цикл вывода от 1 до 10. Условие – I меньше 10. Стейтмент – 2) Еще важный момент, i запоминает эти изменения.
напечатать и и увеличить i на 1. Цикл прекращается когда условие false. После while loopa значение I будет 11.
Тут все логично

Пример 4 – если есть присвоения (в условии или в стейтменте) и


Пример 3
джава до этой строчки доходит, то присвоение срабатывает

Список цифр пока не наткнусь на число которое нацело делится на 7 и 3


2) Дальше. Если кондишн фолс, то джава даже не заходит в тело
цикла. Но утверждение в кондишне учитывается все равно (да?)

1) Вот здесь напечатается 12. Логика


Условие: 5 меньше 10 – да. + 1
Заходим в тело цикла: +1
Условие: 7 меньше 10 – да. +1
Заходим в тело цикла: +1
Условие: 9 меньше 10 – да. +1 То есть здесь а все же стало 10.
Заходим в тело цикла: +1
Условие: 11 меньше 10 – нет. все равно срабатывает +1, но уже не заходит в тело цикла
Тут b – boolean переменная. Ниже в стейтменте условие, которое задает Типа иногда не логично срабатывает этот а++
когда b true, а когда false (if стейтмент).
+ помним историю с кавычками – если одна строчка после –
можно кавычки не ставить. Но лучше всегда ставить

Do while loop

Отличие что в do while мы сначала делаем, а потом проверяем условие. То есть здесь как минимум 1 раз
тело цикла обрабатывается. А в while если условие не выполняется, то в тело даже не заходят.

Пример 1. Вывести от 1 до 10
Пример 2. С казино

выводится от 1 до 10. Все логично. Выводится 1, увеличивается на 1,


проверяется условие. То есть отличие что в do while мы сначала Все логично
делаем, а потом проверяем условие. То есть здесь как минимум 1
раз тело цикла обрабатывается. А в while если условие не
выполняется, то в тело даже не заходят.
Минимально позволяемая запись.

1) Получается бесконечный луп. Желательно всегда использовать скобки.


2) Тут обязаны использовать фигурные скобки (из-за
того что между do и while больше одной строчки)
Unreachable statements

Infinity loop
Нереалистичные условия

1) В while нельзя писать нереалистичные условия 2) А вот с while Java не ругается, потому что в
любом случае стеймент выполнится 1 раз 1) В while и do while можно сделать такие инфинити лупы

2) Здесь например «пока» никогда не выведется на экран пока,


потому что тут инфинити луп, без конца будет писаться привет

Nested while/ do while


Примеры на выведение часов

1 вариант

Все сработало.
1) outer loop – do while. Здесь мы задаем значение часа. То есть тело лупа будет обрабатываться (пвторяться) до тех
пока час меньше 24х. Именно в конце тела do while час увеличивается на 1. (chass++) Это важно.

2) Для минуты мы используем loop while. Это наш inner loop. Важно! Именно в теле do while, перед тем как задать while, мы создаем
переменную int minuta = 0; Почему не раньше, там же, где мы создавали переменную int chas = 0, а именно здесь? Потому что при
выполнении while и do while переменные запоминают свои значения. То есть int minuta достигла бы 60 и на этом все закончилось бы. А нам
нужно, чтобы с каждой интерацией outer loop do while, int minuta обнулялась и начинала насчитывать минуты заново.

2 вариант
(outer– for, inner - while)

Сработало, еще меньше места. Outer и inner написаны для удобства.


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

Пример continue
Пример с break

Очевидный пример с break. Просто чтобы


показать, что continue и break так же работают.

1) Здесь есть continue outer, он расположен перед minuta++;, значит до строчки chas++; джава не доходит и сразу
переходит в следующий интерейшн outer loopa. Учитывая, что chas++; не сработал, chas все еще 0, по условиям 2) Вот если перенести update statement в начало и изменить
while все что внутри скобок должно повторяться пока chas не дойдет до 24, а chas остался 0. int minuta обнуляется переменную, на -1. То такой ошибки не будет. (Но в этом
до нуля и inner while повторяется с самого начала. И так до бесконечности. chas никак не может дойти до chas++. случае 24 надо поменять на 23 внизу – так как здесь джава
Поэтому в итоге джава выводит на экран от 0:0 до 0:19 снова и снова. сначала выполняет действие, а потом проверяет условие)

2) Вот если перенести update statement в


Важно! переменную, на -1. То такой ошибки н
Всегда обращайте внимание где в цикле do while/ while находится update statement (chass++ и тд). Если он находится в конце do while/while и случае 24 надо поменять на 23 внизу –
используется continue, цикл будет бесконечным (если continue встречается где либо внутри тела do while или while? нет, скорее если continue сначала выполняет действие, а потом п
направлено на этот цикл – прямо, или через лейбл: continue OUTER, а update statement OUTER находится после этого continue). И всегда шаг за
шагом пытайся проанализировать работу циклов, чтобы не попасться в infiniti loop.

Здесь не скомпилируется, потому, что int a видна только в кавычках, то есть while не понятно,
что это за а, она еще не создана для while. Int должен был быть создан раньше.

К домашнему заданию. После conmtinue мы не могли добраться именно к minuta++. Поэтому хватит
Урок 16. String

Запись объектов класса String

String S1 = “Hello”
1) В случае с классом String нам не приходится писать его полное имя, хотя оно в памяти заложено как стандартный класс.
2) Находится этот класс в пакете java.lang. Этот пакет настолько часто используется, что он импортируется сразу, его не нужно импортировать.
3) Обычно пришлось бы импортировать так:
Import java.lang* (чтобы импортировать все классы пакета)
Но не приходится, потому что он импортируется сразу автоматически
Объявление создание объектов Стринг

1) String s1 = new String(“Good day!”); 2) String s2 = “Hello”; 3) sout(“Privet”) ;

Первый вариант. S1 референсная переменная со своим адресом которая Можно и не использовать new и конструктор. Но здесь java не гарантирует что будет создан новый объект. У java есть Если «привет» уже есть в пуле, тоже не будет создаваться новый объект. Но
ссылается на созданный в памяти участок памяти объект. Причем new String string пул где сохраняются выбранные надписи. Если надписи такой же нет - создается новый объект. Если надпись уже если записать через new String, то объект создаться новый
всегда создает новый объект – даже если текст одинаковый есть в пуле, новый объект не создается, переменная будет ссылаться на этот же объект. Важно string пул считается
константным, значения не меняется в нем, об этом позже.

Сравнение объектов класса String

Сравнение 1 Сравнение 2

Здесь надписи одинаковые («Privet»), но они созданы через new String,


Что в этом случае будет выводится на экран? Если в констант пуле уже существует «ок» то в sout будет
поэтому для каждой надписи создается свой объект, со своим адресом.
выводиться “ок” из пула. Если не создан, то будет создан объект в пуле для «ок» из sout . Но в любом случае
В такого рода сравнениях всегда сравнивается адрес объектов. В данном
этот «ок» будет из пула. «Ок» из строчки выше создан через new String а значит, у него в любом случае будет
случае адреса разные. Значит (s1==s2) будет false
другой адрес. Здесь тоже будет false.

String objects counting

Часто на экзамене есть задачки с подсчетом количества объектов.

Ответ - 5,потому что в сравнении “Привет” “пока” “привет” с маленькой буквы – значит другой объект.

Final static с референсными типами данных

Но! Внутренности этого участка памяти менять можно. То


Final static C значит что «C» зафиксирован и может есть модно поменять цвет или тип п=мотора. Final не
ссылаться только на один объект – участок памяти. ограничивает то что происходит внутри объекта

Нельзя Можно

Здесь мы присваиваем «С» какой-то новый Но можно поменять то, что содержит этот объект.
объект. Так делать нельзя, потому что «С»уже Например красный цвет машины на черный.
привязан к объекту, он уже final

Еще пример

Запускаем – цвет машины все равно red. Это пример того что вызван метод на объект класса car. В output тоже объект класса car. И внутри метода
создан новый объект класса car. И цвет присвоен именно ему. Объект же Car с после вызова метода никак не изменился – цвет по прежнему
красный. Все изменения произошли с ново созданным объектом с2. С объектом с ничего не произошло.

Массив = array (коротко введение)

1) Коротко – объект представляющий из себя коллекцию каких-то значений. В фигурных скобках эта коллекция. 2) У каждого элемента есть значение и индекс – где стоит элемент в массиве.
Здесь не могут быть использованы разны типы данных. Если массив int – все значения должны быть int. Индексация массива всегда начинается с нуля. Важно - массив это объект!

String is immutable

Если мы написали String «привет», то этот «привет» уже не может быть изменен. 3 фактора почему значение String не меняется.

1) String хранится в private array (прайват массиве), который имеет 2) Он в final массиве, поэтому может быть инициализирован только раз. То есть мы можем написать этот
фиксированную длину. То есть мы пишем String «привет» – в памяти создается 3) Ни один из методов класса String не изменяет индивидуальные элементы массива
объект один раз и все - больше нельзя. То есть в случае на картинке массив value ссылается только на объект типа char. То есть у класса String есть ряд методов которые мы будем изучать позже. Ни
массив с набором символов совпадающих с этой надписью. Private здесь “привет” и не может ссылаться на другой объект. Он final . Но как мы отметили раньше, внутренность этого
значит что что массив может быть виден только внутри класса String один из них не меняет элементы этого массива
объекта может быть изменена (как в том примере с машиной – цвет машины и тип двигателя внутри объекта
изменить можно, а переназначить на другой объект эту переменную нельзя.) Как же тогда он не
изменяемый, если содержание поменять можно? Следующий пункт объясняет
Методы String

2. charAt
1. Length

1) Параметров нет, возвращает int. То есть помогает


найти длину массива. В данном случае 6. 2) Или так

1) Параметр int index, возвращает char. «Символ на». 2) Если написать слишком большой индекс - 10й когда элементов 6
То есть узнаем, какой символ на этом индексе. Помни, – выведется exeption – сообщение что столько индексов нет
что подсчет идет с нуля. Здесь 4 символ = v

3. Index of

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

1) Char c– на каком индексе элемент с, данном 2) String s – вписываешь набор букв из String , например “рив” из 3, 4) Если есть несколько одинаковых символов . Char и int/ String и int – на каком индексе находится первый такой символ после такого-то индекса. (Важно,
“привет”, выведет номер индекса на котором этот String – то есть походу включая этот индекс. Смотри ДЗ к этому уроку)
случае «t» – выводит 5
по факту номер первого элемента? Да, тут выводит 3
Например на каком индексе первый “a” после 5го индекса. В данном случае 7. То есть это самый обычный номер индекса этого String - отсчет индекса начинается с
самого первого символа. Но все другие «а», если они были до 5го индекса, игнорируются.
Если указать символ или строку, которой не существует, Важно! Указывается индекс именно самого первого «a» после 5-го индекса, если дописать после этого «а» еще несколько «а», на результат это не повлияет.
выведет -1 То же самое со string. И опять -1 если не выполняется.

5. Replace
4. Trim

Просто убирает пробелы по бокам Не трогает пробелы


внутри String.
1) Replace меняет один символ на другой. Важно – не изменяет
2) Второй использует String . Тут String, нельзя поменять на
старый String, а создает новый с изменением. Если заменить символ
Char, только String и String или Char и Char.
которого нет, новый String будет таким же, без изменений.

8. subsstring
6. Startswith 7. endswith

1) Отвечает на вопрос, правда или нет, что String 2) Отвечает на вопрос, начиная с этого
начинается с этого набора символов. индекса - идет этот набор символов?
Логично. Тоже должен быть String а не Char 2) То же самое, но еще указываем, по какой индекс отрезать
1) Принимает int и возвращает string, который содержит не учитывается. Здесь 7й индекс «а». Выбираем отрезать п
участок string от указанного индекса и до конца. То есть «а» на экран не выходит.
отрезаем кусочек от такого-то индекса. Например, здесь string Интересный момент. Если надо вывести все, а их 10, то т
abcdefgabc. Указываем индекс 3. Получаем defgabc. Причем 3й написать выведи все по 11й индекс, хотя 11го нет. Джава п
индекс выходит на экран (тут это d) ты хочешь вывести все существующие 10, то есть по

9. To lower case 11. contains


10. To upper case

9. concat

Метод конкетернации, просто знак плюса. Два варианта записи

Вариант записи 1 Вариант записи 2

Разные примеры о конкатенации

Пример 1

1) Просто интересный пример. А + и сработает как сумма и потому что


2) Если мы не хотим, чтобы они складывались можно 3) Хотим чтобы и в этом примере intы все же
это int. А с “c” сработает как конкатенация и напечатает вместе. То есть
дописать спереди пустой String складывались – используй скобки.
Java сама понимает, когда складывать, когда конкатенировать

Пример 2 Пример 3

1) Здесь уже возникает ошибка. Ошибка потому что


нельзя присвоить String`у int – ошибка компиляции 1) Ошибка компиляции – первый тип boolean, второй double.
Вывод. Обычно в случае конкатенации предпочитают
использовать плюс а не метод конкат. 2) Но опять же, можно избавиться от ошибки,
3) Но можно сделать красиво
если вставить между ними пустой String.

Пример 5
Пример 4

Null значит не ссылается ни на какой объект. И именно Null в Тут ошибки нет. Но так писать нельзя. (тут не понял,
этом случае соединяется с «ok» о чем это? тут есть ошибка компиляции)
Method chaining

1) Hello world конкат (присоединяется) к урра!!!! Создался новый объект Hello WorldUrrrrrraaa!!! s3 ссылается на этот объект.
2) Дальше trim. Он никаких изменений не вносит но все равно возвращает новый String. s3 такой же по содержанию – Hello WorldUrrrrrraaa!!, но уже
ссылается на новый созданный объект.
3) Затем метод replace меняет английское Urrrrrraaa!!! на русское Ура!. s3 ссылается на этот новый объект.
4) Теперь действует replace – World. Worldвыходит на экран. Объект s1 и s2 никак не изменились
5) Дальше. Выводится первоначальное значение s1. Hello world . Потом высчитывается что в скобках – и substracts. Получается world . Тут чтобы выполнить
метод нудно узнать параметр а параметр – другой метод. Поэтому тут не слева направо

Следующая задача

Есть текст. Пишем его с большой буквы, если пишется с большой буквы.

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

Определение равенства String

1) Метод equals имеется у всех классов по умолчанию, а


значит может быть вызван для всех объектов. Именно этим 2) Бай дефолт метод equals VS двойное равно 3) Но метод equals можно перезаписывать, в зависимости от того, что мы считаем «равенством».То есть два объекта «машина» равны
методом надо пользоваться чтобы сравнивать объекты. “==” это одно и то же. по цвету, или они считаются равными если у них одинаковый мотор.
Со String`ом метод equals как раз и перезаписан, то есть работает не по дефолту. То есть для String equals и «==» не одно и то же.
Метод equals для String является true, когда длина и содержимое (каждый символ) одинаковы. «ок» и «ок».

4. В то время как “==“ сравнивает, ссылаются ли переменные на один объект. 5. В связи с этим есть еще один метод. equalsignoreCase. Говорит, равны ли String`и,
Здесь переменные с3 и с4 ссылаются на один объект поэтому «==» возвращает true. игнорируя большие буквы и маленькие буквы.
Equals тут тоже одинаковый, потому что все символы совпадают, поэтому тоже тру.
17. StringBuilder

Отличия StringBuilder от String

1) В String нельзя поменять значение - нужно каждый раз создавать новые объекты. А в методе StringBuilder менять значение можно. То есть значение StringBuilder является mutable – можно менять.
2) В String в основе лежит final массив символов. В основе StringBuilder – не final массив символов.
3) Методы StringBuilder направлены не на создание нового объекта, а на изменение этого объекта StringBuilder. Импортируется автоматически, поэтому нет смысла импортировать можно писать короткое имя.
4) Нужен чтобы сохранить память – со String может забиться память если использовать String в проектах где постоянно меняется значение String.

Конструкторы StringBuilder

1) Обычный конструктор. Создается объект, но без какого либо 2) В параметре написано значение, в памяти создается объект со 3) Здесь тип данных int. Этот объект пока пустой, но 4) Можно создавать в StringBuilder с
значения. По дефолту вместимость указывается как 16 символов. Это значением. Здесь при создании автоматически выделилось 24 места в оно говорит, что вместимость будет 50 символов. другим StringBuilder в параметре.
первоначальная capacity, но ее можно менять. То есть если мы сначала массиве. 8+16 (то есть при создании массива со значением 16
записали до 16 символов, просто используется этот стандартный добавляется вдобавок к количеству знаков в параметре?)
массив. Если поменяли на 16+ char – создается новый массив с нужным
количеством char и в него копируется значение старого и добавлябтся
новые места. (а старый удаляется garbage collector наверное)
Методы StringBuilder, которые совпадают с методами String

2. charAt
1. Length

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


Просто выводит длину. Важно! Если вывести, например, sp3 у которого указано int 50, то
длина все равно будет ноль, потому что хоть capacity 50, но там еще нет ни одного char.

2. indexOf 3. Substring

2) С помощью int указываем, с какого


индекса начать учитывать символы
1) Возвращает отрезанный кусочек, начиная от 2) Возвращает отрезанный кусочек, начиная от
указанного индекса до конца строчки указанного индекса, до указанного индекса
1) Возвращает значение int индекса первого символа указанного String.
Здесь уже нельзя выводить char. Только String. (в смысле, что char
обозначается ‘a’, а String “aaa”. В одиночных кавычках выбьет ошибку,
но если записать 1 символ в двойных кавычках, то все сработает)

Методы StringBuilder, которых нет у String

1. subsequence 2. append

1) В конец StringBuilderдобавляет указанное в 2) То есть добавляя новые append добавляются новые


Выводит отрывок последовательности символов. Поэтому в output – параметре значение окончания, не создавая новый объект. Добавляя объект в конец,
char sequence, последовательность символов. в StringBuilder добавится адрес этого объекта в памяти. (не
Работает так же как substring метод. Просто в output – char sequence. (в знаю, к чему это, но новый объект не создается)
чем разница между string и char sequence? string это класс, char
sequence – интерфейс. В отличии от string, char sequence можно менять.
Думаю потом об этом расскажут подробнее)

3. Insert 4. delete 5. deleteCharAt

Удаляет символы с одного индекса по другой индекс

Удаляет конкретный символ на конкретном индексе

Вставляет на какую-то определенную позицию определенное значение. )


То есть может использоваться как расширенный метод append

6. reverse 7. replace 8. Capacity

Меняет символы от index до другого index, заменяя Просто показывает Capacity этого StringBuilder
Переворачивает StringBuilder в другую сторону
указанным String. Включается по указанный индекс, не
включая его (то есть здесь 5й индекс – “d”, но “d” остался)
Append будет выполняться в первую очередь (по правилам метод chaning)?. Далее substring. По идее должно выйти на экран “friend”. Но по факту выйдет
ошибка компиляции, потому что в substring index of указан f , а по правилам должен быть String. Если бы там была String, то на экран вышло бы френд.

StringBuffer

Есть еще класc StringBuffer – очень похож на StringBuilder. Его не будет в экзамене. Функциональность
почти одинакова, StringBuffer лучше в многопоточности. А StringBuilder там где нет многопоточности.

Пример. Что выведется на экран?

Учитывая, что это StringBuilder, новые объекты не создаются. Append добавляет новые
значения в конец. Все изменения происходили с одним и тем же объектом, поэтому на кран
выйдет одно значение для обеих переменных. Обе переменные ссылаются на один объект.

Равенство StringBuilder`ов

1) Напоминаем, что 2 String будут equals если их 2) А как в StringBuilder`? Создаем 2 одинаковых StringBuilder`а. Проверяем 3) Вот только сейчас будет тру. То есть
содержание совпадает. Также напоминание, что их с помощью ==. Выдает false. С помощью метода equals. Тоже false. Это здесь обычный метод equals и ==.
метод equals есть у всех классов. значит что в методе StringBuilder equals не перезаписан и работает как ==.

Еще два конструктора класса String.

1) В параметре String можно использовать Stringbuilder. 2) То же самое уместно со StringBuffer


018 Урок 18 Понятие «массив». Работа с массивами

Общая информация. Многомерные массивы

1. Массив это объект который хранит определенную 2. Элементы массива могут повторяться (5 и 5). Первый элемент – индекс 0. В заданном 3. Вот эти квадратные скобки указывают, что 4. Тип данных массива может быть каким угодно. Если
коллекцию значений определенного типа данных массиве нельзя изменить длину массива (в данном примере элементов 5) перед нами массив типа String. Если бы их не мы создали новый класс Car, он ведь тоже тип данных.
(либо примитивного, либо референс) Ниже пример массива с референсными типами данных. Массив референсных типов данных было, это было бы просто String Можем сделать массив типа данных Car.
ссылается на адреса этих объектов (которые как я понял автоматически создаются? или их
надо создать заранее?)

5.Также можно создавать массивы, элементами которого являются другие 6. У внутренних массивов двойная индексация. Два 7. Как поменять значение определенного
массивы. запись ниже. Все элементы двумерного массива являются индекса – первого массива и второго. элемента массива? Запись ниже. 8. Как вывести второй нулевой элемент второго массива на экран?
одномерными массивами. Индексы у каждого одномерного массива
отдельные. Но у внутренних массивов своя индексация

9. А с двойными массивами? Как вывести на экран их элементы? 10. А теперь трехмерный массив. Например char. Как выглядит в джаве. 11. Нет ограничений на количество измерений. 5-мерный, 6-мерный, сколько
хочешь. Элементами 5-мерного массива будут 4-мерные массивы и тд.

Объявление массива array

1. тип данных + знак array[] и название массива 2. На данной стадии массив ссылается на null

Этапы создания массива

Allocation

1. Allocation (Определение)
Здесь уже нужно указывать размер. размер массива – всегда int 2. Можно обмануть java здесь и вписать минусовое значение размера, но в итоге 3. Но если длины массивов одинаковы на втором уровне, то
выбьет exception (логично - не может быть минусовое количество элементов). можно сразу указать длину обоих массивов
То есть в скобках int`ом указывается размер. Это число означает длину массива. То есть Подробнее про двумерные массивы. Нужно же указать длину массивов. А что если
создается массив с заданным размером, заполненный дефолтными значениями на втором уровне количество элементов в разных массивах разное? Тогда можно 4. Отметим момент. Параметр длина (length) в данном случае не с
указанного типа данных. Если массив int, то это нули. оставить второй квадратик пустым, java так разрешает. Но нужно обязательно методом. У массива длина это не метод – мы не ставим круглые
указать количество элементов в массиве первого уровня! после length. length– это элемент класса, то есть это переменная.
length это метод, у массива – это переменная, атрибут клас

Initialization

Инициализация - в данном случае это когда элементам придается определенное значение.

Статическая инициализация

3. Еще один пример, создаем array 7. задаем ему размер 2. а потом array 7
приравниваем к array 5 . Это же объекты, то есть так можно делать. Это значит, что
array 7 будет ссылаться на тот же объект, что и array 5. (а на массив array 5 тогда
больше ничто не ссылается и он удаляется?)
2. Внимание как можно придать значения двумерному массиву.
1) Создаем двумерный массив array4 типа данных int. Это значит, что есть 4 массива, в
каждом из которых есть 2 элемента int.
2) Создаем отдельно одномерный массив array5, который вмещает 2 элемента int.
3) Присваиваем первому массиву array4 значение массива array5. Джава проверяет, что у
массивов одинаковое количество элементов и разрешает так сделать

Еще один вывод, при многомерных массивах, только последний массив содержит указанный
1. При статической инициализации инициализируем arrey 2. Просто при создании тип данных, все массивы выше это массивы, которые содержат другие
присваиваем элементам значения. Один за другим. Занимает много места. массивы. То есть настоящее содержимое только в массивах последнего уровня)
Не обязательно инициализировать все элементы.

Динамическая инициализация

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

2. 2й пример. Создаем двумерный массив array2


1. 1й пример. Мы задали элементы array1 не вручную, а написали Задаем статично его элементы. Конечно каждый 3. А теперь задаем лупы for для этих
формулу, которая задает логику, как задавать значения. элемент первого уровня это новый array (делаем их элементов-массивов второго уровня.
разного размера в данном примере – для интереса)
Смешанные варианты создания массива

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

1) Похоже на создание обычных объектов, 2) Похоже на создание обычных объектов, 3) Похоже на задачу значения
3) Как вариант 2) но записано в 2 строчки
где параметр [] – длина массива где параметр {} – значение массива примитивному типу данных: int a= 5;

Здесь мы объявляем массив и сразу показываем, какая у него Java допускает такое написание. Напоминает создание В два шага – создаем массив. В этом варианте объединены все три шага. тип данных, знак [] указывающий
будет длина. Здесь все 7 элементов будут принимать обычных объектов классов, но параметры в {} скобках, задаем значения массива. что это массив, в фигурных скобках задаем значение элементов массива. Мы
дефолтное значение, инициализации не происходит. не указываем длину, джава сама посчитает. Два раза указывать длину
нельзя, в этом случае мы уже типа указали длину с помощью задачи
значения элементов.

Но так нельзя, в этих квадратных скобках нельзя Вот так нельзя. Разбивая на две строчки нужно указывать
указывать длину массива. нельзя дважды new int и квадратные скобки. На экзамене будет много
указывать длину массива, явно или неявно. вопросов где будут ловить правильно ли записаны массивы.

Как задавать значения многомерному массиву.

СМОТРИ ПРЕДЫДУЩИЙ СЛАЙД ДЛЯ ПРИМЕРА

1) С помощью формулы, если есть логика какая-то 2) Создаешь многомерный массив – пока пустой. Потом отдельно создаешь массивы нижнего 3) Можно сразу вписать все значения на всех уровнях, используя фигурные скобки {}.
уровня с указанными элементами. Потом элементам внешнего массива присваиваешь Помни, что если уровней массивов два, то элементы первого (внешнего) массива –
значение этих отдельно созданных массивов нижнего уровня. массивы, а элементы второго (внутреннего) массива – данные (тут String). То есть при
данной записи все внешние массивы находятся в одних фигурных скобках. (то есть в
это конкретном примере на скриншоте пиши фигурные скобки, в них создай массивы
внешнего уровня (тут их три), а в них создай массивы внутреннего уровня (тут их два,
три и один, они типа данных String))

Положение квадратных скобок

1) Квадратные скобки могут стоять и так и 2) Но, если мы запишем так, то это значит что и ”array” 3) а в этом случае мы говорим, что “b” это массив типа
так. с двумерными можно даже так. и “a” это названия массивов, потому что знак 4) Это значит, что “d” – одномерный 5. А вот так – “d” – одномерный а “e” – двумерный.
int, а “c” это переменная типа int. Так лучше не писать,
квадратных скобок стоит до названия массивов. массив, а “e” – трехмерный
но нужно знать для экзамена.
(квадратные скобки относятся и к “е”).

Введения к исключениям (exceptions)

Задаем размер массива – 3. Пытаемся задать значение элементу с индексом 3 1) Создаем двумерный массив. Длину массива второго уровня не 2) Не к массивам, просто к слову. Точно также создадим переменную
(индекс 3 – 4й по порядку, так как отсчет идет с 0). Джава пропускает, т.к. не знает, что задаем. То есть они еще не заданы. Выводим на экран String с. она еще не задана (то есть она тоже null). Выводим ее на
элемента с индексом 3 не существует. Но при запуске выбьет исключение. предположительный первый элемент второго уровня – выбьет экран. Тоже выдает ту же самую ошибку.
ошибку. Этот объект еще null, у него нет никакой информации,

class Arrays

Я так понимаю, что класс arrays содержит методы для работы с массивами. И я так понимаю, он не импортируется автоматически. Класс arrays
находится в пакете java.util. Импортируем его чтобы ссылаться на него по короткому имени. Создаем array1 и задаем сразу значения.

Метод sort(array)

Сорт сортирует массив.


Мы выводим элементы с помощью for. А что было бы если просто sout array1?

3) Arrey это объект. Всегда при попытке вывести на экран объект в виде строки
2) Теперь отсортируем. Пишем Arrays.sort и в параметр пишем имя
1. Сначала выведем на экран элементы массива. (String), вызывается метод toString. Метод может быть перезаписан чтобы вывести
нашего массива. И опять с помощью цикла for выведем на экран.
красиво, но в данном случае он не перезаписан.

Метод binarySearch(array, value)

*обязательно нужно сначала отсортировать

А если попросить вывести элемент которого нет, например 10? Вывел отрицательный индекс -9.
1) Выполняет поиск определенного value в определенном arrey. Важно – Почему? Он показывает где была бы «10» если бы она была в массиве.
корректно работает только в отсортированном массиве. Выдает индекс на
На последнем месте (в уже отсортированном array – смотри скриншот слева).
котором находится наш элемент. если элемент не найден – возвращает
И индекс был бы 8. Ставим минус «-» перед индексом, получаем -8. И еще отнимем 1 (не понял почему).
отрицательный индекс. В данном случае вывел индекс 0 Получаем -9. Это просто к слову, скорее всего не понадобится.

Сравнение массивов
Метод main

Как можно догадаться в методе main указан массив String. имя массива args может быть любым, его можно поменять.

Пример-задача

Написать метод который принимает в параметр массив и выводит на


экран его наибольший и наименьший элемент (1.31).

1) В параметре метода мы пишем массив. Создаем два double переменные, которым назначаем значение 0го элемента массива.
2. Дальше создаем метод main. В нем создаем array1и задаем его
2) Потом создаем цикл for с двумя if.
значения. Используем метод, все работает.
3) В первом if мы сравниваем значение1-го элемента массива с 0-м (используя созданную перед этим double переменную max). Если 1й элемент массива
больше 0го, double max принимает значение этой переменной. Если нет, двигается дальше. С каждым циклом, эта проверка двигается к следующему
элементу массива, пока не дойдет до конца и не будет найден элемент, который окончательно больше остальных.
4) То же самое делается, но уже с переменной double min.

Просто еще один способ записывать String. Вручную задав каждый


элемент массива char и присвоив его String (но стринг создается То же самое что и append, но вставляем элементы в
через полную запись) середину StringBuilder а не в конец
То есть у нас есть массив char “Привет” и StringBuilder “Hello World”.
Этот метод берет 3 параметра:
Метод append добавляет к концу StringBuilder новые элементы, взяв их из массива (это работает только со StringBuilder – массив
1й - с какого индекса вставлять (2)
char? Кажется это метод исключительно StringBuilder но он берет много разных параметров, так что могут быть другие варианты
2-й – из какого массива вставлять (array1)
использования) В данном случае к “Hello World” добавились 2, 3 и 4й индексы.
3-й - с какого индекса array1 вставлять (1)
Что значат параметры:
4-й - сколько элементов вставлять (3)
1й – из какого массива берем элементы (array1)
2-й - с какого индекса array1 вставлять (2)
3-й - сколько элементов вставлять (3)
019 Урок 19 Параметры метода типа varargs. Аргументы типа command line. Цикл «foreach»

Command line arguments

1. Все что мы записываем в методе main


становится частью массива args.

2. Задаем через компилятор элементы массива args. Запускаем – выбивает


результат. То есть мы передали эти аргументы (вписанные в командной
строке уже – «ok poka privet on ona» – это и есть command line arguments
программы в момент запуска. Это String, args всегда String. Все аргументы
command line arguments – String.

Variable arguments = varargs

1. Метод выводит на экран сумму двух элементов


2. А что если нужно вывести на экран сумму трех 3) Сумму четырех? Снова новый метод. Эти методы
элементов? нужно написать новый метод.
называются overloaded. А что если нужно вывести 100
методов. Такой копипейст займет много места. Для
этого придумали varargs

4) Вместо всего этого можно написать один


метод. “int … a” означает, что метод summa
5. Это абсолютно то же самое, если бы мы написали массив int. 6. Также summa сумма можно было бы записать так. Указываем в
можно вызывать с любым количеством 7. Можно указывать несколько элементов с разными типами
Поэтому можно написать этот цикл и вписывая любое значение в параметре массив. тогда в параметре метода при его вызове в
переменных int. От 0 до бесконечности данных. Например здесь обязательный элемент String s. Если
параметры summa в методе main будет выполняться значение цикла методе main нужно тоже указывать массив. Это не всегда удобно. Но
for – то есть будут складываться указанные числа в параметре его указать как «ок», он всегда будет «ок». а потом varargs а, в
так и не надо писать. Когда мы используем varargs метод именно это который можно указать любое количество значений. Но
метода сумма. Сколько бы чисел мы не указали бы. и происходит «за кулисами». Создается такой массив. Джава просто varargs должен быть только один и стоять последним в
переводит после компиляции этот параметр в массив. Но с varargs параметрах
просто удобнее работать.

Пример. Массив в параметре varargs


Следующий код varargs выбивает ошибку

То есть это одна программа с таким методом. Ошибку выбивает, потому что Java
будет считать, что и там и там одинаковый метод abc – в параметре и там и там
указан массив int, для Java они одинаковы и Java не может понять, какой из них
выбрать, хоть запись и разная (с массивом и с varargs) Еще один пример. Вот это значит, что можно вписывать в параметр неограниченное количество массивов типа int. То есть можно
использовать массив в параметре varargs. Что это значит. Помним, что параметр varargs можно заменить массивом (это по сути и
есть массив). То есть например (int…a) можно заменить на массив int: (int[]a) и вписать неограниченное количество целых чисел
int. А в случае с массивами (String[]..a)? Их можно заменить на массив массивов String. То есть это двумерный массив, с
неограниченным количеством под-массивов внутри. Напомню, что двумерный массив это набор массивов, внутри которых
массивы данных, то есть только 2 уровня («элементом двумерного массива является одномерный массив» - вот эта классная
фразу чтобы представлять многомерные массивы). Пример на этом скриншоте выше. Короче говоря, в случае массива в
параметре varargs, можно будет вписать неограниченное количество массивов одинакового типа. Всегда приводи себе пример,
как было бы с примитивными типами данных. С int можно было вписать сколько хочешь целых чисел, с массивом можно
вписать сколько хочешь массивов одинакового типа (никаких третьих уровней, их только два, то есть грубо говоря набор
массивов одинакового типа один за другим в линеечку.
Enhanced for = foreach

Это вариант лупа for. Этот луп используют в основном с массивами и коллекциями. Коллекции проходятся в
следующем уроке, поэтому здесь только примеры с массивами, но к коллекциям все относится точно так же.
Пример

1. Это пример обычного лупа for. 2. С массивами чаще используется луп foreach. Его быстрее писать и 3. Рассмотрим, что здесь происходит. Сначала foreach
4. Во время следующего interation foreach лупа – “а” принимает
он занимает меньше места. Результат тот же, но меньше места. говорит, что “а” должно принять минимальное
значение следующего элемента. И так далее. Foreach луп сам знает
значение массива array. Заходим в тело цикла,
когда остановиться, он знает какой элемент следующий, он знает,
выводится на экран в данном случае 0.
какой элемент последний. То есть foreach придает по очереди
значение элементов массива и для каждого выполняет код,
написанный в теле (в данном случае выводит на экран) Интересно, что
после компиляции Java переводит foreach луп в обычный луп. то есть
это просто возможность писать меньше.
Пример: Сложение всех элементов лупа

Допустим есть массив и мы хотим сложить все элементы лупа с помощью foreach.

Пример – nested foreach

1. Создаем два массива. Хотим чтобы output был таким – должно


выводить каждого студента с предметом, который он сдает.
2. Естественно тут будут использованы nested лупы. Здесь есть inner луп, разобраться потом. 53 – объяснение.

Пример с двумерным массивом.

2. Теперь то же самое с foreach (нужно указывать тип данных для foreach –


1. Сначала вывод на экран с помощью обычного лупа. здесь это array). После двоеточия всегда указывается массив, откуда берутся
элементы. До двоеточия указывается переменная типа данных этого массива. с
условным любым названием. На место этой переменной и подставляется один
за другим все элементы этого массива.

Пример с изменением всех элементов массива

2. Здесь цикл действует так. Есть два этапа – сначала придать «а» значение нулевого элемента массива.
1. Сначала пример с обычным циклом for.
Потом придать значение 3. Потом придать значение первого элемента массива. Потом снова придать
Можно сделать так – тогда все элементы
значение 3. Но на элементы массива это никак не влияет. Поэтому они никак не меняются.
массива становятся равны трем. То есть с помощью foreach нельзя поменять значения примитивных типов данных. Потому что меняются не 3. Правда, если выводить значение сразу, в этом же
значения массива, а значение этого int a foreach, то значение int a не успевает поменяться и все
работает правильно – выводятся тройки

Пример с референсными типами данных


и со StringBuilder

1. Все точно так же, но меняем на референсные типы


данных. Поменялось в этом случае? Тоже нет.
1. Теперь сразу пример со StringBuilder. Но и его значения не поменялись. Как здесь работает.
Все то же самое. Тоже два этапа. Первый – sb принимает значение первого элемента массива. Второй этап – принимает
значение “hello”. Первый цикл – sb принимает значение sb1 и ссылается на объект “привет”. Второй шаг первого цикла
– создается новый объект “hello” и sb ссылается на него. Переменная не может ссылаться на два объекта так что sb
ссылается только на “hello”. Второй цикл – sb ссылается на второй элемент массива. Второй шаг второго элемента –
создается новый объект “hello” и sb теперь ссылается на новый объект “hello” и так далее. Но sb1, sb2 и sb3 как
ссылались на свои значения так и ссылаются, они никак не поменялись.

Пример со StringBuilder №2
Пример – динамическая инициализация объектов с foreach

2. Теперь попробуем то же с foreach. Не работает (почему – кажется очевидно). То есть с


помощью foreach нельзя проводить динамическую инициализацию массива.
Объяснение:
Первый шаг цикла – “b” принимает значение нулевого элемента – он не задан, по дефолту
ноль. Второй шаг цикла – принимает значение 10. То есть опять это никак не влияет на
1. С помощью for выведем на экран значения массива.
элементы в массиве, меняется “b”, элементы в массиве остаются такими какими и были

Еще пример.

1. Здесь мы меняем все элементы массива array1 на 12, array2 на 3. 2. Создавая foreach нужно выбрать один конкретный array. Если мы выбрали в
Можно ли сделать что-то подобное с помощью foreach? данном случае array1, то “а” уже не имеет никакого отношения к array 2. Поэтому
внутри foreach лупа можно работать только с элементами одного массива.

Потом наверное переписать все эти правила с примерами к кажому сверху. Каждый луп
нужно использовать для своих целей, форич нельзя использовать во многих случаях.
020 Урок 20 Всё о классе ArrayList

ArrayList

• Если коротко то Arraylist это массив который может менять свою длину. Тогда как у массива длина не может меняться (мы задаем длину массива в
начале). То есть Arraylist предпочтительней когда мы не знаем сколько элементов в массиве.
• В основе Arraylist лежит массив! Поэтому у Arraylist очень много от array, но также много нового. Одна из структур Collections, есть и другие.

ArrayList – схожесть с Array

1) Индексация 2) Возможность повторения элементов 3) Неупорядоченность элементов

Небольшое отступление – о наследовании

3) Вывод – в основе ArrayList лежит массив типа Object. А элементами


2) Важно запомнить. Имея массив типа object – его массива типа Object могут быть любые референсные типы данных (но не
элементами могут быть любые референсные типы примитивные). Поэтому ArrayList принимает только референсные типы
данных (не примитивные типы данных, потому что данных. Так как примитивные типы данных не являются объектами, они не 4. Но у каждого примитивного типа данных есть wrapper класс. О них
1) Потом будет подробнее о наследовании, но object это примитивные типы данных не классы – int, char и тд). потом. То есть у int есть класс integer, который является
единственный класс у которого нет родителя – он в начале могут быть использованы в arraylist.
То есть референсные типы, как car, String, StringBuilder референсным типом данных. С его помощью int конвертируется в
всего. Все классы это наследники класса object . могут быть элементами массива объект. рефересный тип данных и может использоваться в ArrayList.

Самый простой вызов класса ArrayList

ArrayList List1 = new ArrayList();


list.add(«Privet»);

То есть здесь мы самым обычным способом создаем объект класса ArrayList, называем его List1 . Потом
вызываем один из многочисленных методов класса ArrayList самым стандартным образом.

1) ArrayList находится в пакете java.util. Сначала его надо


2) В ArrayList можно добавить любые элементы. Для этого
импортировать чтобы использовать его короткое имя. используем метод list.add. Добавляем в него String 3) Создаем ниже класс типа car. Он пустой. 4) Создаем еще один класс Student. Добавляем в ArrayList. Создаем еще
Создали объект типа ArrayList.
Создаем объект класса car в методе main. И StringBuilder. Тоже добавляем в ArrayList. То есть теперь у этого ArrayList
методом add добавляем этот объект в ArrayList . разных типа данных. Но так практически никто не делает. Обычно
используют ArrayList одного определенного типа данных

Продвинутый способ вызова класса ArrayList – создается для одного конкретного типа данных

По факту синтаксис такой же как и в обычной форме (по сути обычное создание объекта класса), но
между ArrayList и названием мы указываем тип данных в скобках <>.

1. ArrayList . В скобках <> указываем тип данных. Название листа. И 6. И на самом деле вот это второе указание типа данных после 7. Учитывая, что ArrayList это лист, то такая запись тоже
после знака равно тоже указываем тип данных в скобках <>. равно не нужно, его можно просто убрать. Тут нет разницы. сработает. Иногда можно встретить такую запись. Разница с
Запишем пример с типом данных String. Добавим элемент «poka» - листом потом. Пока не надо на это обращать внимание.
все добавилось отлично. Но добавить объект класса Student уже
нельзя, здесь добавляется только String.

При создании ArrayList String можно сразу указать его


размер – что происходит за кулисами в этот момент.

2. Преимущества ArrayList в том, что у него можно менять количество элементов и у него есть
много полезных методов. Можно конечно использовать обычный массив, а в случае если
1. Мы записываем синтаксис для создания обычного ArrayList String надо использовать больше элементов – просто создавать новый массив большего размера.
– в памяти создается ArrayList в основе которого лежит массив типа Object. У Но ArrayList делает это автоматически, так просто проще. Вот как написано сверху можно
этого массива capacity (вместимость) по умолчанию 10 мест (если мы еще создать ArrayList и с самого начала указать 30 элементов. Но даже если все 30 заполнятся
не задали элементы) будет создано столько элементов сколько нужно. 3. Кстати. Что происходит, если заканчивается количество мест в
дефолтном ArrayList? Создается новый с большим размером и в него
переносятся все элементы старого ArrayList и добавляются новые. А
старый ArrayList не используется.

4. Еще нужно помнить о разнице между понятиями size и capacity.


Вот в прошлом примере создали ArrayList с 30 элементами. Если в
него добавить 2 элемента то size ArrayList будет 2, а capacity - 30.

5. Есть еще такой вариант. Когда в параметр ArrayList указывается другой ArrayList.
То есть тут в параметре list5 указан list2. В данном случае создается точно такой же 6. Их capacity одинаковое. 7. Также, как мы видим, элементы list5 и list2
ArrayList, но переменный list2 и list5 будут ссылаться на разные объекты. То есть list5 ссылаются на одни и те же объекты. То есть это
ссылается на подобный ArrayList list`у2, но не именно на list2. разные объекты (разные ArrayList ), но их
Они оба ссылаются на подобные ArrayList, но объекты разные, с разными адресами, элементы ссылаются на одни и те же объекты.
поэтому получаем false.
Методы ArrayList

1. Add 2. get

1. Вписываем индекс – метод возвращает 2. С помощью этого метода и обычного 3. Но для этой цели foreach удобнее (не
1. Примеры с add мы уже прошли. Возвращает boolean, но он элемент ArrayList на этом индексе. Если for можно легко вывести все элементы нужны никакие дополнительные
2. Можно также указать на какой индекс 2. А если попытаться добавить на 5ю позицию – вписать несуществующий индекс – опять
всегда true, не задумывайся об этом. Можно добавлять ArrayList на экран методы) поэтому именно он и будет
расположить новый элемент. выбьет exception – такого индекса здесь нет выбьет exception
элемент определенного типа данных и он будет добавляться использоваться в дальнейшем)
на следующую позицию.

3. set

2. [“А это пример – как изменить элементы ArrayList без его методов”] Пример, как изменить
1. Работает как replace – имеющийся объект элементы, не используя метод set. Но здесь также используется метод get здесь и size.
заменяется на другой. Указываем индекс и указываем Мы создали три StringBuilder и добавили их как элементы ArrayList. Сейчас с помощью
элемент, который хотим поместить на тот индекс обычного for будем добавлять восклицательные знаки в конец каждого элемента. То есть get
выдает а мы уже изменяем элементы листа с помощью for.

4. remove

сли удалять по индексу то в output Если удалять по объекту, то в output будет boolean true
выбьет этот удаленный объект. если удалился, false если не удалился.

3. Почему? У нас есть три переменных


ссылающихся на объект. А в list.remove
мы вставили создание нового
ла используем индекс. Удаляем второй StringBuilder на который не ссылается 5. Еще пример со String. Удаляем “poka”– “poka” исчезло. Здесь даже если в list.remove указали бы ne
2. Теперь удаляем по значению объекта. Попытаемся ввести в
нт и выводим на экран что получилось никакая переменная. То есть в то все равно удалилось бы. В этих случаях удаляется элемент, если он equals. В прошлом примере ни
параметр list.remove «new StringBuilder(“Hello”)» (один из 4. Поэтому надо писать sb1 в remove.
элементов). Запускаем – не работает list.remove просто другой объект. был equals– это были разные объекты. А в этом примере пока в list.remove идентичен пока в одном
ArrayList и поэтому он удаляется. Потому что у String equals возвращает true, кода значения одинаков
примере объекты и equals не возвращает true (потому что адреса разные, а метод equals перезапис
String). Эта концепция применима не только к remove.

5. addAll

т – вписываем в параметр название


2. Второй вариант – можем указать, с 3. Интересный момент. Что 4. Что на что ссылается теперь? Нарисуем структуру элементов list1 и list2.
ayList. Метод добавляет элементы
какого индекса первого ArrayList произойдет если после этого addAll [Вопрос, когда мы создаем String, или StringBuilder, это же объекты класса String, или 5. Еще один пример – здесь меняем не ссылки на объекты, а сами объекты, по
rayList в конец первого ArrayList.
добавлять элементы второго ArrayList. изменять элементы list2. То есть мы StringBuilder и тд. Когда мы добавляем их в ArrayList, что именно добавляется? Сам объект, StringBuilder (потому что в String вносить изменения нельзя). Добавляем объе
ращает boolean true, не обращай
То есть все элементы добавляются не в вставили элементы list1 в лист и или переменная, которая ссылается на объект? Сам объект не может добавиться. Скорее восклицательный знак. Здесь ссылки меняться не будут, а будут внесены изм
внимание на это.
конец, а на указанный индекс хотим поменять второй элемент list1 всего конкретная ячейка ArrayList выступает как переменная и может ссылаться на адрес объект (добавится «1»). Все ссылки остаются на своих местах, поэтому все
на “Ivanov”. Как можем? через list.set объекта. Удобно так представлять, чтобы понять что на что ссылается.] сработать.
Если s2 у list2 стал ссылаться на “Ivanov”, то s2 list продолжает ссылаться на “Sidorov”. То Используем list.get.append. Все сработало. В данном случае это изменение о
есть значение листа не изменится (рисовать вот так ссылки кстати очень полезно) ArrayList тоже, s2 и s2 штрих ссылаются на один объект в этом случа

6. clear
7. indexOf
8. lastIndexOf

1. Позволяет быстро очистить ArrayList. 1. Возвращает индекс самого первого обнаруженного элемента. Опять же не надо в
параметр вставлять new StringBuilder пока – он создаст новый объект (и выведется индекс 2. Но, как и в методе remove, все работает 1. Выдает самый последний индекс который выдает искомый объект
Запускаем – видим, что он стал пустой.
«-1» что значит что искомый объект не обнаружен). Нужно писать имя переменной в этом случае со String, потому что для (задаешь объект, он показывает последний индекс на котором
Для примера добавим пару пустых
(работает как метод remove – тоже идет сравнение с помощью метода equals) String метод equals перезаписан встречается такой объект). Если объект не найден – выбьет «-1»
строчек, чтобы было наглядно.

9. Size 10. isEmpty 11. Contains 12. toString

1. Возвращает int. Все просто –


выдает количество элементов. 1. Проверяет пустой ли ArrayList. 1. Есть ли такой элемент в ArrayList– возвращает true или
Пустой – true, не пустой - false false. Опять же используется метод equals – сравниваются 1. Чтобы каждый раз не писать for или foreach чтобы вывести на экран
элементы ArrayList с искомым элементом. можно использовать toString. Метод возвращает стринговую
репрезентацию на экран (в скобках). Этот метод показывает как выгляд
объект ArrayList в данном случае в виде строки.
Методы ArrayList и связанные с ArrayList

1. Clone

звращает не ArrayList, а object. Допустим есть ArrayList list1. Его 2. Создаем list1 и используем метод Clone. Метод .clone возвращает объект и в итоге
менты ссылаются на 3 StringBuilder. Клонируем list1 – получаем получается ситуация, когда справа от равно объект, а слева – Arraylist. Выбивает ошибку. 3. Проверяем, одинаковые ли объекты. Должны быть разные, потому что
солютно новый ArrayList (поэтому метод возвращает объект), Поэтому он перезаписал list1.clone(); как (ArrayList<StringBuilder>)list1.clone(); list1 и list2 ссылаются на разные объекты (разные ArrayList ). 4. Если бы нужны были чтобы ссылались на одинак
енты которого ссылаются на те же 3 StringBuilder (был похожий Не обращаем на это внимание, об этом будет в конце курса. В итоге мы создали list2, который Проверяем, да разные – выдает false. А вот уже элементы этих двух ArrayList объекты, написали бы так. Мы создали переменную
пример ц страницы назад с ArrayList в параметре ArrayList ) равен клонированию list1 должны ссылаться на одинаковые объекты. list3, которая ссылается на тот же объект, что и list1, п
они равны. Тут все очевидно (это пример просто к с

5. Проверяем, ссылаются ли элементы list1 и list2 на 6. Если поменять элемент в list1 , как это отразится на list2. Если,
одинаковые объекты. Должно быть да. Все правильно. например, поменять сам объект sb1, например вместо «а» 7. Как пример, добавляем «!!!» в конец 0-го
8. А теперь 0-й элемент list1 меняем на новый объект
вписать «аА», то оба массива увидят это изменение. А вот если элемента list1. Получилось «А!!!». Выводим 0-й
StringBuilder “D”. Выводим 0-й элемент list2 – он
поменять ссылки, то есть, например, в list1 sb1 поменять на новый элемент list2, тоже получаем «А!!!». Потому что
продолжает ссылаться на объект «А!!!»
StringBuilder «D», то sb1 list2 продолжит ссылаться на «а». оба элемента ссылаются на один объект.

2. toArray

Иногда полезно переводить ArrayList в Array. Используется для этого метод toArray.

1. Сначала рассмотрим пример перевода toArray в object. 2. Теперь с помощью foreach лупа можно
Output toArray это массив типа object (он вот так и вывести на экран элементы этого массива. 3. А теперь второй способ – он позволяет вернуть тип данных, 4. Опять можем с помощью ArrayList вывести элементы этого
записывается: Object [] array1. Массив object, это типа массив Все правильно показывает. который пишем в параметре. Посмотрите на синтаксис. массива. Получили A, B, C и 7 раз null. Почему? Потому что мы
объектов? То есть набор объектов, как набор целых чисел? А Напоминает создание массива StringBuilder, но часть после создали массив StringBuilder размером 10, осталось 7 мест и
что имеется в виду под объектами тут? Любой объект без равно («new StringBuilder[10]») находится в параметре данный метод toArray заполнил Null.
конкретики? Потому что на следующем слайде выводя с метода toArray, вызванного через ArrayList list1. В итоге
помощью foreach эти объекты, вывелись те добавленные значения ArrayList list1 записываются в этот массив (я так
StringBuilder`ы) понял, что создается массив, элементы которого ссылаются
на те же объекты, что и оригинальный ArrayList ) и
присваиваются переменной массива StringBuilder Array2

6. В чем разница между первым и вторым вариантом toArray. Первый возвращает массив
object. Второй возвращает массив того типа данных, который мы напишем в параметре.
Естественно со вторым часто удобнее работать.
7. Важно! метод toArray создат новый массив. Референсы элементов нового массива
5. Если указать меньший или идентичный размер массива – выведет ссылаются на те же элементы, что и первый массив. То есть создается не ArrayList, а
A, B, C, но уже без Null. Размер в любом случае будет три. Даже если массив, array, элементы которого ссылаются на те же объекты что и ссылаются элементы
в StringBuilder там указать 1 в параметре. А если пишешь больше, то array листа. (то есть точно такая же логика как и у клонирования?). То есть если в List1
метод заполняет лишнее Null. Но если ничего не написать в сделать так чтобы sb1 ссылался на другой объект “D” (смотри картинку), то это никак не
параметре, то выбьет ошибку – помним, что создавая одномерный повлияет на то что sb нового массива продолжит ссылаться на объект Аа.
массив, нужно обязательно указать его размер.

3. Arrays.asList

1. В параметр пишем массив определенного типа, на выходе


получаем List этого же типа. Именно List, не ArrayList. 2. Если мы попытаемся заменить элемент массива, или
Полученный лист не ArrayList. Его длина измениться уже не изменить внутренность у ArrayList, то у List отразится то 3. А теперь давайте не изменим а заменим. 0-й элемент поменялся и
может. List это интерфейс, о нем позже. же самое. (в отличии от методов clon и toArray) Этот List у массива и у list. А в toArray и clone если бы мы заменили сам
полностью зависит от ArrayList. Давайте изменим 0-й объект, а не его внутренность, то это бы никак не повлияло на
элемент массива array. Видим что этот элемент клонированный ArrayList или ново созданный массив toArray.
поменялся и у list8.

4.Collections.sort

1. Вызывается с помощью класса Collections. Если для сортировки массива 2. Импортируем класс Collections. Потом в параметр
использовался класс Arrays (нам сначала надо было импортировать вставляем ArrayList и метод его сортирует.
java.util.Arrays), то здесь используем класс Collections.
Мы в параметр вставляем ArrayList и он его сортирует.

5. equals

1. Тут пока очевидно 4. Создадим list4, добавим только один элемент,


1. А если создать list3 и добавить в него такие же значения (то есть сделать так, 3. Проверим, влияет ли порядок, в котором
проверяем – false. То есть все элементы в правильном
чтобы элементы list3 ссылались на те же объекты, что и list1). Получается true, значит указаны эти элементы. Да, важен.
порядке должны ссылаться на те же самые объекты и
list1 и list3 равны. То есть метод equals в ArrayList перезаписан. Два ArrayList тогда equals с ArrayList выбьет true
считаются равными если содержат одинаковые элементы.
(Но, если создать 2 ArrayList с разными объектами, у которых одинаковые значения,
то выбьет false – элементы должны ссылаться на одни и те же объекты)
Iterator & ListIterator

Iterator

1. Кроме лупов, как еще можно вывести на экран содержание


листа? Можно импортировать java.util.iterator и записать Отличия Iterator и ListIterator от foreach в том, что с
3. Есть еще такое написание.
следующее (см картинку). Что такое Iterator. Iterator это 2. Дальше пишем while с it.hasNext(). Запускаем. Iterator помог вывести на помощью Iterator можно, например, удалить элемент
ListIterator работает так же.
повторитель. С помощью этого объекта it (название переменной экран элементы ArrayList. hasNext смотрит есть ли следующий элемент. (смотри выше) (в принципе, можно еще с помощью
объекта Iterator) мы можем пробежаться по элементам листа. Когда дошел до “D”, hasNext вернул false – значит нет следующего обычного for удалить элемент). hasNext смотрит если ли
Логика записи: iterator Arraylist String под названием it = возврату элемента. А метод next выдает этот элемент. следующий элемент. it.next выводит, it.remove удаляет.
метода iterator построенного от Arraylist list1.
021 Урок 21 Понятие «garbage collection»

1. Мы уже его проходили – аналог if statement. Выражение до «:» 2. Но вот так писать нельзя. Потому что если “а” меньше 4х,
выполняется если условие до «?» - true. Выражение после «:» мы не сможем int присвоить значение “привет”.
выполняется если условие до «?» - falsr. Причем выражения 1 и 2
не обязательно должны быть одного типа данных (смотри схему
3. Еще пример. Здесь срабатывает выражение 4. И наоборот, здесь срабатывает false, Java
этого оператора). Может быть, например, int и String.
true, а увеличивается на 1 и выводится на даже не заглядывает в true, сразу читает false.
Пример. Выводи 7, если true и “привет” если false
экран. Но до строчки b++ Java не доходит, Поэтому код в true не выполнится
поэтому к b единица не добавляется

Конфликт имен при экспорте

Когда происходит конфликт имен при экспорте, а когда нет. Вот у нас есть классы а в пакетах p1 и p2. Мы их импортнули оба.

Пример 1) Если использовать короткое имя класса Пример 2) Java разрешает импортировать все классы Пример 3) Вот если мы импортируем «а» из пакета p1 напрямую, а p2 все Пример 4) И как на самом деле стоит такие
«а», Java будет непонятно, какой из двух пакетов p1 и p2 (*). Но вот так вызывать класс а нельзя. классы импортируем целиком, то Java будет принимать к сведению класс классы импортировать. Чтобы не было путаниц
импортированных пакетов нужно использовать. опять же она не понимает с каким классом а работать. “а” импортированный напрямую в первую очередь. нужно обращаться по длинному имени.

4. Пример. Таких примеров будет много на экзамене. Типа, сколько будет


удалено объектов. Самое главное правило – мы можем знать какие
объекты могут быть удалены, но гарантии нет. Там был в итоге простой
пример – у переменной обрывается ссылка на объект, переменная может
быть удалена. На объект ничего не ссылается – объект может быть
2. Мы можем с помощью этого метода удален. Внутренняя переменная – закончилась область видимости –
3. Этот метод вызывается Garbage
1. Garbage коллектор отмечает объекты, которые по правилам намекнуть Java, что сейчас неплохо было элемент может быть удален.
коллектором на объект, когда Garbage
стали недосягаемы . Мы на этот процес повлиять не можем. бы использовать вот в этом случае
коллектор определяет что, объект
Garbage коллектор. Но Java может это
Объект становится недосягаем если: может быть удален.
просто проигнорировать.
1) написать что «а» = null
2) присвоить “а” новый объект
3) если “а” ссылается на объект, но “а”
локальная переменная и ее скоуп закончился.
Тогда мы не можем использовать этот объект.

Моменты с Garbage коллектором, которые нужно помнить

1. Есть паблик int а. Находится в package p1. Есть еще p2, в нем класс б. 2. Очень тонкий момент, многие упускают из виду. У конструктора А () модифаер
Если перед классом “а” не будет стоять public, то этот класс не будет виден 3. Тут все понятно
дефолт, поэтому он не виден в классе B. То есть в классе 6 объект Aa = new А
в пакете p2 – только в пакете p1. Перед тем как смотреть какой модифаер нельзя создать – его там не видно. Важно следить за access модифаерами и
у элементов, сначала посмотрите какой модифаер у класса (логично) У помнить, что дефолтный модифаер не отображается но он есть.
класса может быть только private или default тип.

4. Внутри конструктора Test вызываем конструктор Test. Так


нельзя. Этот процесс никогда не закончится, он постоянно 5.1 Создаем конструктор test3. Создаем в
будет вызывать себя. class А объект test3. Все работает,
5.2 Добавляем return type void – все, это уже не 5.3 Вот если создать конструктор
выводится на экран надпись.
конструктор, а метод. Запускаем, в отличии от то все сработает.
конструктора, метод ничего не выводит. Потому Могут быть вопросы такие.
что сработал дефолтный конструктор (потому Сколько тут конструкторов –
что мы сами не прописали конструктор для только один – второй – метод.
класса test3)

8. Почему вывелось 97? потому


7. Видим что overloaded метод может иметь как что порядковый номер символа
референс так и примитивные параметры. «с» где-то в Юникод - 97
6. Можно здесь создать переменную test3, компилятор не
ругается. test3 и метод, и конструктор, и класс, и переменная. А
если есть класс, то можно назвать переменную test3 test3, но так
лучше не делать чтобы избежать путаницы.

1) Метод, который возвращает какое-то значение, не


2) Пример когда return type не последнее предложение в методе.
обязательно должен быть присвоен переменной. То 3) Можно писать return в метод, где return type – void. Как тут, но
есть две последние строчки – два разных варианта, Можно так написать? Да. Return 5 это statement и он стоит не в 4) Здесь уже смысл есть – если I2
после return нельзя ничего писать, это будет unreachable statement
самом конце. Return statement должен быть последним statement,
присвоенный переменной и нет. (я так понимаю, что в этом случае return просто выводит из метода больше 3, то заканчиваем метод.
код которого выполняется. Он не обязательно должен стоят в
– return это последняя выполняемая строчка в методе). Но смысла
самом конце метода. То есть в данном случае если “i” больше 10,
нет писать, так как и так и так метод заканчивается. То есть у этого
последним statement будет return 5 и больше ничего не
return здесь нет смысла.
произойдет. Если сработает else – сработает return 10, до return 5
курсор java не дойдет.
Урок 22 Инкапсуляция. Super Protected

3 принципа ООП

Encapsulation (сокрытие данных) Inheritance (наследование) Polymorphism (полиморфизм)

Encapsulation (сокрытие данных)

Как пример – банкомат, вводим пинкод, видим баланс. Нельзя поменять просто баланс. Можно поменять
баланс только выполняя операции. Мы можем увидеть баланс, но он защищен и просто так его не поменять. То
есть некоторые операции возможны только через другие операции, а некоторые вообще запрещены.

Пример в Java

1. Создаем final String pol и задаем его в конструкторе. Создаем объекты, что 2. Тут можно легко поменять возраст на 2500 и вес на -65. Это никуда не годится. 3. Ставим access модифаер privat для наших переменных. Затем, если мы хотим чтобы мы могли что-то делать с переменной
может меняется у человека. Создаем класс Тест с методом main. Создаем объект Нужно сделать так, чтобы возраст и вес менялись в определенных границах. name вне нашего класса мы создаем паблик методы. первый паблик метод позволяет нам видеть эту переменную name. Такие
Chelovek и задаем значения. Создали такого вот человека. Поэтому к классу применяется инкапсуляция. Задаем ограничения. паблик методы обычно называют get+что позволяет видеть – name. getName. Никаких параметров, return – name.
(То есть, хочешь защитить класс – сделай его privat, а если хочешь все же иметь возможность манипулировать этим классом в
каких-то границах, сделай public методы, которые будут задавать, что именно и как можно менять.)

4. Также создаем метод, который позволяет сменить имя. setName. (этот метод
void потому что он не должен возвращать имя, для этого есть метод getName. Этот 5. С возрастом еще интереснее. Тоже создаем паблик метод 6. Зато их можно менять с помощью методов.
метод только меняет) Параметр – String s. Присваиваем name = s. То есть мы getVosrast и setVosrast. Но в setVosrast есть условия – не
применили инкапусляцию к String name. Мы сделали ее privat и создали методы меньше нуля. То же самое делаем и с весом.
которые меняют его элементы – гетные и сетные. Теперь нельзя напрямую работать с возрастом, весом и
именем. Они privat и выдают ошибки теперь

7. Выводим на экран. Еще раз, Get позволяет видеть переменные. Set – 8. Маленький момент – если
позволяет придавать им значения. Сеттеры и Геттеры. boolean то не Set, или Get, а Is.

9. То что эти методы – паблик значит, что их можно использовать и в других пакетах. (Меняем только
и конструктор Chelovek на public). Создаем новый пакет и проверяем. То есть мы можем работать с
privat переменными даже из другого пакета, используя public методы.

11. Вот так – тут возвращается не сам объект а его копия.


Запускаем программу – плюсы не добавились. Когда мы
10. Меняем String на StringBuilder. Добавляем 1111 в конец. Это ошибка – нельзя, чтобы с помощью Get можно было получаем от метода getName этот StringBuilder, мы
поменять объект. Инкапусляция не срабатывает. Для этого есть Set. Как это можно исправить?
получаем именно копию Name. С этой копией что угодно
Mutable – например StringBuilder
можно делать, это не повлияет на Name и на экран
(String – не mutable)
выведется Name. То есть мы меняем sb а не Name.

Inheritanc
e

1. Наследование. Класс Animal – Parental. Dog, cat - Child классы.


2. Синтаксис наследования. Используется слово extends. Допустим класс Animal имеет методы run и
Логика что класс-родитель может быть только один. Но у классов
количество ног. Тогда Cat и Dog тоже будут иметь эти методы. К тому же они могут иметь какие-то
родителей может быть много классов детей.
свои уникальные методы. Родительский класс всегда более общий, детский класс – более
конкретный. Это разные названия этих классов, все используются.

Пример Inheritance

1. Вот тут нет никакого наследования. создано три класса. Много 3. В итоге если создать нового доктора, то ему доступны все
повторений. Можно создать общий parent класс employee. 2. Создали – сразу занимает меньше места.
параметры Doctor и все параметры Employee.

4. Детские классы тоже можно экстендить


5. Еще важный момент о котором говорили раньше – на
верхушке иерархии есть класс Object, у которого нет
прародителей. Мы не пишем, но Java сама дописывает что
эти классы экстендят Object
Отношение между классами. Object класс

Тут на интуитивном уровне понято – два вида отношений.

Что наследуется классом?

1. Не важно почему static – просто как пример. Посмотрим 2. Все заданные выводятся. Name не задал – потом
какие атрибуты доступны в классе Student. вписал Коля и вместо null выводился Коля. В итоге 3. Но private наследоваться не может –
все элементы паблик поэтому все наследуются. private виден только внутри себя 4. А если privat переменным сделать с помощью
инкапсуляции паблик методы Get Set? С помощью методов
можно работать с этой переменной – вывести на экран
имя. Потому что public методы наследуются, если даже
privat элемент этих методов не наследовался.

5. Попробуем с default модифаером – с ним видно в


6. Последний модифаер – protected. Работает как default, но с
пакете, но не за пределами пакета. Тут очевидно в
отличием – элементы класса видно в классе и во всех классах
этом пакете все наследуется, а в другом нет.
которые наследуют. Даже если в другом пакете. 7. Тонкий момент. Protected значит, что методы и переменные класса будут видны только объектам классов в пакете, в
котором они созданы + еще в других пакетах всем классам, которые этот класс экстендят. За пределами пакета ключик к
этим protected элементам только у объекта, класс которого экстендит класс этих protected элементов (то есть в примере на
картинке к protected элементам можно обратиться только через объект- переменную s). Получается парадокс – объекты
класса, в котором созданы эти protected переменные, в другом пакете не видят свои protected элементы, потому что по
факту этот класс не экстендит сам себя в другом пакете.

То есть если класс не экстендит, то его объекты не видят protected элементы, даже если это его же элементы. Даже если
создать объект суперкласса в сабклассе (не важно, суперкласс в другом пакете все равно не экстендит сам себя)

Но! Static элементы все же можно вызывать в классе который экстендит, но в классе который не экстендит вызвать не
получится (смотри Student2.salary) – для них не нужно создавать объект, поэтому это своего рода исключение.

1. Конструкторы не наследуются. Создаем новый класс Human3, с одним


обычным конструктором, который задает оба значения и один 2. Пока закомментируем конструкторы , будем использовать
дефолтные конструкторы. Что происходит в методе main. 3. Когда создается объект саб-класса, то вызывается конструктор этого класса (в данном случае Student3) и внутри конструктора
оверлоадед, который только задает значение String name (оверлоадед –
Создается объект Student3 то есть вызывается конструктор (у вызывается конструктор супер-класса (в данном случае Human3). Вызывается автоматически с помощью ключевого слова super.
вписываешь один String n, он подставляет значение в первый конструктор
этого класса Student3 он сейчас дефолтный) можем его даже Напишем как это выглядит, хотя это происходит автоматически. Super означает обращение к супер-классу. В данном случае у класса
в String name, а в String s подставляет null)
написать, без каких либо параметров. Human3 тоже дефолтный конструктор который ничего не делает. Что происходит.
1) Мы создаем объект класса Student3
2) Вызывается конструктор Student3, Java заходит в тело конструктора.Student3
3) С помощью ключевого слова super вызывается конструктор суперкласса Student3 – Human3.
4) Конструктор Human3 в свою очередь вызывает конструктор своего суперкласса, который мы не видим.
5) И так далее пока не дойдем до конструктора класса Object который суперкласс для всех классов
6) Дойдя до класса object Java начинает спускаться вниз.
Все это направленно на создание единственного объекта – объекта класса Student3, который является объектом и класса Human3 и
класса Object , так как это его прямые (Student3) и косвенные (Object) суперклассы.

4. Пробуем с двумя кастомными конструкторами, которые мы написали в 5. Мы можем создать конструктор super и вписать параметр “Petya” и ошибка 6.Порядок работы конструкторов
начале. Выдает ошибку “no suitable constructor found”. То есть не было исчезает. Java понимает что надо обратится к конструктору с одним String 1) Сначала Java заходит в конструктор Student3 (который с super). В нем вписано одно имя.
найдено подходящего конструктора для Human3. То есть: параметром. 2) Потом заходит в конструктор Human3 (String n) – потому что мы вписали только одно имя
1) В нашем Student3 создается дефолтный конструктор который сначала То есть: 3) Этот конструктор отправляет вписанное имя в свой оверлоадед конструктор (в параметре которого 2 String). В этом конструкторе
обращается к суперконструктору Human3, у которого нет аргументов. 1) Обычно, когда мы создаем объект класса, мы вписываем информацию для Java бай дефолт добавляет обращение к супер-конструктору, в данном случае – к конструктору класса Object
2) Но его суперкласса Human3 есть два конструктора. И из этих двух конструктора в параметрах. Например: 3) После того, как заканчивается тело конструктора Object, конструктор Human3 с двумя параметрами принимает свои значения и
конструкторов нет конструктор без аргументов. Student3 s = new Student3(“Kolya”); его тело заканчивается.
3) Поэтому происходит ошибка компиляции 2) Но если этот класс наследует другой класс, в который тоже нужно ввести 4) Дальше заканчивается тело конструктора Human3 с одним параметром
(у саб-класса конструктор пустой, а у супер-класса - два – с параметрами. информацию для конструктора, то мы вручную создаем для саб-класса 5) Затем заканчивается тело конструктора Student3
Джава не может выбрать ни один, они должны совпадать. Поэтому написание конструктор и используя слово super вписываем значение для конструктора 6) И наш объект s Student3 создан
параметра помогает убрать ошибку) супер-класса
Student3(){
super ("Petya");}
То есть я так понимаю, что можно задать одно такое значение один раз при
создании саб-класса? И оно передастся всем объектам саб-класса? да, но я
так понял, что потом значения инстанс переменных суперкласса можно будет
внести отдельно для каждого, типа s.name

9. Еще один пример. Здесь мы создаем объект Student3. У класса Student3


8. На тестах будет много примеров с вопросами, что выйдет на экран.
7. И ключевое слово this и super требуют, чтобы они находились на есть параметр String. Мы создаем объект и указываем в параметре String
Здесь два конструктора, один с параметром int (с «с аргументами»),
первом месте в теле конструктора, поэтому можно использовать или “ok”.Все отлично.
другой без. Если мы при создании объекта Student3 впишем параметр,
то, или то (не факт, потом был пример в котором сначала был super. а Но Student3 экстендит Human3. А у Human3 есть конструктор, который
то используется конструктор с параметром, если нет, используется
на следующей строчке this. Но в том примере this относился к требует String в параметре. Выбивает ошибку. Поэтому в таком случае нужно
конструктор без параметра. Но конструктор без параметров внутри
переменной в параметре конструктора. Наверное нельзя чтобы был обращать внимание, какой бай дефолт вызывается супер-конструктор
Урок 23 Overriding Hiding Final

Типы reference переменных и объектов

1) Копируем extended
2. Мы можем создать класс main и в нем объекты 3. Но нужно понимать что тип референсной переменной и тип объекта на
классы из другого урока. 4. Все методы employee вызываются в этом случае, а
этих работников. который ссылаетесь могут быть разными. Но есть правила.
Здесь мы видим что “т” класса teacher ссылается на 1) Переменная одного типа может ссылаться на объект того же типа вот методы доктора – нет, компилятор выдает
new teacher. Тип референсной переменной и объекта (обычное создание объекта) ошибку. Компилятор в таких случаях всегда смотрит
на который ссылаемся одинаковый. 2) Супер класс переменная может ссылаться на саб класс объект. (Как на тип данных переменной. Так же с другими
выше – доктор это работник, все ок. Но не наоборот) классами нижнего уровня.

Method overriding

Сразу пример в голову приходит – метод equals. String наследует метод


equals но использует его не обычным способом, а измененным

3. Вписываем метод eat отдельно и в суперклассе, и в


2. В методе main используем метод eat. 4. Запускаем метод main. Выходит 5. Создадим объект класса Employee и выведем его
1. Возьмем тот же класс для примера. сабклассе. Но немного изменил метод eat в суперклассе.
Выводит – «кушать». Все правильно. “Кушает работник”. А в сабклассе teacher пишем – “кушает именно «кушает учитель». метод eat. Ожидаемо на экран выводится “кушает
учитель”. Нет никакой ошибки компиляции работник”. См скриншот. Эти методы называются
overridden.

Методы считаются overridden, если:

1) Имя в саб классе такое же, что и в 2. Список аргументов в саб классе такой же,
супер классе что и в супер классе

1. То есть в нашем примере везде имя метода


должно быть eat. Если назвать у Teacher например
eat2 то получим два раза “кушает работник”. то есть
метод не будет перезаписан.

1. Если у методов одинаковое название, но разные параметры то они не overridden, а overloaded.

В этом примере на скриншотах с параметром int a класс teacher наследует от класса employee метод eat с параметром int а. А
еще у нас есть другой метод eat, в котором есть параметр double b. Это не overridden метода, а overloaded.

3.1) Return type в саб классе такой 3.2) return type в саб классе – это саб класс return type из супер
же, что и в супер классе, или же класса (covariant return type)

1) Создаем в том же проекте еще классы Eda и Frukti. Создаем новые 1) Return type overridden методов может быть и не одинаковым. Но в 2) Нельзя взять Return type какого-то 3) Но для примитивных типов данных должен
методы eat в классах Employee и Teacher, с return type класса Eda (в теле таком случае return type одного overridden метода должен быть левого класса А например. использоваться один и тот же тип (логично –
метода создается объект класса Eda и этот объект в return). Также метода сабклассом другого overridden метода. Как например в этом примере. ведь у примитивных типов нет саб-классов)
перезаписаны в Teacher “кушает учитель”, в Employee «Кушает Есть супер класс Eda, с саб классом Frukti. Мы создаем в классе Employee
работник». Все условия соблюдены, return type одинаковый. метод Eda eat. Теперь создадим его overridden метод в классе Teacher.
Теперь у нас есть два варианта, какой сделать return type. Либо Eda
(такой же return type, как и у первого метода). Либо Frukti, потому что
Frukti – саб-класс Eda. Второй случай называют covariant return type.

5. Метод в саб классе должен быть нон статик


4. Access modifier в саб классе такой же,
или менее строгий, чем в супер классе

1) Если метод в супер-классе 2)Если изменить тело статик метода в


1) Если метод Eda eat public, то и его 2) Если метод Eda eat default, то его overrriden метод Frukti 3) Если метод Eda eat protected, то его нон-статик, то и в саб классе саб классе, то этот метод будет hidden
overrriden метод Frukti eat в саб классе eat в саб классе может быть default или public, или overrriden метод Frukti eat в саб он должен быть нон-статик – об этом позже
тоже должен быть public protected. То есть overriden метод может иметь менее классе не может быть default, потому
строгий access modifier, чем метод в супер классе что default более строгий
Пример с перезагруженными и перезаписанными методами

1) Создаем два класса, Mouse экстендит Animal. А 2) Создаем объект класса test5 и объект класса Mouse c переменной
3) А вот, если бы мы запускали overridden методы an.getName, тогда
потом отдельный класс, у которого два оверлоадед Animal. Запустим метод abc с этой переменной Animal. Что выйдет на
сработал бы run time binding (методы обычные), и в этом случае сработал
метода, которые отличаются тем, что один принимает экран? Интересно. Метод abc перегруженный, есть вариант вставить
бы метод объекта – Mouse.
в параметр объект класса Animal, а второй – Mouse. переменную Animal, или Mouse. Мы вставляем переменную Animal, но
она ссылается на объект Mouse. Я думаю важно, что это все же объект
Animal, поэтому на экран выйдет «А» - сработает перегруженный метод с
параметром Animal. Здесь срабатывает compile time binding, в runtime нет
необходимости – тут an используется как простая переменная, параметр
ожидает переменную этого же типа, все, нет проблем.

Почему private методам не нужен run time biding –


почему срабатывает именно compile time binding

1) Два overridden метода sleep. У employee «спит


2) Нет никакой ошибки компиляции. Проверяем прошел ли 4) Но если метод перезаписан, то вызов этого метода через переменную «е» класса
работник», у teacher – “спит учитель”. Оба метода private.
overriding. Создаем объект teacher через переменную 3) Меняем метод sleep в Teacher на Employee (Employee e = new Teacher();) тоже должен вывести «Spit uchitel» - должен
Teacher и Employeer. И с той, и с той переменной вызвать public, вызываем через переменную сработать run time binding и вывести метод объекта, а объект здесь – Teacher. Но
метод sleep не получилось – он private. класса Teacher – все работает выбивается ошибка компиляции. Потому что для класса Employee метод sleep private.
Значит метод sleep не наследуется классом Teacher – он просто не виден из класса Teacher.
То есть в этом случае мы просто создали новый метод sleep в классе Teacher.

Method hiding
Почему static методам не нужен run time biding – почему
срабатывает именно compile time binding

тот же скриншот, что и 3)

1) Сделаем метод sleep и в Teacher и в Employee 2) Если мы вызовем метод sleep созданный через
static. Нет ошибки компиляции – кажется что мы его переменную класса Employee, которая ссылается на объект 3) Если вызвать метод sleep через
перезаписали. На самом деле нет. класса Teacher (Employee e = new Teacher(); 4) В данном случае происходит не метод overriding, а метод hiding.Это значит, что в классе
переменную класса Teacher, то teacher унаследованный от класса Employee метод sleep (sout “Spit rabotnik”) закрыт вот
e.sleep();) , run time binding не происходит, выводится сработает метод sleep класса Teacher
метод sleep класса Employee – срабатывает compile time этим измененным методом Sleep (sout “Spit uchitel”) – методом с таким же именем и по
– на экран выходит “Spit uchitel” определенным правилам (в данном случае – методом с тем же именем, но с другим телом.
binding. Компилятор смотрит на класс переменной «е» - в
нашем случае Employee и вызывает sleep именно из Полный список правил смотри ниже). В private ни оверрайдинг, ни хайдинг не происходит,
Employee – на экран выходит «Spit rabotnik» потому что эти методы не наследуются.

Когда методы считаются hidden Отличие hiding от overriding

Variable hiding

1) У нас есть переменная double salary 2) Ее можно hide (скрыть) в саб классе Teacher. Например
= 100 в классе Employee. напишем тот же тип данных, но другое значение. double salary =
200; Выводим на экран salary от класса Teacher – выходит 200;
3) Можно даже скрыть переменную
Переменные не могут быть перезаписаны – это называется
переменной другого типа данных.
variable hiding. Переменные могут скрывать другие переменные. И
не обязательно, чтобы они были статик.

annotation @Override
Final method

Конечно и там и там происходит compile time binding – методы не могут быть
перезаписаны, поэтому сразу понятно, к какому классу методы относятся

1) Если мы не хотим, чтобы метод возможно было перезаписать, 2) Если сделать статический метод final, то его нельзя hide. На
то можно назвать его final. Поменяли eat на final в Employee и он в скриншоте метод sleep выдает ошибку уже.
Teacher уже выдает ошибку. Его можно использовать в сабклассе
(потому что он наследуется), но перезаписать нельзя.

Final class

Причины использования

2) перформанс – в этом случве точно будет compile time binding, а


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

+ помним, что конструкторы не могут быть final

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

Если есть саб класс и супер класс. В каждом классе есть перезаписаный метод showName. Мы создаем переменную Мой пример. Если есть саб класс и супер класс. В каждом классе есть перезаписаный метод showName. Мы созда
сабкласса, которая ссылается на объект суперкласса. Какой метод showName где будет задействован? переменную сабкласса, которая ссылается на объект сабкласса(!). Какой метод showName где будет задействова

Пример с дефолт методами и run time binding №2


Пример с дефолт методами и run time binding №1

1. Создаем класс Mouse который экстендит Animal. Метод showName overridden в классе Mouse.

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


Алгоритм работы. переменной а. Наследованный showInfo и перезаписанный ShowName. Значит
они и будут использованы.
(А если пользоваться логикой Заура, то отталкиваемся от объекта –
Фаза компилятора класса Animal: Фаза компилятора класса Mouse: создается объект Mouse, runtime узнает, какой метод наиболее актуален для 2
1) Мы создаем класс Animal и в нем метод ShowInfo и обычный метод showName. 1) Мы создаем класс Mouse, который экстендит класс Animal . Mouse класса Mouse – перезаписанный метод showName – он и вставляется)
2) Java уже сейчас, пока мы пишем, видит, что в метод ShowInfo нужно вставить метод showName. автоматически наследует метод ShowInfo и метод showName. В любом случае на экран выводится «Name of the animal: mouse»
3) Java также видит, что showName – дефолт. И сразу понимает, что нужно использовать run time 2) Мы перезаписываем метод ShowInfo.
binding. Учитывая, что showName - дефолт, а значит его возможно будут перезаписывать, Java 2) Java уже сейчас видит, что метод showName перезаписывает ре
решает, что это может быть не единственный возможный вариант showName, а проверить это можно наследуемый у Angel метод showName. Все еще никакого binding не
только с помощью run time binding. сделано, мы продолжаем ждать run time binding.

Run time фаза:


1) Java видит в psvm, что мы создали Animal a = new Mouse. Java понимает, что мы будем отталкиваться от класса
объекта, который мы создали – Mouse.
2) Java направляется в класс Mouse и смотрит – что есть у этого класса: Наследованный метод ShowInfo и
перезаписанный метод showName .
3) Java вставляет showName в ShowInfo и выводит результат.

Если есть саб класс и супер класс. В каждом классе есть статик метод showName. В сабклассе статик метод Мой пример. Если есть саб класс и супер класс. В каждом классе есть статик ме
showName конечно заслоняет метод showName в суперклассе. Мы создаем переменную сабкласса, которая статик метод showName конечно заслоняет метод showName в суперклассе.
ссылается на объект сабкласса. Какой метод showName где будет задействован? супербкласса, которая ссылается на объект сабкласса. Какой метод showNam

Пример со статик методами и compile time binding №1 Пример со статик методами и compile time binding №

1. Создаем класс Mouse который экстендит Animal. Метод showName теперь Static. И два разных метода ShowInfoAboutAnimal и 1. Второй метод не сработает, потому что переменной а доступны только
ShowInfoAboutMouse. Тут статик методы и два отдельных метода, используется compile time binding. Mouse, инициализированные в классе Animal. Мы можем запуст
showInfoAboutAnimal, а он уже сбайнился с методом showName в к
Алгоритм работы.

Фаза компилятора класса Animal: Фаза компилятора класса Mouse:


1) Мы создаем класс Animal и в нем метод ShowInfoAboutAnimal и статик метод showName. 1) Мы создаем класс Mouse, который экстендит класс Animal . Mouse автоматически наследует уже
2) Java уже сейчас, пока мы пишем, видит, что в метод ShowInfoAboutAnimal нужно вставить метод showName. сбайндившийся метод ShowInfoAboutAnimal и статик метод showName.
3) Java также видит, что showName – статик. И сразу понимает, что можно использовать compile time binding. 2) Мы создаем новый метод ShowInfoAboutMouse, в который тоже надо вставить showName.
Учитывая, что showName - статик, а значит его точно не будут перезаписывать, Java решает, что это 2) Мы закрываем (hiding) наследованный статик метод ShowName новым статик методом ShowName.
единственный возможный вариант showName и сразу подставляет его (байндит) в метод ShowInfoAboutAnimal, 3) Java уже сейчас видит, что новый статик метод showName закрывает наследуемый у Animal статик метод
не дожидаясь run time binding. showName. И учитывая, что метод showName статик, уже сейчас проводит compile time binding, подставляя
showName в созданный в этом классе метод ShowInfoAboutMouse.
4) Тем временем никаких изменений в метод ShowInfoAboutAnimal не вносится – в него уже вставлен метод
showName из класса Animal, он уже сбайндился.

Run time фаза:


1) Java видит в psvm, что мы создали Mouse a = new Mouse. Все связи (binding) уже сделаны на уровне
compile time. Наша переменная Mouse a, значит мы отталкиваемся от класса Mouse
2) Выполняем a.showinfoAboutAnimal. Наша переменная
Java направляется в класс Mouse и смотрит – что есть у этого класса: уже сбайндившийся метод
ShowInfoAboutMouse и уже сбайндившийся метод ShowInfoAboutAnimal.
3) Java выполняет ShowInfoAboutAnimal.
4. Выполняем а. ShowInfoAboutMouse – все точно так же, ShowInfoAboutMouse уже сбайндился,
осталось только выполнить.
Какие элементы доступны переменной суперкласса, которая ссылается на объект сабкласса

Пример 1

2) Срабатывает run time binding. Пользуемся методичкой-алгоритмом, который я написал


4) Среди названных методов, доступных классу С есть только один, инициализированный в классе A:
на полях на прошлой странице.
abc с параметром А (sout A)
Определяем, какие элементы доступны переменной c1. Это переменная суперкласса A,
То есть переменной с1 доступен только этот один метод abc с параметром – объект класса A. Но и объект класса
которая ссылается на объект сабкласса C. То есть с1 доступны все элементы сабкласса C,
B тоже подойдет, потому что класс B это частный случай класса А (B – саб класс A). То есть метод срабатывает и
которые были инициализированны в суперклассе А.
на экран выходит «А».

3) Определяем, какие это элементы. Вот тут осторожно! Внимательно смотри где перезаписанные
методы, а где перегруженные. В этом примере:
1) У класса B метод abc не overridden, а overloaded (overloaded - одинаковое название, разные
параметры, разное тело, overridden - одинаковое название, одинаковые параметры, разное тело).То
есть у класса B есть методы:
• abc с параметром A (sout A)
• abc с параметром B (sout B).
1. Создали класс А, B, C. B экстендит А, С экстендит В. У класса А метод аbc с 2) У класса С метод abc перезаписал метод abc из класса B (название, одинаковые параметры, разное
параметром объект класса А, выводит на экран «А». Класс В перезаписывает класс тело) теперь тут sout C. Но у метода С есть еще overloaded метод abc (A a) (sout A) (overloaded -
А – параметр теперь объект класса В, выводит на экран «В». Класс С одинаковое название, разные параметры, разное тело), унаследованный через класс B от класса А. То
перезаписывает метод abc – все еще в параметре объект класса В, но выводит на есть у класса С есть:
экран «С». • abc с параметром А (sout A)
Создаем объект класса С, с переменной класса А (так можно, С это частный случай • abc с параметром B (sout C).
А). Вызываем метод abc, в который исходя из условий создаем метод B.

Пример 2 Пример 4 – мой эксперимент


Пример 3 – мой эксперимент

В виде эксперимента, рассмотрим задачки с прошлой странички.


Если здесь вывести на экран a.showName. Логика: Animal a = new
Mouse(); доступны элементы класса Mouse, которые были
созданы в классе Animal, но в том виде, в котором они в классе
1. В этом примере мы перезаписали класс abc (A) sout (“a”) в классе B Mouse. В классе Mouse доступны методы showName
(теперь он выводит «BBB»). Разберем, что выйдет на экран теперь. (перезаписанный) и просто наследованный showInfo. Выведется А теперь я хочу этот пример с a, b, c выполнить runtime binding. Что для этого надо? Это уже я в виде
перезаписанный метод showName (mouse) эксперимента сделал такие классы. Что тут доступно классу С?
2. Делаем все точно так же, как и в прошлом примере. Следуем моей методичке-алгоритму. Какие 1) abc (A a) перезаписан в классе B и в таком видео достигает C – просто выводит BBB.
элементы доступны переменной с1? 2) Перезагруженный вариант метода abc (B b1).
• abc с параметром А (sout BBB) 3) И перезаписанный метод inp.
(именно он был перезаписан) Выводится на экран метод abс с параметром B. Конечно больше подходит метод 2 (2)
• abc с параметром B (sout C). Перезагруженный вариант метода abc (B b1).) – у него тоже параметр B. Но этот метод был
Только abc с параметром А был инициализирован в классе А, поэтому именно он и срабатывает, как перезагружен в сабклассе B. Классу А из всех этих методов доступны только abc (A a) и inp. Но abc (A
ив прошлом примере (но метод перезаписан и на экран выходит уже “BBB”) a) подходит, параметр объект B может встать в параметр A, так как B это сабкласс (частный случай а).
Поэтому срабатывает метод 1) – выводит на экран BBB. Все правильно.

Обращение к элементам супер класса, используя key word “super”

То есть если this означает обращение к текущему объекту (классу?), то super – обращение к
объекту родительского класса

Как хайдить переменную из супер класса с помощью ключевого слова super

1) То есть мы создали в новом экстендет классе String s2, которому 2) Например, если мы хотим, чтобы переменная s1 класса A10 равнялась
присвоили значение String s1 из класса А10 + «, друг». Здесь можно было переменной s1+ «, друг!». Пишем s1 = super.c1 + “, друг!”. Напоминает this
и не писать супер, потому что класс B10 просто и так наследует s1. и создание конструкторов. И кстати, это считается, что мы хайдим
Поэтому супер используется в таких случаях когда мы делаем s1 hide. (заслоняем) переменную s1 в сабклассе B10.

Использование ключевого слова super с методами

1. Допустим, хотим перезаписать метод int summa в


2. А можно просто создать массив и каждый элемент
сабкласс B10, чтобы результат еще и выводился на массива вставлять в этот наследованный метод
экран. Ао-первых, что делает метод? В его параметр
summa, используя ключевое слово super.
вставляется массив int, а потом с помощью foreach
(первый int из массива I, + 1 пока не дойдем до
конца). И каждый элемент массива суммируется с
другим, получается сумма. Допустим хотим
перезаписать метод и еще выводить результат.
Можно перезаписать все тело. Но это глупо.

Использование ключевого слова super со статик методами


Еще раз о байндинге (уже от меня по другим источникам – это главная страница по байндингу)

Зачем нужен байндинг

Пример байндинга в обычных классах

1. Забудем на секунду о наследованных классах. У нас есть 2. Допустим у этого обычного класса есть перегруженный
обычный класс. В нем есть переменная и обычный метод. Мы метод. Джава всегда сначала смотрит на параметры и с
создаем объект и компилятор с помощью компайл тайм помощью компилятора определяет, какой из
байндинга определяет, что переменной, которая ссылается на перегруженных методов больше подходит. Все просто.
этот объект соответствуют эта переменная и метод.

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

Пример байндинга в экстендет классах, если в классах перегруженные методы

Superclass t1 = new Superclass () Subclass t2 = new Subclass () Superclass t3 = new Subclass ()

1. Теперь мы добавляем экстендет класс. Этот экстендет 2. Логично, что объект суперкласса не сможет увидеть 3й вариант
класс наследует два перезагруженных метода абс и 3. Объекту сабкласса в свою очередь доступны все три метода, 4. Но мы можем также создать переменную типа данных суперкласса,
перезагруженного метода в сабклассе. Этот третий вариант
дописывает еще один перезагруженный метод абс. два наследованных перегруженных варианта метода, и один которая ссылается на объект сабкласса.
создан в сабклассе, его не видно в суперклассе. Выбивает
перегруженный вариант уже в сабклассе. Это тоже понимает В таком случае опять же срабатывает компайл тайм байндинг и по
ошибку. Опять же компайл тайм определяет, что объекту
компайл тайм, просто обращая внимание на параметры. параметрам методов Джава решает, что этой переменной доступны
суперкласса доступны первые два перезагруженные методы, а
сабклассу три перезагруженных метода. только перегруженные методы, доступные в суперклассе.

Вывод: В этом примере в экстендент классах используются только перегруженные методы. Опять же, с помощью параметров можно легко решить,
какие методы мы имеем в виду. Поэтому используется компайл тайм байндинг – отталкиваемся от типа данных переменной.

Пример байндинга в экстендет классах, если в классах перезаписанные методы

Superclass t1 = new Superclass () Subclass t2 = new Subclass () Superclass t3 = n

1. В этом примере у нас тоже экстендет класс. Но теперь в 2. Создаем объект суперкласса и вызываем его метод. Вот 3. Создаем объект сабкласса и вызываем его метод. Опять
экстендент классе метод не перегружен, а перезаписан. То здесь у джава появляются проблемы. Использовать же - у джава появляются проблемы. Использовать 4.1 Здесь создаем переменную типа данных суперкласса, которая ссылается на
есть параметры у этих методов одинаковые. компайл тайм байдинг не получится – у обоих методов компайл тайм байдинг не получится – у обоих методов объект сабкласса. Вызываем метод, отталкиваясь от этой переменной. Как и в
одинаковое количество параметров, не понятно, какой одинаковое количество параметров, не понятно, какой предыдущих примерах, джава по параметрам не может узнать какой из
метод из двух перезаписанных вариантов мы вызываем. метод из двух перезаписанных вариантов мы вызываем. перезаписанных методов выбрать. Поэтому используется рантайм метод. Джава
Здесь джава дожидается рантайм байндинга. Джава Здесь джава дожидается рантайм байндинга. Джава отталкивается от объекта – в данном случае сабкласс. Но в данном случае
отталкивается от созданного объекта – здесьэто отталкивается от созданного объекта – здесьэто сабкласс. переменной будут доступны только элементы, которые доступны в сабклассе и
суперкласс. И смотрит, какие элементы доступны этому И смотрит, какие элементы доступны этому сабклассу. инициализированы в суперклассе.
суперобъекту. Только вариант метода, записанный в Только вариант метода, записанный в сабклассе. Вот он и Какие элементы доступны сабклассу? Только метод перезаписанный в сабклассе.
суперклассе. Вот он и используется. используется. Он был инициализирован в суперклассе? Да! значит используем его.

Вывод: В этом примере в экстендент классе метод перезаписан. Количество параметров у метода одинаковое, поэтому джава для байндинга не может использовать компайл тайм – нужно использовать рантайм. При рантайме мы отталкиваемся от
объекта, смотрим какие элементы доступны объекту (если переменная суперкласса, то оставляем только те элементы, которые были инициализированны в суперклассе) и используем эти объекты

Пример байндинга в экстендет классах, если в методе статик

1. Создаем статик объект в суперклассе. Статик метод не ассоциируется с 2. Используем статик метод в psvm. Нам даже не нужно 4. Мы не можем перезаписать этот статик метод в сабклассе. По логике джава, этот метод
3. Сабкласс наследует этот статик метод, это
определенным объектом, статик элемент принадлежит классу, его создавать объект – это статик метод. Все работает. принадлежит классу, а значит и сабклассу, который его наследует. А значит и всем объектам
тот же скриншот. Сабкласс может точно так же
принято вызывать без объекта (можно и с объектом, но учитывая, что сабкласса. Смысл статик метода в том, чтобы не быть индивидуальным, а сохранять внесенные в
без объекта вызывать этот статик объект.
статик элемент принадлежит классу, его принято вызывать через класс – него изменения. Проще будет, если представить, что это статик переменная – в отличии от обычных
test10.abc). А если статик элемент принадлежит классу, то его нельзя переменных, которая может принимать разные значения для разных объектов, статик переменная
перезаписать – «перезаписывание (overriding) и polymorphism в целом одна на весь класс и она запоминает все изменения, вне зависимости от класса. По логике джава
напрямую связаны с созданием объектов – в зависимости от типов нет смысла ее задавать по разному в сабклассе.
объектов вызываются те, или иные методы. А само понятие static не Но, у джава все же есть такое понятие как хайдинг. В сабклассе можно переписать этот статик метод
подразумевает под собой создание объектов». А если его нельзя с измененным телом, если его параметры такие же. Это не считается перезаписанным методом,
перезаписать, то Джава считает, что это его окончательное значение. измененный метод как бы заслоняет в сабклассе оригинальный статик метод.
В итоге для суперкласса значение этого статик метода оригинальное (если вывести этот метод через
суперкласс, на экран выйдет соут А)
А для сабкласса значение этого статик метода заслоненное (если вывести этот метод через
сабкласс, на экран выйдет соут Б)
И все это конечно определяется компайл тайм.

Superclass t1 = new Superclass () Subclass t2 = new Subclass () Superclass t3 = new Subclass ()

5. Так обычно не делают (это считается плохим тоном), но статик


переменные также можно вызывать через объект, указав название
6. Создаем объект суперкласса через переменную суперкласса. 6. Создаем объект сабкласса через переменную сабкласса.
переменной. В этих случаях конечно важна не переменная (статик 7. Создаем объект сабкласса через переменную суперкласса. .
Вызываем через эту переменную статик метод. У методов Вызываем через эту переменную статик метод. У методов
классы создаются не для объекта, а для класса), а класс (дописать) Вызываем через эту переменную статик метод. У методов 8. Здесь
одинаковые параметры. Но тут нет перезаписи (по умолчанию с
одинаковые параметры. Но тут нет перезаписи (по умолчанию с одинаковые параметры. Но тут нет перезаписи (по умолчанию с сабкласс
статик методами нет перезаписи). Поэтому тут уже произошел статик методами нет перезаписи). Поэтому тут уже произошел
байндинг – компайл тайм. Компайл тайм отталкивается от типа статик методами нет перезаписи). Поэтому тут уже произошел Создаем об
байндинг – компайл тайм. Компайл тайм отталкивается от типа байндинг – компайл тайм. Компайл тайм отталкивается от типа Опять ком
данных переменной – это суперкласс. Суперклассу соответствует данных переменной – это сабкласс. Сабклассу соответствует
оригинальная версия метода. Выводится «A». данных переменной – это суперкласс. Суперклассу соответствует суперкла
заслоняющая версия метода. Выводится “B” оригинальная версия метода. Выводится “A”

Вывод: Статик методы вызываются обычно через класс, а не через объект. Мы не можем перезаписать статик метод по определению, только заслонить. Если метод заслонен в сабклассе, то джава
компайл тайм легко определяет, что суперклассу принадлежит оригинальный статик метод, а сабклассу принадлежит заслоняющий статик метод.
И хоть это и плохой тон, но можно вызывать статик методы через объекты. В таких случаях помним,что здесь работает компайл тайм байндинг. А значит нужно отталкиваться от переменной – какому
классу принадлежит тип данных переменной, его метод и использовать. (почему это работает именно так я не нашел объяснение, сам механизм, поэтому пока просто запомнить как правило)

Пример байндинга в экстендет классах, если в методе privat

Superclass t1 = new Superclass () Subclass t2 = new Subclass () Superclass t3 = new Subclass ()


Урок 24 Абстрактные Дефолтные Статические методы

Интересные примеры к прошлой теме

1. Если сделать метод main final, то его


функциональность не поменяется. Просто потом не
получится оверрайдить или хайдить метод main

2. Еще пример. В классе A есть переменная String s и метод abc. Здесь класс B
хайдит String s и перезаписывает метод abc. Именно это наследует класс s. В
методе main объект и переменная s. Поэтому на экран выводит именно скрытый и
перезаписанные версии переменной и метода.

abstract классы и abstract методы

1. Есть класс Figura, у которого int kolichestvostoron, методы perimetr, ploshad. Класс Figura экстендится классами Kvadrat, Pryamougolnik и Okrujnost. Но в
любом случае эти элементы в экстендет классах придется хайдить, или перезаписывать. Почему? Потому что для этих фигур нет одинаковой формулы 2. Тогда можно перед словом Figura добавить слово abstract. Это не access modifier, на видимость не
для площади, периметра . То есть класс Figura здесь знает, что эти методы должны быть, но не знает, как они работают. Figura здесь это категоризация – влияет. Сразу скажем, что еще есть абстрактные методы – методы perimetr и метод ploshad– мы не
в реальности ее не существуют. Если говорят “нарисуй фигуру “– вы нарисуете или квадрат, или круг, или прямоугольник. Figura здесь не конкретное знаем, как их узнавать, не знаем, что в них писать, дописываем abstract перед ними.
понятие, а абстрактное и мы не хотим, чтобы объекты типа Figura могли быть созданы.

Особенности abstract классов и abstract методов

1) У абстракт методов не бывает тела 3) Если в классе есть абстракт метод, то этот
2) Невозможно создать объект abstract класса 4) абстракт класс может содержать, а может и не содержать абстракт методы
класс тоже должен быть абстракт

5. Если у класса есть абстрактный метод, то этот класс тоже


1. Раз тела абстрактных методов неизвестны, то должен быть абстракт. Если убрать абстракт у класса 1. Абстракт класс может содержать, а 2. У абстрактного класса могут
можно вообще не писать тела – удаляем фигурные 1. Для абстрактного класса нельзя фигура, абстрактные методы выбьют ошибку. может не содержать абстракт методы. быть обычные методы.
скобки. Появляются ошибки компиляции у саб создать объект – выбьет ошибку.
классов. Сейчас объяснит почему.

5) Дочерний класс должен перезаписать все абстракт методы родительского


класса или тоже быть абстракт

1. Саб класс должен перезаписать все абстрактные методы


суперкласса, или тоже должен быть абстракт. Тут логично – 2. Перезапишем также оставшиеся сабклассы.(он
абстракт методы могут быть только в абстракт классах, а потом тоже добавил количество сторон классу 3. Создаем класс Chetirehugolnik. Создаем класс def, который
сабклассы наследует эти абстракт методы. Вот на квадрат, хотя это ни на что не влияет) выводит на экран «Это четырехугольник». Допустим, мы не знаем,
скриншоте мы перезаписали ВСЕ абстрактные методы как будут выглядеть периметр и площадь у четырехугольника, 4. Сабкласс абстрактного класса может перезаписывать или не
супер класса (конечно нужно перезаписывать все поэтому мы не хотим перезаписывать методы суперкласса. перезаписывать элементы, мы уже это обсудили, суперкласса.
абстрактные методы, иначе они останутся абстрактными) Поэтому можно сделать метод четырехугольник тоже абстракт. И Если не перезаписывает – называется абстрактным классом. Если
перезаписывать не надо, иначе была бы ошибка компиляции. То перезаписывает – называется конкретным классом (то есть
есть сабклассы абстракт метода тоже могут быть абстракт, если в нем нет абстрактных методов).
мы не хотим их перезаписывать.

6) Можно использовать переменную абстракт класса, чтобы ссылаться на объект дочернего не абстракт класса 7) Переменные не могут быть абстракт 8) У абстракт классов есть конструктор

1. Легко – создали объект не абстракт 2. Но, конечно же, нужно пользоваться правилами байндинга. Например, если
1. Переменные не могут быть абстракт. Абстракт это 3. У абстракт классов есть конструктор, видим по
класса, на который ссылается переменная вызываем f1.количество сторон. Пользуемся моим алгоритмом. Какой тип
только класс или метод. примеру, что все работает, не смотря на то что объект
абстракт класса. Это саб и супер классы, данных? Инт, примитивный. Значит компайл тайм байндинг, отталкиваемся от
класса фигура не может быть создан.
конечно так можно. типа данных класса переменной – Figura f1. Значит f1.kolichestvostoton – 0.
Проверяем ф1.площадь. Пользуемся моим алгоритмом. Это метод. Проверяем -
он перезаписан. Здесь произошел рантайм байндинг, сработал метод из класса
Фигура, отталкивались от объекта квадрат. Получаем 500.

9) Любой перезаписанный метод может 10) Для методов недопустимо сочетание: final
14. Абстрактный класс может
быть как абстракт, так и не абстракт abstract, private abstract, static abstract 13) Абстрактный класс не может быть final
экстендить конкретный класс.

1. Для методов не допустимо сочетание final abstract,


interface

Интерфейс в 7-й и 8-й версии отличаются. Сначала рассмотрим что такое интерфейс в 7-й версии, потом какие отличия появились в 8-й

1. Есть класс Employee. Есть Teacher, который экстендит Employee. И класс Driver, который 2. Interface пишем как class при создании класса,
экстендит Employee. Пришло распоряжение, что и учитель и водитель должны уметь потом пишем имя интерфейса. Добавляем метод
тушить пожар и оказывать медицинскую помощь. А водитель еще и уметь плавать. Если мы оказания помощи и тушить пожар. В методах нет 3. Создаем еще один интерфейс – умение плавать. То 4. Теперь нужно к Teacher применить интерфейс Help_able. Пишем перед
все это добавим в Employee то учитель тоже будет уметь плавать. Может можно сделать тела. Потому что интерфейс может содержать только есть по факту интерфейс это возможность дописать в началом нужно класса «implements Help_able». Сразу выбивает ошибку.
отдельный класс и сделать от него экстендс на отдельные классы? Нет нельзя, потому что абстрактные методы. Тут можно не писать перед отдельные наследуемые классы какие-то методы (и Потому что класс Teacher сейчас наследует абстрактный элемент (по сути
Teacher и Driver может экстендить только один класс. Можно конечно еще вручную это классом abstract - джава и так это понимает (можно и может еще другие элементы) интерфейс это как абстрактный класс (иногда называют абстрактным
вписать. Но есть лучше способ. В этих моментах помогает интерфейс. написать, но нет необходимости) классом до мозга костей – хотя интерфейс это все же не класс), но не
перезаписывает его методы. Поэтому сейчас есть два варианта. Либо
перезаписать методы интерфейса в классе Teacher. Либо объявить класс
Teacher абстрактным.

5. Для примера объявляем класс Teacher


abstract – ошибка компиляции исчезает.
7. Перезаписываем метод, но компилятор опять ругается. Потому что бай дефолт все
8. Перезаписываем еще и второй метод. Все, все методы
методы интерфейса имеют public access modifier. Поэтому нужно перезаписанному
перезаписаны, ошибка компиляции класса Teacher исчезла –
методу дописать public . Ошибка, потому что мы назначаем более строгий access
все абстрактные методы перезаписаны.
modifier наследованному методу (был private – стал default)

Паблик абстракт можно не


писать, он пишет это в
интерфейсе за тебя сам.

9. Естественно класс Teacher может имплементировать 10. Класс Driver должен имплементировать два
интерфейс, даже если он не экстендит класс Employee. Но интерфейса: Help_able и Swim_able. Записываем
если экстендит, то сначала надо писать экстендс, а потом - названия интерфейсов через запятую после
имплементирует слова implements.. То есть класс может
имплементировать какое хочешь количество
интерфейсов. Перезаписываем все методы
интерфейса. Задача выполнена.

Одно из больших преимуществ интерфейса – возможность multiple inheritance – множественной наследовательности. Потому что если мы создадим два интерфейса с одинаковыми методами
абс() и абс (), наследуя из интерфейса в одном классе их придется обязательно перезаписать, а чтобы было два метода с одним названием в одном классе, эти методы еще и придется
перезагрузить (вписать разные параметры) и ошибки не будет. Это контракт, если интерфейс наследуется, то объект обязан выполнить его методы, обязан переписать эти методы и выполнить.
И третье – мы говорим что нужно сделать, но мы не говорим как (метод без тела нужно перезаписать и указать как его выполнять, так как это абстрактные методы).

некоторые особенности interface

1) Невозможно создать объект 3) Access modifier у всех топ-левел 4) Если не указать самостоятельно, то компилятор
2) У интерфейса нет конструкторов
интерфейса, потому что это не класс интерфейсов или public, или default добавит в определение интерфейса слово abstract

1.У нас был интерфейс Help_able – попробовали 1. Интерфейс может быть default, если не пишем ничего, или public. Здесь public выдает
создать объект как класса – выдает ошибку. ошибку, потому что есть правило что может быть только один класс private в файле. В этом
1. Попробовали создать – выдает ошибку
файле уже есть private class test3. То есть это правило действует и на интерфейсы, хоть это и 1. Но можем и не писать, компилятор сам это добавит
не класс. И файл должен называться как паблик класс или как паблик интерфейс

6) Если не указать самостоятельно, то компилятор


добавит в определение всех non-default (не access 7) Методы интерфейса не могут быть final 8) Если класс, который имплементировал интерфейс, не перезаписал
5) Интерфейс не может быть final
modifier) и non-static методов слова abstract и public все его методы, то этот класс должен объявляться абстракт

Конечно, они же перезаписываются

1. Уже говорили раньше

1. Логично, ведь его должны имплементировать 1. Поэтому при имплементации нужно дописывать паблик

9) Из переменных в интерфейсе могут быть только константы, которые были в нем инициализированы. Если не указать 10) Логично, что если метода интерфейса есть параметры, то у перезаписанных методов в классах
самостоятельно, то компилятор добавит в определение всех переменных слова public final static тоже должен быть тот же параметр – при перезаписи методов параметры должны быть одинаковы
interface i1 = new class ();

1. Хоть интерфейс и не класс, и объект создать нельзя, но


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

3. То же самое можно сказать и про интерфейсы. Можно с помощью h 4. С помощью h можно вызвать методы, которые
2. Вспоминаем создание объекта по типу: переменная суперкласса Employee “e”
вызвать переменную int a из интерфейса (потому что это инт, driver оверрайдит из интерфейса Help_able (потому
ссылается на объект сабкласса Driver. С помощью переменной “е” можно примитивный тип данных, компайл тайм байндинг, отталкиваемся от
обращаться только к элементам Driver, которые есть и в классе Employee тоже. что тут рантайм – отталкиваемся от объекта - driver).
типа класса переменной). Но нельзя с помощью h посмотреть salary (тоже Это методы помощь и тушить пожар.
Например здесь в том числе вызовутся методы eat и sleep. И если они примитивный тип данных double и тоже компайл тайм байндинг).
перезаписаны в классе Driver, то вызовутся именно перезаписанные версии. Почему? Потому что компилятор проверяет, h к какому типу относится?
Потому что это определяется рантайм.
Help_able. В Help_able есть константа salary? Нет. Все, нельзя вызывать.
Точно так же нельзя вывести с помощью h название машины. Тоже самое
компилятор проверяет и не находит.

6. Таким образом на объект класса может ссылаться:


1) переменная такого же типа что и сам объект,
1) типа его суперкласса
3) типа интерфейса, которые этот класс созданного объекта
имплементирует.

Можно провести параллель – все что есть в суперклассе есть в


сабклассе (все что наследуется). И все что есть в интерфейсе есть в
классе который его имплементирует. Поэтому не надо удивляться что
можно создать Swimable s = new Driver(); Так можно потому что
поддерживается is a отношения. Можно сказать, что «водитель это –
способный плавать»

5. С помощью h нельзя вызвать метод eat который драйвер


наследует от Employee. Или vodit. Потому что этих методов
компилятор не находит в переменной типа h. А переменная
типа h это интерфейс helpable. 6. Таким же образом можно вызвать с помощью
переменной s интерфейса Swim_able только swim –
единственный метод интерфейса.

Пример с типом данных Jumpable

1. Создаем два класса, у которых отношения не is a. Human 2. Например интерфейс jumpable, который оба имплементируют.
это не Animal и Animal это не Human. С помощью какого-то Тогда можно создать jumpable 1 = new human и jumpable 2 = new
интерфейса можно сблизить эти классы. Например. human . Оба прыгающие, все логично.

Если класс имплементирует два интерфейса, в


которых методы с одинаковым названием

1. Тут все ок, в методе который имплементирует 2. Здесь не пойдет, потому что единственное отличие в return type,
методы перезагружены, так как разные параметры. параметры одинаковые. Внутри класса, который имплементирует
интерфейс, методы интерфейса, если у них одинаковое имя, должны
оверлоадиться. А так оверлоадить нельзя, параметры должны быть
разными. Поэтому если класс имплементирует два интерфейса, у которых
два метода с одинаковыми именами, чтобы потом не было ошибки,
нужно у этих методов использовать разные параметры

особенности наследования интерфейсов,


абстрактных классов и конкретных классов

Класс может наследовать 0 или 1 класс. Для наследования класс


использует ключевое слово «extends»

Интерфейс может наследовать 0 или более интерфейсов. Для


наследования интерфейс использует ключевое слово «extends»

Интерфейс может наследовать интерфейсы, причем множество.

Класс может имплементировать 0 и более интерфейсов. Для


имплементации класс использует ключевое слово «implements»

Класс не может наследовать интерфейс

Нельзя написать, класс extends интерфейс

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


имплементировать интерфейс

Абстрактный класс может наследовать конкретный или абстрактный класс и


имплементировать интерфейс

Абстрактный класс может имплементировать интерфейс тоже. Например abstract class D имплементирует A2 и B2. Он может:
1) не оверрайдить методы этих интерфейсов и остаться абстрактным
2) может оверрайдить какой-то из них и не оверрайдить остальные – класс все еще остается абстрактным
3) А может соверрайдить все и перестать быть абстрактным.
В данном примере, кстати, можно не имплементировать интервейс А2, потому что B2 экстендит A2 (то есть В2 содержит все что есть в А2) Если вдруг появится
класс Z который экстендит D, он может один или несколько методов оверрадить, но если он соверрайдит не все, то он тоже должен стать абстракт. Класс который
оверрайдит все абстрактные методы – он уже не пишет абстракт перед собой – он конкретный. Все очень логично

Первый конкретный класс в иерархии должен снабдить все абстрактные


методы телами

Первый конкретный класс должен перезаписать все абстрактные методы интерфейса.


Изменение в интерфейсах в джава8

default методы в интерфейсах

1. Главная особенность, что дефолтный метод из интерфейса


2. Если убрать тело, то Java думает, что это 3. Зачем это изменили в java8? Допустим есть интерфейс и 100 классов,
можно не оверрайдить . Конечно можно и оверрайдить. То есть 4. Поэтому теперь возможен такой хитрый ход – можно этот абстрактный
абстрактный метод, зачем ему тело? которые имплементируют этот интерфейс. И вдруг, нужно добавить в этот
здесь мы его не оверрайдили и компилятор не ругается. Другими метод сделать дефольтным, снабдить его телом, и оверрайдить этот
Выдает ошибку интерфейс какой-то один метод, скажем, void ghi. И теперь придется во
словами, в отличии от абстрактных методов, дефолтные методы метод только в 10 классах, где нужен этот ghi – сделать его таким, как нам
всегда имеют тело! всех 100 классах оверрайдить этот ghi, он же абстрактный. А этот метод нужно. А остальные 90 классов, которые имплементируют интерфейс,
ghi нужен только в 10 классах, допустим. могут этот метод не трогать. (то есть этот дефолтный метод
перезаписываем там где нам надо, а не везде, как было с абстрактным)

5. Видим, что в классе Z2 можно не перезаписывать дефолтные методы ghi и def, 6. Но если хотите оверрайдить эти дефолт методы, то нельзя написать default void ghi и
перезаписать нужно только абстрактный метод abc. новое тело метода, хоть это и было бы логично.
Создаем метод main, создаем в нем объект Z2 и через переменную этого объекта Access modifier дефолтных методов при перезаписи – паблик. То есть как и с перезаписью 7. Вообще, можно дописать public и перед default перед названием дефолтного
можем вызвать и abc и def и ghi. Все методы вызвались, хоть мы и не обычных абстрактных методов из интерфейсов, при перезаписи дефолтных методов из метода в интерфейсе. (в данном случае default это не access modifier, а
оверрайдили ghi и def – они вызвались в дефолтной реализации. интерфейса нужно обязательно писать public. Важно! В случае с перезаписью дефолтных обозначение, что это default метод, а access modifier здесь public , но Java
методов нужно еще и убирать слово default, по сути просто меняем default на public. дописывает это автоматически – смотри ниже)

privat и final – очевидно почему. а со статик там есть


особенность, которую он чуть позже расскажет.

Интересный пример

3. Этот интерфейс также может сделать так, чтобы этот


2. Этот интерфейс может оверрайдить и переписать дефолт метод наследованный дефолтный метод стал абстрактным. если сделать
1. Есть интерфейс с дефолтным методом. Есть
так, то все классы, которые имплементируют i2 будут вынуждены
интерфейс, который экстендит этот интерфейс.
уже оверрайдить abc

5. Но может и оверрайдить (не забываем 6. Или сделать этот метод абстрактным (класс же
4. То же касается абстрактных клаcсов. Класс R конечно же абстрактный, так что ошибки не будет)
писать public и убирать default).
наследует дефолт метод из интерфейса I2. Может не
перезаписывать дефолт метод интерфейса.

Пример

interface I1 {
default void abc(){System.out.println(“I1”);}}

interface I2 {
default void abc(){System.out.println(“I2”);}}

interface I3 {
void abc();}

a) class Test1 implements I1, I2{} b) class Test2 implements I1, I3{}

Тут мы имплементируем интерфейсы I1 и I2. Тут мы имплементируем интерфейсы I1 и I3.


В обоих интерфейсах написаны дефолтные В интерфейсе написан дефолтный методы
методы abc с одинаковыми параметрами. abc, в другом – абстрактный метод abc. У
Здесь компилятор уже выбьет ошибку - методов одинаковые параметры.
потому что не будет знать, метод какого из Здесь компилятор уже выбьет ошибку -
интерфейсов перезаписывать. потому что не будет знать, метод какого из
интерфейсов перезаписывать.

a) class Test3 implements I1, I2{ a) class Test4 implements I1, I3{
public void abc () public void abc ()
{System.out.println(“Test3”); } } {System.out.println(“Test4”); } }

Но если мы в классе оверрайдим метод abc без параметров, то мы оверрайдим оба унаследованных метода
abc без параметров. И тогда компилятор понимает, что он не будет использовать ни ту ни ту версию, а тут
которую сам сейчас изменил. То есть класс Test3 унаследовал 2 метода abc с одинаковыми параметрами и в
итоге оверрайдил оба этих метода, оставив только последнюю версию (в классе может быть только один
метод с одними и теми же параметрами)
Static методы в интерфейс

Тоже новое в java8.

1. Похоже на обычный статик метод в классах. Но есть отличия. Нельзя вызвать в методе 2. Поэтому можно обращаться к статическому методу
main метод def ни просто по названию, ни через имя класса, как можно было с обычными только через название интерфейса. Тут тоже есть привязка
статик методами. Почему? Потому что даже учитывая, что R имплементирует I1, нельзя вот к одному элементу, но этот элемент не класс, а интерфейс.
так вызывать статический метод. Статический метод не наследуется из интерфейса в класс,
чтобы можно было к нему обращаться по имени класса, не считается, что этот статический
метод принадлежит классу (логично, этот статический метод тогда принадлежал бы всем
классам, которые имплементировали бы этот интерфейс. В этом нет смысла, идея
статических элементов в том, чтобы они были привязаны к чему-то одному и сохраняли
внесенные в них изменения вне зависимости от объектов(обычно это привязка к классу, но
тут не так))

3. Причем можно обращаться к статическому методу


интерфейса через название интерфейса, даже если не
класс не имплементирует интерфейс. Но здесь уже играет
Access modifier для статик методов в
роль область видимости. То есть если интерфейс имеет
интерфейсах, как и для всех методов, public
дефолтный модифаер и находится в другом пакете, то
конечно его не будет видно классу R

Еще пример

В этом случае класс R может без проблем имплементировать и I1 и 12. Почему? потому что в любом
случае перед тем как вызвать метод, нужно будет указывать имя интерфейса, которому принадлежит
этот статик метод, поэтому путницы из-за одинаковых параметров не возникнет

Еще момент

Еще момент. Если мы что-то импортируем, то короткое имя можно использовать и


в интерфейсах, и в классах. (кажется и так было очевидно)

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


type, и в параметре. Главное помнить, что с чем имеет is-a отношение

1. переменная может быть любого примитивного типа данных, типа класса (как 3. А может быть в return type какой-то абстрактный класс.
абстрактного, так и конкретного) и еще сегодня добавилось - типа интерфейса. 2. А может быть return type класса R Может быть как на скриншоте – создали абстрактный
(пример про Jumpable j1 = new Human();) класс. Создаем метод типа данных О в классе R который
То же самое касается и return type методов. экстендит О и в return type пишем объект R – это
То есть сейчас на скриншоте у метода return type - void справедливо, потому что R экстендит О.

4. Если класс имплементирует интерфейс, то можно создать метод типа 5. Также, любой тип данных можно использовать в параметрах метода.
данных интерфейса (причем в return type может быть класс который Например – переменную типа данных интерфейса.
имплементирует этот интерфейс. Помним про отношения is-a)
Урок 25. Полиморфизм. Оператор «instanceof»
Дословный перевод слова «полиморфизм» - множество форм.
Полиморфизм – это способность объекта принимать несколько форм.

Полиморфный объект Полиморфный метод

Когда объект имеет более 1 связи IS-A Когда один метод ведет себя по разному, в зависимости от того, объект какого класса его
вызывает. Перезаписанные методы также часто называют полиморфными

Пример полиморфизма с обычными классами


Пример полиморфизма с интерфейсами

1. Abstract parent class Employee, сабклассы


2. В методе main создаем 3 переменные, которые
перезаписывают метод Eat.
ссылаются на объекты сабклассов и вызываем через 1. Пример полиморфизма с интерфейсами. 2. Но, если сделать, чтобы класс Employee
них методы work. Из-за того что методы Интерфейс имлементируется классом, можно имплементировал интерфейс, то все сабклассы
перезаписаны, сработал рантайм байндинг, все сделать тип переменной интерфейса, которая Employee получат метод из интерфейса. И конечно
методы сработали по разному. ссылается на объект класса. Но метод Work уже переменные этих сабклассов, которые ссылаются на
не сработает, его нет в интерфейсе. Employee смогут вызывать метод из интерфейса.

Интересный пример со статической переменной


Пример полиморфизма с массивами

5. Пример с массивами. Мы можем создавать массивы примитивных 1. Статическая переменная. Можно вызывать без оьъекта, но здесь
типов данных и референсных типов данных. Массивом референсных 6. Можно еще записать так и вызвать метод work для вызовем с объектом. Все работает. А теперь ссылаем на null (то есть эта с
типов данных могут быть массивы конкретного класса, абстрактного каждого объекта через foreach. Это классический пример на объект уже не ссылается). Вызываем снова с через переменную а, и на
класса, или интерфейса. объяснения полиморфизма. В зависимости от того, какой удивление все срабатывает снова. Почему сработало? Потому что это
array1 Driver– в массиве только конкретные объекты Driver. Driver “is a” объект сработает, то тело метода и срабатывает статик объект, он принадлежит классу, здесь объект с не проверяется,
Driver проверяется какому классу этот объект принадлежит
array2 Employee – в качестве элементов объекты Driver, Teacher,
Doctor(потому что Driver, Teacher, Doctor «is a» Employee . Нельзя создать
объект Employee потому что класс Employee абстрактный.
array3 Help_Able – элементы объекты всех классов, которые
имплементируют интерфейс Help_Able – они «is a» Help_Able ).
То же самое можно было бы сделать с ArrayList. Оператор instanceof

Car c = new Car();


System.out.pryntln(c instanceof Object);

Имеется в виду, является ли “C” объектом класса Object (все классы наследуют
object). Выводится на экран true. Это boolean оператор, который помогает
определить, является ли объект объектом какого-то класса. Другими словами,
есть ли между этим объектом и классом отношение «is a»

Пример

3.Мы создали String c1, но потом сослали 4. Даже если так написать то выбьет
c1 на null. Поэтому instanceof говорит что ошибку, потому что null это ничто.
2. Компилятор не разрешает null это не String, значит false. 5. А так – array2 это 6. “O” это teacher? нет, false. потому
так написать. Потому что объект? да, объект. что не каждый object это teacher. Но
1. Проверяем на предыдущем
компилятор знает, что test1 и каждый teacher это object .
примере. Да, работает
emp1 не могут быть связаны.

Пример, как компилятор знает, какие элементы можно


сравнивать с помощью instanceof, а какие нет

1. If выводит на экран “J is Jumpable”, если J instanceof Jumpable, и “M is Jumpable”


2. Пишем третий пример, if (s – instanceof Human). Но компилятор так не разрешает. Тут тонкий момент. Конечно, можно чтобы S ссылался
если M instanceof Jumpable.
Jumpable J = new Man. В таких случаях при проверке смотрят на сам объект, не на на сабкласс Student. Какой сабкласс – компилятор не может проверить. То есть компилятор знает, что S ссылается либо на Student, либо
на какой-то сабкласс Student(если он есть). (Потому что переменная может ссылаться либо на свой класс, либо на сабкласс, либо в случае
переменную, то есть в данном случае – на Man. Man имеет отношение к
интерфейса - на класс (или его сабкласс) который имплементирует этот интерфейс). Но невозможно, чтобы этот гипотетический сабкласс
Jumpable? Да, потому что Man extends Human, а Human implements интерфейс
Student имел супрекласс Human. Потому что у него уже есть суперкласс Student . А два суперкласса у одного класса быть не могут. То есть
Jumpable , то есть Man наследует через Human Jumpable . То же самое с M и
есть два шанса, чтобы instanceof сработал. Если переменная ссылается на объект с которым сравнивают instanceof (Human h1 = new
Human, в итоге обе строчки выходят на экран.
Human). Или если переменная ссылается на сабкласс объекта с которым сравнивают instanceof (Human h1 = new Man, а мы сравниваем
h1 instanceof Human) Но в данном случае еще до запуска компилятор видит, s может ссылаться на Student, или на сабкласс Student.
Student точно не равен Human, а сабкласс Student не может быть сабклассом Human(может быть только один сабкласс у класса, если это
Student , то это Student , не может быть и Student, и Human) То есть компилятор даже до запуска сразу понимает, что s не может быть
Human. То есть между этими элементами никакой связи “is a” быть не может.

4. Еще один хитрый момент. Мы сразу видим, что Jumpable не может быть Student( Student не имплементирует Jumpable и не является
сабклассом класса, который имплементирует). Но как думает компилятор. Student s может ссылаться на Student и на сабкласс Student . И
компилятор не видит, имплементировал ли сабкласс интерфейс Jumpable . Он видит, что сам студент не имплементировал, но имплементировал
ли сабкласс – не факт.
(важный момент! компилятор все эти выводы делает через того, какая переменная стоит перед instanceof . То есть компилятор не знает, с каким
объектом мы сравниваем. Но знает что с s может стоять либо Student, либо саб класс Student. И каким-то образом знает, имплементирует ли
Student или суперклассы студент интерфейс Jumpable . но не знает, имплементирует ли интерфейс сабкласс Student. Что видит компилятор а что
нет – это не понятно, какая тут логика. Чуть позже объяснил. По ходу компилятор может сравнивать только элементы до instanceof . Переменная
какого класса – s. s имплементирует интерфейс? Нет. суперклассы s имплементируют интерфейс – нет. Это видно. А что с элементами после
Еще пример

1. Исходный код.
2. Создаем объект для каждого сабкласса. С
помощью емп1 кроме перезагруженных методов
если они есть можно использовать только элементы 4. То есть с помощью кастинга мы можем сказать
из класса Емплоии (из-за компайл тайм байндинга). 5. Дописываем перед емп1 (Доктор) - компилятор перестает выдав
переменной емп1 – слушай, веди себя как
То есть специализацию не вывести. Но объект же ссылается на тот же объект, что и емп1. И уже с помощью д1 мож
переменная типа доктор, и с помощью этого помоги
доктор, специализация относится кдоктору, специализацию. (продумать, в чем разница между просто д1 = е
вывести специализацию. Как это можно сделать.
допустим мы очень хотим через емп1 вывести То есть, что мы сделали. Мы сказали компилятору, поверь мне, е
Можно написать Доктор д1 = емп1? Нет, потому что
специализация. Это возможно с помощью кастинга. ссылается на объект типа доктор (другими словами до этого компи
не любой эмплоии является доктором. Если бы это
ссылается ли он на доктор? это же емп1, переменная емплоии, он
было бы возможно то и емп1 и д1 ссылались бы на
эмплоии и на сабклассы эмплоии. А тут мы уточняем, что это переме
объект доктор (на нью доктор?). Это не то что мы
точно ссылается на объект доктор (а не на какой-то другой эмплои
хотим. То есть компилятор говорит, что емп1 является
чтобы компилятор не сомневался, что это можно пропустить (Возм
суперклассом д1, и не каждый эмплоии является
что с примером инстансоф из прошлого пример
доктором. Но можно сделать кастинг
Другиим словами с помощью этих скобок мы замаскировали пер
переменную доктор. С помощтю полученной переменной д1 можн
лечить который сугубо класса доктор. То есть (Доктор)эмп1 сов
переменной доктор.

6. Можно и не использовать эту д1. Можно сразу писать ()доктор)емп1. Но надо их в скобки
взять в данном случае. Как видим, даже переменную из сугубо класса доктор, которая не
имеет отношения к специализации, тоже можно вызвать. По сути мы говорим джаве, что
эта переменная (доктор)емп1 считается просто обычной переменной доктор.
(просто с емп1 не получится)
7. Как и в случае с инстансоф, тут не Но, можно обмануть компилятор и, например,
получится вставить тест3, джава видит что емп2 (который ссылается на объект Тичер) –
сразу, что это невозможно. Эмплоии и что он доктор. Джава поеврит и компилятор
тест3 не имеют никакой связи из-э. пропустит это. Но в таком случае рантайм
выбъет исключение.

Использование кастинга с интерфейсами

1. Дописываем интерфейс 2. С помощью х можно вызывать метод


хелпейбл в этот проект. хелп. Но нельзя вызывать специализация 3 Но. можно использовать кастинг. То есть
или метод лечить. Логично.. с интерфейсами, если соблюдается
отношение из э, тоже кастинг работает. Еще пример. Можно вызвать метод вот так. все работает. Что произошло. Компилятор поверил, что
емп ссылается на доктор, с помощью емп получилось вызвать метод, не относящийся к емп, а
относящийся к интерфейсу, который имплементирует доктор. То есть переменная просто выступает
как обычная переменная доктор. Хотя переменная не меняет своего типа – это все еще Емплоии,
просто кастинг маскирует емп под тип доктор, заставляет джава поверить, что это тип доктор.

Когда мы пишем емплоии емп2 = нью Тичер(); это тоже кастинг,


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

Еще пример

1. Проверяем , ссылаются ли на одлин объект е и


2. Но, е и т на один объект ссылаться не могути 3. Вот метод иквалс может сравнивать любые объекты, потмоу что его
емп. Так можно написать, так как они могут
компилятор сразу не пускает так писать. По сторонам можно оверрайдить по любой логике. И из-за этого можно сделать
ссылаться на один объект – доктор. Так же как и е
== можно писать только элементы которые имебт из вручную так, чтобы два абсолюьно разных не пересекающихся объектов
==емп2, х==емп2
э связь. В этом случае это не так. будут считаться равными. Поэтому можно использовать иквалс для
сравнения объектов из разных классов.
Еще пример

С помощью фор хотим работать только с элементами 2. Но можно сделать кастинг, чтобы е принимался за драйвера. Когда
объекты драйвер, чтобы они выводили названия машины выпадет драйвер, этот элемент точно будет иметь отношение из э и
и метод водить. Нельзя написать е.названиемашины, выведется названиемашины и метод водить. С другими элементами иф
потому что е – типа эмплоии. не допустит в тело иф, поэтому не из э элементы в него не попадут и
исключение не выбьет. То есть иф оберегает нас от рантайм экспешн – мы
не кастим все что попало, только если это драйвер.

Еще пример

1. Так можно написать, потому что любой 2. Здесь уже левый массив стринг, он
массив является массивом типа обджект. кажется не имеет отношения к массиву 5. Но нулевой элемент аррей2 можно
аррэй 2 («потому что не любой обджект 3. Дописываем кастинг со 4. Можно так написать? Нет,
То есть кастинг происходит и с массивами. назначить стрингбилдером. Потому что
это массив типа стринг»). Чтобы их стринг массивом в скобках – компилятор не пропустит.
Тут конечно апкастинг – он произошел тип аррей2 – обджект, тут опять
уровнять нужен кастинг. Мне кажется оибка компилятора исчезает. Потому что аррей3 какого
автоматически. произошел апкастинг. Компилятор
выбьет исклюение. типа? Стринг. Его 0й элемент пропускает, но если запустить, то получим
не может быть стрингбилдер эксепшн, потому что у нас аррей2 =
аррей1, а аррей1 – Стринг. Мы пытаемся
рантайм вставить стрингбилдер в массив
стринг, поэтому получаем эксепшн

Еще пример

1. Есть такой код. Вопрос, как внутри метода абс 2. Например, можно использовать ключевое 3. А как в методе абс тест30 вызвать метод абс 4. (Он по ходу дела захайдил переменную а в каждом классе). Но сначала
тест30 вызвать метод абс тест20? слово супер. тест10? Так нельзя попробуем достать переменную а из абс 10 в абс30). И для этого нужно
использовать кастинг.. Для этого создаем объект класса тест30 и кастим ее в
объект тест10 – так можно потому что тест30 из э тест10. и выводим на экран.

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


воспринимал т как переменную тест10. А учитывая, что переменные
используют компайл байндинг, уже известно на уровне компиляции
изместно, что т это тест10 и поэтому на экран выходит 5.
6. Если в этом примере использовать метод абс, тогда сработает
все равно метод абс тест30, потому что сработает рантайм
байдинг, метод же перезаписан. на экран выходит ок3.

3. А есть еще нарроуинг. Тут наоборот, из шорта


переходим в байт и тд. Есть два варианта нароуинга
1) без кастнига
2) с кастингом.
Сначала рассмотрим бе кастинг. Должны
выполняться следующие условия.

2. Например, тут можно без проблем перевести инт а


1. У примитивных типов понятие кастинга заменяется (чаще
в б. Потому что а помещается в б, а больше б. Это и
всего?) понятием вайденинг. От меньшего типа данных переходим 1) Если это не байт, шорт, чар, то не Не получится, даже если
называется расширением. Б теперь будет в более
к большему. Не будем приводить примеры на все 19, потому что сработает. потому что и2 это инт, а не лонг сделать файнал
широком типе данных. в инте.
логика там одинаковая. шорт, байт или чар

Пример. Инт равен 111111. Мы


присвоили переменной шорт с
5. Если правила не выполняются, то
кастингом шорт значение инта. В
назначить значения можно, но через
итоге не вышло исключение, а вышло Пример2. Мы не можем написать, что чар равен ортицательному
кастинг, прописанный вручную.
искаженное значение (по огике значению. Но с помощтю кастинга можно. В итоге кастинг по какой-то
Работает как с рференсными типами Но можно кастить только элементы
которую он не объясняет). такой логике меняет значение на положитекльное и выходит этот символ.
данных. Пишем в скобках Что здесь произошло. Мы значение инт закастили в чар.Мы говорим которые соответствуют друг другу. То е
большой инт не вместился в шорт
необходимый тип данных. Здесь – булеан закастить в инт не получится
компилятору, что мы знаем что значене может не поместиться в чар и
пусть и1 воспринимается, как шорт возможно придеться обрубить какие-то биты, но мы согласны на это.

Еще интересный пример. Эт максимальное значение инт. Логика такая – когда мы добавляем +1 к максиальному
Если вывести +1, то получится какое-то странное значению, там уже нет места, чтобы что-то добавить.
отрицательное значение, высчитанное по какой-то лоигке. Поэтому мы перескакиваем к минимальному значению. То
есть после максимально число+1 = минимальное. Все идет
по кругу. Поэтому на экран выходит.
2. Тонкий ммент. Так нельзя. Потому что здесь лонг умножается
1. Сначала и конвертируется в лонг,
на лонг и присваивается инт. Инт меньше лонг, выбивает
потом лонг прибавляется к лонг. 3. Здесь есть еще и 3й вариант. Что тут. Сначала умножь потом
ошибку. Но если использовать кастинг то все ок. (тут нужно все
Выводится 15. приравняй. И умножаем на л, и конвертируется в лонг, лонг
выражение взять в скобки, чтобы кастинг сработал не только на
и а на все выражение) умножается на лонг. Затем получившийсялонг кастится и
назначатеся переменной и. В первом случае нужно было пистаь
касинг.В этом случае кастинг происходит автомтатически.

Потому что любой дробный тип данных больше чем


целочисленный тип данных. По сути втоое правило
ничего нового нам не говорит.
Что здесь происходит. и2 это инт, целоочисленный
тип. ф это флоат – дробный тип. и2 конвертируется во
флоат и прибалвляется к флоату ф.

То есть байт шорт чар переписывается в инт, даже


если инт не участвует. Уточняем, потому что если инт Перед тем как все сложится, все три переведутся в
учатвует, что байт шорт чар должны переписаться по инт. потом складывается и получается 12. Но есть исключение – унарный оператор. ++, --, тогда
правилу1, автоматически. как на картинке б конвертироваться в инт не будет.
Такое исключение.

б2 сначала переводится в тип инт. Затем б2 Доказываем – только дабл


То есть к какому типу данных пришли, такое и будет у конвертируется в флоат и проводится сложение. Еще пример. Помним, что если мы используем
может принять это значение. Еще пример. Или
результата, дробное число, то оно по дефолту дабл. Дабл не
результат конвертируется в дабл, потому что дабл дописывай ф. или касти
больше фолат. Результат значит будет в дабл. помещается во флоат. Если не хотим кастить, то
можно просто дописать ф.
Естственно, если мы складываем ф10 + д10, ф10
конвертируется в дабл. И результатом будет дабл.

Другой немного посторонний пример

Как мы задаем переменные. Вот так можно, потому


В первом случае д принял значение 8, во втором случае д2 принял значение 5. Почему.
что на этом этапе джава уже знает чему равен б. И д так пистаь тоде можно.
Потому что а2 на данном этапе равен нулю.
будет равно 8. так писать можно. А вот так писать нельзя. Потому что на этом
этапе д3 еще нет.

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