JRE (Java Runtime Environment) — минимальная реализация виртуальной машины, необходимая для исполнения Java-приложений, без компилятора и других средств разработки. Включает в себя:
JDK (Java Development Kit) — бесплатно распространяемый компанией Oracle Corporation (ранее Sun Microsystems) комплект разработчика приложений на языке Java. Он включает в себя:
JVM (Java Virtual Machine) — виртуальная машина Java — основная часть JRE.
Байт-код — набор инструкций, исполняемых виртуальной машиной Java.
Динамическая компиляция JIT (Just In Time) - технология увеличения производительности программных систем, использующих байт-код, путём компиляции байт-кода в машинный код или в другой формат непосредственно во время работы программы. Большинство реализаций JIT имеют последовательную структуру:
Garbage Collector - одна из форм автоматического управления памятью.
Пакет - это именованная логическая группа классов. Пакеты непосредственно соответствуют иерархии в файловой системе.
Импортирование имен - способ ссылки на классы из другого пакета. При импортировании простое имя типа погружается в текущую область видимости имён, и его можно использовать непосредственно, без указания имени пакета.
Класс — это описания структуры и поведения объектов. Классы записываются программистом в виде исходного кода и компилируются в байт-код. Имея байт-код классов, виртуальная машина способна создавать объекты и обеспечивать вызов их методов.
[public] [final|abstract] class ClassName
[extends OtherClass]
[implements Interface1, Interface2] {}
Объекты — это участки памяти виртуальной машины, содержащие своё состояние в виде полей.
[public|protected|private] [static] [final] Type field;
Метод — это просто функция, которая неявным параметром принимает объект, на котором она вызывается. Таким образом, отправка сообщения сводится к вызову функции.
[public|protected|private] [static|abstract|final] Type method(Type param) {}
Абстрактный класс — это такой класс, часть функционала которого не реализована, но задекларирована.
Интерфейс в Java можно понимать как класс, содержащий только абстрактные методы. Интерфейс предназначен для описания абстракций или контрактов, которые должен предоставлять класс, реализующий этот интерфейс.
Функция — именованный блок кода, возможно, принимающий некоторые данные извне (параметры/аргументы) и, возможно, возвращающий некоторый результат.
Виртуальные методы — такие методы, которые обладают свойством позднего связывания.
Вложенный класс — используется для более тонкой организации классов, чем с помощью пакетов.
[public|protected|private] [static] [abstract|final] class NestedClass {}
Лямбда-выражение — часть парадигмы функционального программирования. Предназначены для замены слишком многословного синтаксиса анонимных классов.
(Type param) -> { /* body */ }
Перечисление — специальный тип данных, предусмотренный для ограничения множества допустимых значений для некоторого типа данных.
[public] enum EnumName [implements Interface1, Interface2] {}
Конструктор — это специальный метод, который автоматически вызывается при создании объекта и инициализирует его состояние.
[public|protected|private] ClassName(Type param) {}
Дженерики — реализация обобщенного программирования, включающая в себя поддержку обобщенных классов и обобщенных методов.
public class SomeClass<T1, T2, ...> {}
<T1, T2, ..., E [extends|super] ClassName> R method(T1 p1, T2 p2, ...) throws E {}
Итератор - объект, предоставляющий доступ к элементам коллекции и навигацию по ним.
Аннотации - дескрипторы, включаемые в текст программы. Используются для хранения метаданных программного кода, необходимых на разных этапах жизненного цикла программы.
import java.lang.annotation.*;
@Target(value=ElementType.FIELD)
@Retention(value= RetentionPolicy.RUNTIME)
public @interface Name {
String name();
String type() default “string”;
}
Shadowing - сокрытие объявления может произойти, когда объявляется ещё одна сущность того же рода с тем же именем в более узкой области видимости. В таком случае к исходной сущности нельзя обращаться по простому имени.
Obscuring может произойти, когда существует неоднозначность имени между разными пространствами имён (например, имя переменной совпадает с именем пакета). Такое случается крайне редко.
Hiding - скрытие имен происходит во время наследования, если в родительском и дочернем классе есть одинаковые статические методы.
public class Test {
public static void testClassMethod() {
}
}
public class StandartTest extends Test {
public static void testClassMethod() {
}
}
Overriding - процесс перегрузки метода, который происходит во время наследования, если в дочернем классе есть одинаковые нестатические методы.
public class Test {
public void testInstanceMethod() {
}
}
public class StandartTest extends Test {
public void testInstanceMethod() {
}
}
Исключение - ошибка, возникающая во время выполнения программы. Исключения сигнализируют о возникновении ошибочной ситуации, из-за которой программа не может выполняться дальше. Поэтому исключения вызывают раскрутку стека вызовов. Когда какой-либо метод выбрасывает исключение, виртуальная машина начинает выталкивать элементы из стека вызовов (как будто произошёл возврат из каждого метода) до тех пор, пока не найдёт обработчик, который сможет обработать это исключение. Если такой обработчик нашёлся, то управление передаётся в него, и код внутри этого обработчика может либо продолжить выполнение программы, либо выбросить ещё одно исключение.
Exception
. Метод обязан либо обработать эти исключения, либо явно объявить (с помощью декларации throws
), что он их выбрасывает.RuntimeException
. Их объявлять и отлавливать необязательно.Error
, выбрасываемые виртуальной машиной в случае серьёзной ошибки (кончилась память, не удалось загрузить класс и т.д.). Обычный код не должен обрабатывать эти исключения.try-with-resources
. В Java 7 была введена специальная конструкция, позволяющая безопасно открывать и закрывать ресурсы (классы, реализующие интерфейс AutoCloseable
). public static void main(String[] args) throws Throwable {}
public static void main(String[] args) {
try {}
catch (Throwable t) {}
finally {}
}
JavaBeans - компоненты (бины), обеспечивающие основу для многократно используемых, встраиваемых и модульных компонентов ПО. Компоненты JavaBeans могут принимать различные формы, но наиболее широко они применяются в элементах графического пользовательского интерфейса. [source]
Пример бина, как POJO объекта:
public class PersonBean implements Serializable {
private String name;
public PersonBean() {
}
public String getName() {
return (this.name);
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
...
}
@Override
public int hashCode() {
...
}
@Override
public String toString() {
...
}
}
POJO (Plain Old Java Object) - простой Java-объект, не унаследованный от какого-то специфического объекта и не реализующий никаких служебных интерфейсов сверх тех, которые нужны для бизнес-модели. [source]
ООП (Объектно Ориентированное Программирование) - методология программирования, основанная на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определенного класса, а классы в свою очередь образуют иерархию наследования.
Инкапсуляция - сокрытие реализации.
default
, public
, protected,
private
.Полиморфизм - парадигма ООП. Существует несколько его разновидностей:
Наследование - возможность создавать потомков и переопределять часть функциональности класса.
Абстракция - это выделение общих характеристик объекта, отличая от всех других объектов.
Класс — это описание структуры и поведения объектов.
Объекты — это участки памяти виртуальной машины, содержащие своё состояние в виде полей.
Типы данных - в Java существует два типа данных: примитивные и ссылочные:
byte
, short
, int
, float
, double
, long
, boolean
, char
.Операции - операции в Java разделяются на следующие группы:
+
, -
, /
, *
, %
, ++
, --
.==
, !=
, >
, >=
, <=
, <
.&
, |
, ^
, ~
, <<
, >>
, >>>
.&&
, ||
, !
.=
, +=
, -=
, *=
, /=
, %=
, <<=
, >>=
, &=
, ^=
, |=
.() ? () : ()
, instanceof
Строка - последовательность символов, в Java строки являются объектами.
String
.HashMap
. При том, строки могут свободно использоваться различными потоками, не боясь, что кто-то их изменит, таким образом отпадает необходимость в синхронизации.StringBuilder
или StringBuffer
.StringTokenizer
- позволяет разбивать текст на лексемы, отделяемые разделителями. Парсит данные. Быстрый. Не поддерживает регулярные выражения. Устаревший.String.split
- позволяет разбивать текст на лексемы, отделяемые разделителями. Поддерживает регулярные выражения. Возвращаемым значением является массив строк. Работает медленее, чем StringTokenizer
.Formatter
- обеспечивает преобразование формата, позволяющее выводить числа, строки, время и даты в любом необходимом разработчику виде.Pattern
- применяется для определения регулярных выражений (шаблонов), для которых ищется соответствие в строке, файле или другом объекте, представляющем последовательность символов.Matcher
- если необходимо найти соответствия внутри строки, необходимо использовать этот класс.Массив - фиксированная структура данных.
dataType[] arrayRefVar = new dataType[arraySize];
dataType[] arrayRefVar = {value0, value1, ..., valueK};
public static int binarySearch(Object[] a, Object key)
public static boolean equals(long[] a, long[] a2)
public static void fill(int[] a, int val)
public static void sort(Object[] a)
private
(переменные / конструкторы / методы / внутренние классы) - члены класса доступны только внутри класса.
package-private
или default
(переменные / конструкторы / методы / классы) - члены класса видны внутри пакета.
protected
(переменные / методы / конструкторы / внутренние классы) - члены класса доступны внутри пакета и в классах-наследника.
public
(все) - члены класса доступны всем.
static
(логические блоки / переменные / методы / классы) - статические блоки выполняются во время загрузки класса. К статическим методам и переменным можно обращаться через имя класса.
abstract
(методы / классы) - абстрактные классы должны наследоваться, а абстрактные методы - реализовываться.
final
(переменные / методы / классы) - переменные, которым было присвоино значение, не могут быть переприсвоены. Методы не могут быть перегруженны. Классы не могут быть наследованы.
synchronized
(методы / части метода) - метод может одновременно использоваться только одним потоком.
transient
(переменные) - переменная не сериализуется. Локальные переменные не могут быть объявлены как transient.
volatile
(переменные) - значение переменной, объявленной как volatile, измененное одним потоком, асинхронно меняется и для других потоков.
native
(методы) - обозначает, что метод написан на другом языке программирования.
strictfp
(методы / классы) - обеспечивает выполнение операций над числами типа float и double (с плавающей запятой) по стандарту IEEE 754.
Дженерики — реализация обобщенного программирования, включающая в себя поддержку обобщенных классов и обобщенных методов.
Обобщенные классы - обобщенные (параметризованные) классы могут использоваться для следующих целей:
List<Integer>
, Set<Long>
, Map<String, Runnable>
, Future<HttpResponse>
, Optional<Model>
.public interface Comparator<T> {
int compare(T left, T right);
}
public interface Function<F, T> {
T apply(F arg);
}
public interface Callable<T> {
T call() throws Exception;
}
public interface Provider<T> {
T get();
}
public interface ThrowingProvider<T, E extends Throwable> {
T get() throws E;
}
public abstract class GenericDAO<T, ID> {
protected GenericDAO(Class<T> clazz) { ... }
public T findById(ID id) { ... }
}
public interface StringConverter<T> {
T fromString(String s);
String toString(T obj);
}
public class TwoTuple<A,B> {
public final A first;
public final B second;
public TwoTuple(A a, B b) {
first = a; second = b;
}
}
Обобщенные методы - обобщенные (параметризованные) методы могут использоваться для следующих целей:
public static <T extends Enum<T>> EnumSet<T> allOf(Class<T> clazz);
public static <T> ImmutableList<T> of(T pɴ, T pɵ, T... other);
public <T> T getInstance(Key<T> key);
public static <T> Iterable<T> skip(Iterable<T> iterable, int n);
public static <F, T> Iterable<T> transform(Iterable<F> iterable, Function<F, T> function);
public static <T extends Comparable<T>> T max(Iterable<T> xs);
Wildcards - wildcards существуют трех типов:
public static double sumOfList(List<? extends Number> list);
void printCollection(Collection<?> c);
public static void addNumbers(List<? super Integer> list);
Многопоточность - это когда множество процессов делят общие вычислительные ресурсы, такие как CPU, между собой.
Поток в Java представлен классом java.lang.Thread
, объекты которого являются потоками, работающими внутри текущей JVM.
java.util.concurrent
, в котором содержится большое количество различных классов, помогающих при разработке многопоточных программ.Создание потока. Для того, чтобы выполнить какую-либо задачу в отдельном потоке, можно создать новый поток с помощью конструктора класса Thread
, передать ему Runnable
и запустить его.
new Thread(new Runnable() {
@Override public void run() { /* ... */ }
}).start();
new Thread(() -> { /* ... */ }).start();
Создание сервисного потока. Выполнение Java-машины завершается, когда завершатся все потоки, не являющиеся сервисными, т.е. те, у которых не установлен флаг daemon.
Thread t = new Thread(() -> { ... });
t.setDaemon(true);
t.start();
Критические секции. При работе потоков с общей изменяемой памятью неизбежно возникает проблема синхронизации действий этих потоков.
synchronized-блоки
.synchronized-блоками обозначаются критические секции — участки кода, которые в каждый момент времени могут выполняться только одним потоком.
private static final Object lock = new Object();
private static void transfer(int amount) {
synchronized (lock) {
account1 = account1 - amount;
account2 = account2 + amount;
}
}
Замки - являются более мощной версией synchronized-блока. Основные интерфейсы замков — java.util.concurrent.locks.Lock
и ReadWriteLock
, а наиболее полезные классы — ReentrantLock
и ReentrantReadWriteLock
.
private static final Lock lock = new ReentrantLock();
lock.lock();
try {
// критическая секция
}
finally {
lock.unlock();
}
Пулы потоков - это набор потоков, которым можно передавать какие-либо задачи (например, Runnable) на выполнение.
Executor executor = Executors.newFixedThreadPool(4);
executor.execute(() -> /* ... */ );
executor.execute(new Runnable() {
@Override public void run() { /* ... */ }
});
Жизненный цикл потока. Поток проходит через несколько стадий своего жизненного цикла:
Приоритет - каждый поток имеет приоритет, который помогает операционной системе распознавать порядок в котором потоки будут работать: MIN_PRIORITY
, NORM_PRIORITY
, MAX_PRIORITY
.
Массив. Массивы встроены в язык и довольно производительны; они часто служат основой других коллекций.
Интерфейс Collection<T>
является базовым интерфейсом для линейных коллекций. Он предоставляет основные операции, общие для всех коллекций.
add()
, addAll()
, clear()
, contains()
, containsAll()
, equals()
, hashCode()
, isEmpty()
, iterator()
, remove()
, removeAll()
, size()
, toArray()
.AbstractCollection
реализует большинство методов этого интерфейса.Интерфейс List<T>
является одним из наиболее часто используемых интерфейсов коллекций, который обозначает упорядоченную коллекцию. Каждый элемент списка имеет целочисленный индекс; возможно добавление и удаление элементов по индексу. Дополнительно этот интерфейс предоставляет специальный итератор ListIterator<T>
, который позволяет перемещаться по списку в обе стороны и вставлять новые элементы.
get()
, indexOf()
, lastIndexOf()
, listIterator()
, set()
, subList()
.AbstractList
наследуется от AbstractCollection
и реализует большинство методов List
интерфейса.AbstractSequentialList
наследуется от AbstractList
и реализует большинство методов List
интерфейса с упором на последовательный, чем на случайный доступ к элементам.Реализация ArrayList<T>
используется чаще всего в интерфейсе List
. По сути является реализацией списка на основе массива. Кроме того, ArrayList
очень эффективно использует память, и операции, основанные на доступе по индексу (сортировка, перемешивание, бинарный поиск и т.д.), выполняются быстро.
ensureCapacity()
, removeRange()
, trimToSize()
, clone()
.Реализация LinkedList<T>
используется гораздо реже. Является реализацией списка на основе двусвязного списка. LinkedList
эффективнее при вставке/удалении элементов в начале или конце и при вставке/удалении в середине после итерации до нужного места. Также LinkedList
потребляет значительно больше памяти, чем ArrayList
.
addFirst()
, addLast()
, clone()
, getFirst()
, getLast()
, removeFirst()
, removeLast()
.Интерфейс Set<T>
предоставляет абстракцию математического множества, т.е. неупорядоченную коллекцию, не содержащую одинаковых элементов. Из-за неупорядоченности элементы множества нельзя получить по их индексу, поэтому для множеств не имеет смысла сортировка и перемешивание элементов. Однако при этом операции проверки на наличие элемента во множестве эффективнее, чем в списке.
isEmpty()
.AbstractSet
наследуется от AbstractCollection
и реализует большинство методов Set
интерфейса.Интерфейс SortedSet<T>
является расширением Set<T>
. Он предполагает наличие отношения порядка на своих элементах. Из-за этого SortedSet
предоставляет дополнительные операции.
clone()
, comparator()
, first()
, headSet()
, last()
, subSet()
, tailSet()
.Реализация HashSet<T>
— это наиболее часто используемая реализация множества, потому что основные задачи множества она выполняет наиболее эффективно. HashSet основан на HashMap
. Поэтому, в частности, для использования HashSet
необходима правильная реализация методов equals()
и hashCode()
.
AbstractSet
.clone()
.Реализация LinkedHashSet<T>
объединяет множество на основе хеш-таблицы и связный список. Эффективность всех операций на нём та же, что и у HashSet
, но порядок итерации по нему не псевдослучаен, а соответствует порядку добавления элементов в это множество. LinkedHashSet
основан на LinkedHashMap
и наследует HashSet
, поэтому для него также справедливы условия на методы equals()
и hashCode()
у элементов.
HashSet
.Реализация TreeSet<T>
— это множество, основанное на TreeMap
. Оно реализует интерфейс SortedSet<T>
, и в нём могут храниться только элементы, на которых задано отношение порядка. Класс TreeSet
основан на TreeMap
, и поэтому все операции над элементами имеют логарифмическую сложность. Это хуже, чем у HashSet
, поэтому TreeSet используется только тогда, когда необходимо так или иначе сортировать элементы множества.
AbstractSet
.clone()
, comparator()
, first()
, last()
, headSet()
, subSet()
, tailSet()
.Интерфейс Queue<T>
представляет собой контейнер, в который можно добавлять элементы и доставать их оттуда. Релизации Queue<T>
могут ограничивать максимальное количество элементов в коллекции. Поэтому Queue<T>
предоставляет два набора методов для указанных операций. Первый набор в граничных ситуациях выбрасывает исключение, а второй — возвращает специальное значение (null или boolean).
AbstractQueue
наследуется от AbstractCollection
и реализует большинство методов Queue
интерфейса.offer()
, peek()
, poll()
.Интерфейс Deque<T>
обозначает дек, структуру данных, являющуюся одновременно стеком и очередью. В дек можно добавлять и удалять элементы с двух сторон.
offer()
, peek()
, poll()
, addFirst()
, addLast()
, descendingIterator()
, element()
, getFirst()
, getLast()
, offerFirst()
, offerLast()
, peekFirst()
, peekLast()
, pollFirst()
, pollLast()
, pop()
, push()
, removeFirst()
, removeFirstOccurrence()
, removeLast()
, removeLastOccurrence()
, size()
.Реализация ArrayDeque<T>
с помощью массива - наиболее удобная и эффективная.
AbstractCollection
и реализует интерфейс Deque
.isEmpty()
, clone()
, toArray()
.java.util.Arrays
предоставляет статические методы для манипуляций с массивами, такие как: binarySearch()
, equals()
, fill()
, sort()
.
java.util.Collections
предоставляет статические методы для манипуляций с массивами, такие как: binarySearch()
, fill()
, sort()
, copy()
, enumeration()
, indexOfSubList()
, lastIndexOfSubList()
, list()
, max()
, min()
, nCopies()
, replaceAll()
, reverse()
, reverseOrder()
, rotate()
, shuffle()
, singleton()
, singletonList()
, singletonMap()
, swap()
, synchronizedCollection()
, synchronizedList()
, synchronizedMap()
, synchronizedSet()
, synchronizedSortedMap()
, synchronizedSortedSet()
, unmodifiableCollection()
, unmodifiableList()
, unmodifiableMap()
, unmodifiableSet()
, unmodifiableSortedMap()
, unmodifiableSortedSet()
.
Иерархия коллекций
Интерфейс Map<K, V>
представляет абстракцию ассоциативного массива (словаря, отображения). Он хранит пары (ключ, значчение) и поддерживает три основные операции: put
, get
, remove
. При этом предполагается, что ключи уникальны. Если операция put
вызывается с ключом, который уже есть в ассоциативном массиве, соответствующее значение будет заменено.
AbstractMap
реализует большинство методов Map
интерфейса.clear()
, containsKey()
, containsValue()
, entrySet()
, equals()
, get()
, hashCode()
, isEmpty()
, keySet()
, put()
, putAll()
, remove()
, size()
, values()
.Интерфейс SortedMap<K, V>
обозначает словарь, в котором на ключах задано отношение порядка. Аналогично SortedSet<T>
, SortedMap<K, V>
предоставляет дополнительные операции. Предполагается, что эти операции словарь способен выполнять эффективно.
Map
интерфейса.comparator()
, firstKey()
, headMap()
, lastKey()
, subMap()
, tailMap()
.Реализация HashMap<K, V>
- словарь на основе хеш-таблицы. Из-за этого все операции над HashMap
очень эффективны. HashMap реализован как хеш-таблица на основе цепочек. Внутри он содержит массив «корзин», каждая из которых является односвязным списком. Поэтому элементы словаря должны корректно реализовывать методы equals()
и hashCode()
. Для идеальной хеш-функции эффективность операций константная.
AbstractMap
и реализует Map
интерфейс.clone()
.Реализация LinkedHashMap<K, V>
объединяет хеш-таблицу и связный список. Используется, когда необходимо сохранять порядок добавления элементов в словарь. Помимо структуры хеш-таблицы, LinkedHashMap
добавляет новые записи в связный список. С помощью этого можно восстановить порядок добавления элементов. Эффективность операций у LinkedHashMap
та же, что и у обычного HashMap
, но из-за дополнительной структуры на элементах потребление памяти выше.
HashMap
и реализует Map
интерфейс.removeEldestEntry()
.Реализация TreeMap<K, V>
— это реализация словаря на основе красно-чёрного бинарного дерева поиска (дерево образуют ключи). Эта структура требует отношения порядка на элементах, поэтому TreeMap
реализует интерфейс SortedMap
. Поскольку внутри TreeMap
используется бинарное дерево, то все операции имеют логарифмическую эффективность.
AbstractMap
и реализует SortedMap
интерфейс.clone()
.Иерархия мапов