Java Flashcards
Почему джава платформонезависимая? Почему она запускается на любой машине? Кроссплатформенность. Что такое джава и почему она строго типизированная?
Java — мультифункциональный объектно-ориентированный язык со строгой типизацией.
Кроссплатформенность. Java является кроссплатформенным языком программирования, то есть программы, написанные на Java, могут работать на разных платформах. Потому что джава запускается на джава машине, и мы как бы можем написать код на любой операционной системе, компилятор скомпилирует наш код в байт код, передаст его джава машине, а тот преобразует его в машинный код, понятный уже определенно этой машине, на которой установлен jvm.
Строгая типизация. Она не позволяет смешивать в выражениях различные типы и не выполняет автоматически неявные преобразования.
Разница между процедурном программированием и ооп?
Процедурное программирование - это тип программирования, в котором инструкции для решения задачи выполняются одна за другой, сверху вниз, иногда возникают изменения в их последовательности. Когда программа становится более сложной на помощь приходят методы.
Объектно-ориентированное программирование (ООП) - методика программирования, в которой основными концепциями являются понятия объектов и классов. Прежде чем начать писать инструкции для решения задачи, в задаче выделяются объекты и описываются с помощью классов. В классе прописывается поведение объектов с помощью методов и характеристики или свойства объекта с помощью переменных класса. Одной из ключевых особенностей языка Java является ООП.
Процедурное программирование можно сравнить с постройкой маленького домика - нет необходимости тратить время и ресурсы на продумывание архитектуры. ООП же похоже на постройку сложного архитектурного сооружения, где очень важно продумать все детали, и только потом приступать к программированию (постройке).
Преимущества и недостатки ООП. Что это такое?
ООП – метод программирования, основанный на представлении программы в виде совокупности взаимодействующих объектов, которые являются экземплярами определенных классов, а классы образуют иерархию наследования.
Преимущества:
*ООП парадигма позволяет переложить наш объект из реального мира в наш код. Мы устанавливаем связи и взаимодействия между объектами подобно тому, как они взаимодействуют в реальном мире. И поэтому нам проще с ней разобраться.
*мультифункциональность;
*достаточно простой синтаксис;
*независимость (код сможет работать на любой платформе, поддерживающей Java);
Недостатки:
*В избыточности. Когда мы хотим достигнуть какой-то простой цели, мы не хотим описывать всю структуру объектов, их связи и зависимости. Мы просто хотим получить какой-то результат. То есть как бы не хватает краткости.
*требуемое большое количество памяти;
*низкая скорость по сравнению с С и С++;
Главные принципы ООП:
Абстракция, Инкапсуляция, Наследование, Полиморфизм.
Абстракция – отделяет концепт от ее реализации. Выделение значимых характеристик объекта. Например, у нас есть класс Работник, у которого есть все нужные характеристики: ФИО, дата рождения и прочее. Но если это работник модельного бизнеса нам важны такие характеристики как Рост, вес, цвет глаз., а если работник Инженерной разработки, то эти свойства нам не важны, но есть другие значимые. Значит мы выделяем абстрактного работника, а затем наследуемся от него и добавим какие-то специфические свойства.
Инкапсуляция – размещение одного объекта или класса внутри другого для разграничения доступа к ней, путем модификатора доступа. Пример: У тебя есть имя и фамилия. Их знают все твои знакомые. Но у них нет доступа к изменению твоего имени и фамилии. Этот процесс, можно сказать, «инкапсулирован» в паспортном столе: поменять имя фамилию можно только там, и сделать это можешь только ты. Остальные «пользователи» имеют доступ к твоему имени и фамилии «только на чтение».
Наследование – способность объекта базироваться на другом объекте. То есть когда один объект приобретает характеристики другого добавляя свои собственные. Основное преимущества наследования – повторное использование кода.
Полиморфизм – сокрытие различных реализаций за одним интерфейсом, или это возможность работать с несколькими типами так, будто это один и тот же тип. При этом поведение объектов будет разным в зависимости от типа, к которому они принадлежат. Пример: Интерфейс flyable – с методом fly() и разные птицы наследуют его по разному.
Отношения “Являюсь” и “Имею” в ООП
Отношение «Is A» - это наследование. Когда мы имеем класс БМВ и он наследуется от класса Машина, можно задать вопрос: бмв является машиной? и если да, тогда это отношение is a.
Отношение «Has A» - это когда у нас есть класс Радио и класс Машина. И логично, что у машины может быть радио. И мы должны записать отдельным полем (сделать injection) и такие отношения называются «has a»
Динамический полиморфизм (или рантайм полиморфизм).
Когда мы вызываем переопределенный метод дочернего класса через ссылку на родительский тип, тогда тип объекта указывает, какой метод будет вызван. Принятие этого решения происходит во время выполнения JVM после компиляции кода. Следовательно, это называется как рантайм полиморфизм.
Есть родительский класс Звери и наследники: травоядные и хищники. Классы-потомки расширили родителя и переопределили его метод eat(). И когда мы где-то в программе создаем объект класса звери: Animal animal = new Predator(). И вызываем у этого объекта метод eat(). Так вот он вызовет именно тот, что переопределен в Хищнике.
Что такое перегрузка методов?
В программе мы можем использовать методы с одним и тем же именем, но с разными возвращаемыми типами или количеством параметров. Такой механизм называется перегрузкой методов (method overloading).
Перегрузка конструктора: зачем, в чем смысл?
Конструкторы похожи на методы, поэтому они тоже могут быть перегружены - вы можете объявлять в одном классе несколько конструкторов, которые различаются количеством и типом переменных. Если у нас, например, есть какой-то объект, в котором есть обязательные поля, а есть не совсем. И когда мы создаем объект этого класса и одного параметра не хватает, то нам он как бы и не важен, поэтому мы можем создать. А если у нас будет только один конструктор, то компилятор будет ругаться и не даст создать объект. Поэтому мы создаем два конструктора с разным количеством параметров.
Можно ли создать 2 метода с одинаковым именем и разным возвращаемым типом?
Да, если у них будут разные принимаемые параметры. Если отличаться будет только возвращаемый тип, то будет ошибка, это не перегруженный метод.
Чем отличаются статические поля и методы от не статических?
Статические поля и методы относятся к классу, в котором они объявлены и для обращения к ним не нужно создавать объект. Нестатические относятся к объекту и для обращения к ним нужно создать экземпляр этого класса.
Позднее и раннее связывание.
Позднее связывание связано с формированием кода на этапе выполнения. Если в иерархии классов встречается цепочка виртуальных методов, то компилятор строит так называемое позднее связывание. При позднем связывании вызов метода происходит на основании типа объекта, а не типа ссылки на базовый класс. Позднее связывание используется, если нужно реализовать полиморфизм.
Раннее связывание - это когда метод который будет вызван, известен во время компиляции, напр. вызов статического метода.
Статическое связывание происходит во время компиляции, а динамическое – во время выполнения.
Множественное наследование. Почему от него отказались?
В джаве нет такого наследования, но можно использовать множественную имплементацию интерфейсов.
Отказались потому что с ним связано много проблем. Самая известная – diamond problem – это когда класс В и С наследуются от класса А, а класс D наследуется от них двоих, а затем ему нужно вызвать метод класса А, который не переопределен в классе D, но классы В и С переопределили его по-своему, то не понятно, метод какого класса будет реализовывать класс D.
Композиция и агрегация.
Это частные случаи ассоциации.
Ассоциация означает, что объекты двух классов могут ссылаться один на другой, иметь некоторую связь между друг другом. Например, Менеджер может выписать Счет. Соответственно возникает ассоциация между Менеджером и Счетом. Еще пример — Преподаватель и Студент — т.е. какой-то Студент учится у какого-то Преподавателя. Ассоциация и есть описание связи между двумя объектами.
Композиция — включение объектом-контейнером объекта-содержимого и управление его поведением; значит, что внутренний объект не может существовать без внешнего. Типа, колесо-мотоцикл. Колесо без мотоцикла не имеет смысла.
Агрегация — включение объектом-контейнером ссылки на объект-содержимое; при уничтожении первого последний продолжает существование. Кресло может стоять в квартире, офисе, заводе. Оно может существовать где угодно и выполнять свои функции.
Интерфейс vs Объект vs Класс vs Метод
Класс — это шаблон, используя который мы можем создавать экземпляры объектов, у которых будет точно такая же конфигурация, как и у шаблона — те же свойства и методы.
Объект – это экземпляр определенного класса.
Метод – это поведение, функция или операция, которую может совершать наш объект.
Интерфейс – это контракт, который говорит нам о том, что некие классы, имплементирующие данный интерфейс имеют общее поведение.
Интерфейс — это группа взаимосвязанных свойств и методов, которые описывают объект, но не обеспечивают реализацию или инициализацию этих свойств и методов в объектах.
Главное отличие класса от интерфейса — в том, что класс состоит из интерфейса и реализации.
Есть пример: допустим у нас есть класс Ключ, который имеет публичный метод Открыть, который в свою очередь ссылается на приватные методы Вставить, Повернуть и Вынуть. А также есть интерфейс Ключ, который содержит метод Открыть. Если мы наследуемся от класса Ключ, то наш наследник наследует его метод Открыть, вместе с его реализацией. А если, например, нам нужно открыть дверь с помощью не поворотного ключа, а магнитной карты, а мы унаследовали класс Ключ вместе с его методом Открыть, который открывает уже прописанным способом. Так вот если у нас есть интерфейс, то мы можем прописать для поворотного ключа и для магнитной карты свою реализацию и не переживать, что у нас ограничен функционал.
Модификаторы доступа
private – доступ только внутри класса
default – доступ внутри класса и у классов из этого же пакета.
protected – доступ из класса, пакета и у классов наследников.
public – доступ из любого места программы.
JVM, JRE, JDK
JVM – виртуальная машина Java. Она преобразовывает байт код в машинный код.
JRE (Java Runtime Environment) – реализация виртуальной машины, которая предоставляет платформу для работы джава программ. Чтобы запустить на любой машине джава-программу, сначала надо установить JRE на этой машине. Содержит собственно JVM + набор стандартных библиотек.
JDK (JAVA Development Kit) – основной компонент среды Джава. Включает в себя JRE + отладчик, компилятор и все стандартные классы.
Declaration и Initialization (Объявление и инициализация)
Декларация - это просто объявление переменной: тип и его имя.
Инициализация – это когда наша переменная уже приобретает какой-то объект, начинает ссылаться на объект, занимать место в памяти и т.д.
Переменные, что это. Из чего состоит
Переменная в Java — это контейнер, в котором может храниться некоторое значение данных для дальнейшего использования в программе. По сути переменная — это минимальная неделимая единица Java-приложения. Все переменные в Java можно разделить на два вида: переменные примитивных типов и ссылки.
Состоит из типа и имени, затем идет оператор присвоение и какое-то значение этой переменной.
Разница между локальной переменной и переменной метода (инстанс и локал)
Инстанс переменная или переменная экземпляра – это нестатические переменные, которые определены в классе вне какого-либо метода или блока. Каждый созданный объект имеет отдельную копию или экземпляр этой переменной. Переменная принадлежит классу.
Переменная метода – это переменная объявленная внутри метода и любого другого блока кода. Она перестает существовать, когда метод завершает свою работу.
Где хранится переменная
Примитивная переменная хранится в стэке, а ссылочная в хипе. Примитивная переменная может хранится в хипе, если она является переменной экземпляра, то есть она будет хранится там же, где и сам объект.
переменные метода хранятся в стэке: примитивные полностью, а ссылочные: ссылка в стэке, а сам объект – в хипе. После завершения метода, переменные метода перестают сущетсвовать, а тот объект, который хранился у нас в хипе, ссылка которого была в стэке, удалиться при следующем вызове сборщика мусора, потому что тот проверит что нет никаких переменных, которые ссылались бы на этот объект.
Как в джава передаются аргументы в метод: по ссылке или по значению?
Java всегда передает параметры по значению.
Допустим, у нас есть переменная int a = 10. мы передаем ее в метод
count(int b){
b = b * 10; }
Если мы где-то потом снова выведем переменную а, то увидим, что она не изменилась, потому что в метод count была передана ее копия, то есть только ее значение. и манипуляции были произведены с копией, а не с изначальной переменной.
Если мы говорим о списках, то там тоже самое:
У нас есть список List<Integer> numbers = new ArrayList<>(Arrays.asList(1,2,3)).
мы передаем копию нашего списка.
count(List<Integer> numbersNew){
numbersNew.add(5); }
то есть numbersNew и numbers – это две разные ссылки, но они ссылаются на один и тот же объект. Поэтому любые манипуляции с этими ссылками будут приводить к изменению этого объекта.
Только если в методе написать numbersNew = new ArrayList<>(numbers), а потом производить манипуляции, то тогда не это будут разные ссылки и разные объекты, и манипуляции с одним не будут затрагивать другой.</Integer></Integer>
Типы данных: Примитивные и ссылочные переменные. Отличия. Классы оболочки примитивов.
Ссылочные типы данных – ссылка на них хранится в стэке, сам объект в хипе, чтобы его создать нужно использовать оператор new. Если на объекты, лежащие в хипе не останется ссылки, то ГарбечКоллектор удалит их. Примитивные типы хранятся в стэке. Примитивные: byte(8 бит) = 127, short(16 бит) = 32,7 тыс, int(32 бит) = 2,1 млрд, long(64 бит), char(16 бит), float(32 бит), double(64 бит), Boolean.
Ссылочные – String, все классы, массивы, коллекции и интерфейсы.
Отличия: примитивы хранят значения, а ссылочные – ссылку на объект в памяти, создаются через присваивание значения, а ссылочные через конструктор класса, примитывы имеют строго заданный диапазон, а ссылочные имеют по умолчанию значение null.
Классы обертки нужны нам чтобы работать с примитивами как с объектами: например в коллекциях и чтобы передавать их значение по ссылке.
Почему примитивные типы данных называют строго типизированными и статично типизированными. В чем выражается строгость
Статически типизированный язык, в котором каждая переменная и тип выражения уже известны во время компиляции. Как только переменная объявлена как относящаяся к определенному типу данных, она не может содержать значения других типов данных.
Строго типизированный язык – это значит, что все данные и каждое выражение имеет конкретный тип, который строго определен. А также то, что все операции по передаче данных будут проверяться на соответствие типов.
Автобоксин. Анбоксинг.
Это приведение примитивного типа данных классу обертке и наоброт. То есть мы можем присвоить классу обертке примитивное значение, и он его автоматически преобразует к интеджеру – это автобоксинг, а когда мы присваиваем класс обертку соответствующему ему примитиву – анбоксинг.
Нативные методы
это методы, которые написаны на другом языке программирования
Класс Обджект. Какие методы у него есть? что мы о нем знаем, зачем нужен?
Самый начальный класс, от которого наследуются все классы. Поэтому все классы, могут реализовать методы класса Обджэкт. Его методы:
toString – для строкового представления объекта.
hashCode – получаем своеобразный идентификатор в виде числа типа инт,
equals – для сравнения объектов,
getClass – позволяет получить типа данного объекта,
clone() - создает объект точную копию объекта(есть глубокое и поверхностное копирование – при поверхностном мы копируем ссылки, а при глубоком – копируем все переменные, примитивные и ссылочные),
notify/notifyAll() – возобновляет все потоки ожидающие вызова,
wait() – ожидает исполнение другого потока.,
finalize() – вызывается перед удаление неиспользуемого объекта.
Контракт equals-hashcode.
Это методы класса обджект. если мы хотим, чтобы корректно работали такие структуры данных как хэшмапа, линкедхэшпама и другие, то нам нужно переопределять эти методы в наших классах.
Equals – сравнивает объекты по значениям их полей, hashcode возвращает числовое представление объекта и используется в коллекциях, чтобы определить позицию элемента в хэштаблице.
Контракт гласит:
1. Всякий раз, для одного и того же объекта вызывая несколько раз hashcode во время выполнения приложения, он должен возвращать одно и тоже значение, при условии, что информация, используемая в equals для сравнения, не изменялась.
2. Если два объекта равны по equals, то их hashcode тоже должен быть равен.
3. Если два объекта не равны по equals, то они не обязательно не равны по hashcode.
Принципы переопределения метода иквалс?
Рефлексивность - каждый объект должен быть эквивалентен самому себе(x.equals(x) = true);
Симметричность - два любых объекта должны быть равны независимо от того, в каком порядке они будут сравниваться (x.equals(y) = true только, если y.equals(x) = true).
Транзитивность - для каждого экземпляра x, y и z должно выполнятся условие: если x.equals(y) возвращает true и y.equals(z) возращает true, тогда x.equals(z) должно возращать true
Согласованность - если объекты x и y не меняются, повторный вызов x.equals(y) должен вернуть то же значение, что и ранее.
Сравнение null - ни один объект не должен быть равен null (x.equals(null) = false)
Строка. Всё о ней.
String – это immutable class. Неизменяемый. Класс реализует интерфейсы Serializable и CharSequence. это final класс, который не может иметь потомков. Благодаря своей неизменности, объекты класса String являются потокобезопасными. Его основные методы: toString(), valueOf() - перевод экземпляра любого Java-класса или любого примитивного типа данных к строковому представлению ,indexOf() - метод для определения позиции символа , endWith(), toUpperCase(), toLowerCase(), intern() — помещает строку в StringPool, если там такой еще нету.
String Pool. Сколько там хранятся значения?
Класс String, возможно, наиболее часто используемый класс в Java. Если новый объект создавать в динамической памяти (memory heap) каждый раз, когда мы используем String, то мы потратим впустую много памяти. Пул строк (String pool) решает эту проблему, сохраняя только один объект для каждого значения строки
Что такое конструктор для копирования? Copy constructor
Конструктор копирования - это конструктор, который создает объект, используя другой объект того же класса.
Это полезно, когда мы хотим скопировать сложный объект, содержащий несколько полей, или когда мы хотим сделать глубокую копию существующего объекта.
String Builder, String Buffer
String Builder – потоконебезопасный
String Buffer – потокобезопасный
Они имеют одинаковые методы и отличаются только потокобезопастностью. Самый главный метод append(), который помогает конкатенировать строки. В классе Стринг, когда мы конкатенируем с помощью +, то под капотом используется класс Билдер или Баффер на успотрение компилятора и метод append().
Популярные методы: insert(), replase(), substring(), delete(), reverse().
finally, final, finalize – что это и разница?
finally – это блок кода из try/catch, который выполняется всегда.
final – это слово которым помечается класс, метод или переменная, чтобы обозначить что она финальная и не изменяемая и не может наследоваться, в случае класса
finalize – это метод класса Object, который вызывается перед неиспользуемым объектом.
Циклы:
for – проходит циклом по массиву или коллекции, итерируясь на каждом элементе. под капотом имплементит итератор или итерабл.
for-each - цикл “для каждого…” — разновидность for для перебора коллекции элементов, нам не нужно следить за счетчиком, цикл сам поочередно берет элементы из коллекции и помещает их в указанную переменную.
while – выполняется до тех пор, пока условие дает результат true,
do-while – сначала делает что-то, затем проверяет условие, и если true – идет на новый круг.
Условны операторы.
if / if-else
switch
тернарная операция
Массив: примитив или объект? Это статическая структура данных или динамическая?
Массив – это объект, или конечная последовательность упорядоченных элементов одного типа.
Массив - это статическая структура. Когда массив инициализируется, длина массива не является переменной. Массивы в Java-программах должны быть инициализированы перед использованием. Так называемая инициализация состоит в том, чтобы выделить пространство памяти для элементов объекта массива и указать начальное значение для каждого элемента массива.
Скорость доступа к элементу - O(1) – константное время.
Big O Notation
Это способ обозначения сложности алгоритма.
Абстрактный класс vs Интерфейс
Если нам нужна дефолтная реализация, как бы описание сущности наследников, то мы можем использовать абстрактный класс, если же нам нужен просто контракт, что группа объектов умеет делать, то используем интерфейс.
Гетерогендерный типы(Гетероджерерс)
Когда гетерогенный объект ссылался на гетерогенную коллекцию, коллекцию, которая может хранить объекты разных типов. Неоднородной коллекцией может быть массив Object[] или List<object>, они могут содержать экземпляры разных типов (например, Integer и String).</object>