Skip to content

Instantly share code, notes, and snippets.

@vchernogorov
Last active January 8, 2023 19:48
Show Gist options
  • Save vchernogorov/cacded15f0617c926234994fd63dc683 to your computer and use it in GitHub Desktop.
Save vchernogorov/cacded15f0617c926234994fd63dc683 to your computer and use it in GitHub Desktop.
Java SE

Базовые конструкции

  1. Типы данных - в Java существует два типа данных: примитивные и ссылочные:

    • Примитивные типы: byte, short, int, float, double, long, boolean, char.
    • Ссылочные типы: обертки примитивных типов, объекты классов, массивы.
  2. Операции - операции в Java разделяются на следующие группы:

    • Арифметические операции: +, -, /, *, %, ++, --.
    • Сравнительные операции: ==, !=, >, >=, <=, <.
    • Побитовые операции: &, |, ^, ~, <<, >>, >>>.
    • Логические операции: &&, ||, !.
    • Операции присваивания: =, +=, -=, *=, /=, %=, <<=, >>=, &=, ^=, |=.
    • Прочие операции: () ? () : (), instanceof
  3. Строка - последовательность символов, в Java строки являются объектами.

    • Строки реализованы с помощью класса String.
    • Строки в Java неизменяемы (immutable) в целях безопасности, поэтому строки могут кэшировать свой хэшкод, что делает ее очень быстрой как ключ для HashMap. При том, строки могут свободно использоваться различными потоками, не боясь, что кто-то их изменит, таким образом отпадает необходимость в синхронизации.
    • Если строку нужно изменять, то следует использовать StringBuilder или StringBuffer.
    • StringTokenizer - позволяет разбивать текст на лексемы, отделяемые разделителями. Парсит данные. Быстрый. Не поддерживает регулярные выражения. Устаревший.
    • String.split - позволяет разбивать текст на лексемы, отделяемые разделителями. Поддерживает регулярные выражения. Возвращаемым значением является массив строк. Работает медленее, чем StringTokenizer.
    • Formatter - обеспечивает преобразование формата, позволяющее выводить числа, строки, время и даты в любом необходимом разработчику виде.
    • Pattern - применяется для определения регулярных выражений (шаблонов), для которых ищется соответствие в строке, файле или другом объекте, представляющем последовательность символов.
    • Matcher - если необходимо найти соответствия внутри строки, необходимо использовать этот класс.
  4. Массив - фиксированная структура данных.

    • Массивы в Java объявляются следующим образом:
    dataType[] arrayRefVar = new dataType[arraySize];
    dataType[] arrayRefVar = {value0, value1, ..., valueK};
    • Также существует Arrays класс, который предоставляет статические методы для манипуляций с массивами, такие как:
    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)

Коллекции

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

  2. Интерфейс Collection<T> является базовым интерфейсом для линейных коллекций. Он предоставляет основные операции, общие для всех коллекций.

    • Данный интерфейс предоставляет следующие методы: add(), addAll(), clear(), contains(), containsAll(), equals(), hashCode(), isEmpty(), iterator(), remove(), removeAll(), size(), toArray().
    • Абстрактный класс AbstractCollection реализует большинство методов этого интерфейса.
  3. Интерфейс List<T> является одним из наиболее часто используемых интерфейсов коллекций, который обозначает упорядоченную коллекцию. Каждый элемент списка имеет целочисленный индекс; возможно добавление и удаление элементов по индексу. Дополнительно этот интерфейс предоставляет специальный итератор ListIterator<T>, который позволяет перемещаться по списку в обе стороны и вставлять новые элементы.

    • Данный интерфейс предоставляет следующие методы: get(), indexOf(), lastIndexOf(), listIterator(), set(), subList().
    • Абстрактный класс AbstractList наследуется от AbstractCollection и реализует большинство методов List интерфейса.
    • Абстрактный класс AbstractSequentialList наследуется от AbstractList и реализует большинство методов List интерфейса с упором на последовательный, чем на случайный доступ к элементам.
  4. Реализация ArrayList<T> используется чаще всего в интерфейсе List. По сути является реализацией списка на основе массива. Кроме того, ArrayList очень эффективно использует память, и операции, основанные на доступе по индексу (сортировка, перемешивание, бинарный поиск и т.д.), выполняются быстро.

    • Данная реализация предоставляет следующие методы: ensureCapacity(), removeRange(), trimToSize(), clone().
  5. Реализация LinkedList<T> используется гораздо реже. Является реализацией списка на основе двусвязного списка. LinkedList эффективнее при вставке/удалении элементов в начале или конце и при вставке/удалении в середине после итерации до нужного места. Также LinkedList потребляет значительно больше памяти, чем ArrayList.

    • Данная реализация предоставляет следующие методы: addFirst(), addLast(), clone(), getFirst(), getLast(), removeFirst(), removeLast().
  6. Интерфейс Set<T> предоставляет абстракцию математического множества, т.е. неупорядоченную коллекцию, не содержащую одинаковых элементов. Из-за неупорядоченности элементы множества нельзя получить по их индексу, поэтому для множеств не имеет смысла сортировка и перемешивание элементов. Однако при этом операции проверки на наличие элемента во множестве эффективнее, чем в списке.

    • Данный интерфейс предоставляет следующие методы: isEmpty().
    • Абстрактный класс AbstractSet наследуется от AbstractCollection и реализует большинство методов Set интерфейса.
  7. Интерфейс SortedSet<T> является расширением Set<T>. Он предполагает наличие отношения порядка на своих элементах. Из-за этого SortedSet предоставляет дополнительные операции.

    • Данный интерфейс предоставляет следующие методы: clone(), comparator(), first(), headSet(), last(), subSet(), tailSet().
  8. Реализация HashSet<T> — это наиболее часто используемая реализация множества, потому что основные задачи множества она выполняет наиболее эффективно. HashSet основан на HashMap. Поэтому, в частности, для использования HashSet необходима правильная реализация методов equals() и hashCode().

    • Данная реализация наследуется от AbstractSet.
    • Данная реализация предоставляет следующие методы: clone().
  9. Реализация LinkedHashSet<T> объединяет множество на основе хеш-таблицы и связный список. Эффективность всех операций на нём та же, что и у HashSet, но порядок итерации по нему не псевдослучаен, а соответствует порядку добавления элементов в это множество. LinkedHashSet основан на LinkedHashMap и наследует HashSet, поэтому для него также справедливы условия на методы equals() и hashCode() у элементов.

    • Данная реализация наследуется от HashSet.
  10. Реализация TreeSet<T> — это множество, основанное на TreeMap. Оно реализует интерфейс SortedSet<T>, и в нём могут храниться только элементы, на которых задано отношение порядка. Класс TreeSet основан на TreeMap, и поэтому все операции над элементами имеют логарифмическую сложность. Это хуже, чем у HashSet, поэтому TreeSet используется только тогда, когда необходимо так или иначе сортировать элементы множества.

    • Данная реализация наследуется от AbstractSet.
    • Данная реализация предоставляет следующие методы: clone(), comparator(), first(), last(), headSet(), subSet(), tailSet().
  11. Интерфейс Queue<T> представляет собой контейнер, в который можно добавлять элементы и доставать их оттуда. Релизации Queue<T> могут ограничивать максимальное количество элементов в коллекции. Поэтому Queue<T> предоставляет два набора методов для указанных операций. Первый набор в граничных ситуациях выбрасывает исключение, а второй — возвращает специальное значение (null или boolean).

    • Абстрактный класс AbstractQueue наследуется от AbstractCollection и реализует большинство методов Queue интерфейса.
    • Данный интерфейс предоставляет следующие методы: offer(), peek(), poll().
  12. Интерфейс Deque<T> обозначает дек, структуру данных, являющуюся одновременно стеком и очередью. В дек можно добавлять и удалять элементы с двух сторон.

    • Данный интерфейс предоставляет следующие методы: offer(), peek(), poll(), addFirst(), addLast(), descendingIterator(), element(), getFirst(), getLast(), offerFirst(), offerLast(), peekFirst(), peekLast(), pollFirst(), pollLast(), pop(), push(), removeFirst(), removeFirstOccurrence(), removeLast(), removeLastOccurrence(), size().
  13. Реализация ArrayDeque<T> с помощью массива - наиболее удобная и эффективная.

    • Данная реализация наследуется от AbstractCollection и реализует интерфейс Deque.
    • Данный интерфейс предоставляет следующие методы: isEmpty(), clone(), toArray().
  14. java.util.Arrays предоставляет статические методы для манипуляций с массивами, такие как: binarySearch(), equals(), fill(), sort().

  15. 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().

  16. Иерархия коллекций
    Иерархия коллекций

Многопоточность в Java

  1. Многопоточность - это когда множество процессов делят общие вычислительные ресурсы, такие как CPU, между собой.

    • Многопотчная программа содержит 2 или более частей, который могут работать одновременно, и каждая часть может выполнять свое действие, тем самым создавая оптимальные условия для использования доступных ресурсов.
    • Многопоточность расширяет идею многозадачности в приложениях, где можно разделить определенные операции в индивидуальные потоки.
    • Операционная система разделяет вычислительное время не только между различными программами, но и между потоками этих приложений.
  2. Поток в Java представлен классом java.lang.Thread, объекты которого являются потоками, работающими внутри текущей JVM.

    • Каждый поток может работать параллельно.
    • Начиная с версии 1.5 в состав стандартной библиотеки Java входит пакет java.util.concurrent, в котором содержится большое количество различных классов, помогающих при разработке многопоточных программ.
  3. Создание потока. Для того, чтобы выполнить какую-либо задачу в отдельном потоке, можно создать новый поток с помощью конструктора класса Thread, передать ему Runnable и запустить его.

    • Пример создания потока:
    new Thread(new Runnable() {
        @Override public void run() { /* ... */ }
    }).start();
    new Thread(() -> { /* ... */ }).start();
  4. Создание сервисного потока. Выполнение Java-машины завершается, когда завершатся все потоки, не являющиеся сервисными, т.е. те, у которых не установлен флаг daemon.

    • Пример создания сервисного потока:
    Thread t = new Thread(() -> { ... });
    t.setDaemon(true);
    t.start();
  5. Критические секции. При работе потоков с общей изменяемой памятью неизбежно возникает проблема синхронизации действий этих потоков.

    • Самым простым способом упорядочить работу потоков с общими данными являются synchronized-блоки.
  6. synchronized-блоками обозначаются критические секции — участки кода, которые в каждый момент времени могут выполняться только одним потоком.

    • Синхронизация потоков всегда происходит с использованием какого-либо объекта.
    • Поток, входящий в synchronized-блок, захватывает монитор, связанный с объектом этого блока.
    • Пример создания synchronized-блока:
    private static final Object lock = new Object();
    private static void transfer(int amount) {
        synchronized (lock) {
            account1 = account1 - amount;
            account2 = account2 + amount;
        }
    }
  7. Замки - являются более мощной версией synchronized-блока. Основные интерфейсы замков — java.util.concurrent.locks.Lock и ReadWriteLock, а наиболее полезные классы — ReentrantLock и ReentrantReadWriteLock.

    • Пример создания замка:
    private static final Lock lock = new ReentrantLock();
    lock.lock();
    try {
        // критическая секция
    } 
    finally { 
        lock.unlock(); 
    }
  8. Пулы потоков - это набор потоков, которым можно передавать какие-либо задачи (например, Runnable) на выполнение.

    • Создание потока — дорогая операция, и часто большинство задач выполняются недолго. Поэтому имеет смысл переиспользовать уже созданные потоки для различных задач.
    • Пример создания пула потоков:
    Executor executor = Executors.newFixedThreadPool(4);
    executor.execute(() -> /* ... */ );
    executor.execute(new Runnable() {
        @Override public void run() { /* ... */ } 
    });
  9. Жизненный цикл потока. Поток проходит через несколько стадий своего жизненного цикла:

    • New - новый поток начинает свой жизненный цикл с изначального состояния. Он остается в нем до тех пор, пока программа не запустит его.
    • Runnable - после того, как поток создался, его надо запустить, в связи с чем, он перейдет в данное состояние. Поток в таком состоянии уже выполняет свои функции.
    • Waiting - иногда переходы между потоками занимают некоторое время, во время которого поток находится в таком состоянии, до тех пор, пока другой поток не переведет его в состояние runnable.
    • Timed waiting - runnable поток может установить время ожидания для какого-то события, после чего перейдет в данное состояние. Он перейдет обратно в runnable только после того, как истечет указанное время, или если событие, которого он ждет, произойдет.
    • Terminated - runnable поток завершается после выполнения своих функций (или его завершают) и переходит в данное состояние.
    • Диаграмма жизненого цикла потока: Диаграмма жизненого цикла потока
  10. Приоритет - каждый поток имеет приоритет, который помогает операционной системе распознавать порядок в котором потоки будут работать: MIN_PRIORITY, NORM_PRIORITY, MAX_PRIORITY.

Элементы Java

  1. Пакет - это именованная логическая группа классов. Пакеты непосредственно соответствуют иерархии в файловой системе.

  2. Импортирование имен - способ ссылки на классы из другого пакета. При импортировании простое имя типа погружается в текущую область видимости имён, и его можно использовать непосредственно, без указания имени пакета.

  3. Класс — это описания структуры и поведения объектов. Классы записываются программистом в виде исходного кода и компилируются в байт-код. Имея байт-код классов, виртуальная машина способна создавать объекты и обеспечивать вызов их методов.

    • Шаблон определения класса:
    [public] [final|abstract] class ClassName 
    [extends OtherClass] 
    [implements Interface1, Interface2] {}
  4. Объекты — это участки памяти виртуальной машины, содержащие своё состояние в виде полей.

    • Шаблон определения поля объекта:
    [public|protected|private] [static] [final] Type field;
  5. Метод — это просто функция, которая неявным параметром принимает объект, на котором она вызывается. Таким образом, отправка сообщения сводится к вызову функции.

    • Шаблон определения поля объекта:
    [public|protected|private] [static|abstract|final] Type method(Type param) {}
  6. Абстрактный класс — это такой класс, часть функционала которого не реализована, но задекларирована.

  7. Интерфейс в Java можно понимать как класс, содержащий только абстрактные методы. Интерфейс предназначен для описания абстракций или контрактов, которые должен предоставлять класс, реализующий этот интерфейс.

  8. Функция — именованный блок кода, возможно, принимающий некоторые данные извне (параметры/аргументы) и, возможно, возвращающий некоторый результат.

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

    • В Java все методы виртуальные.
  10. Вложенный класс — используется для более тонкой организации классов, чем с помощью пакетов.

    • Существует несколько типов вложенных классов: вложенные статические, внутренние, анонимные, локальные.
    • Вложенными могут быть также интерфейсы, перечисления и аннотации.
    • Шаблон определения вложенного класса:
    [public|protected|private] [static] [abstract|final] class NestedClass {}
  11. Лямбда-выражение — часть парадигмы функционального программирования. Предназначены для замены слишком многословного синтаксиса анонимных классов.

    • Шаблон определения лямбда-выражения:
    (Type param) -> { /* body */ }
  12. Перечисление — специальный тип данных, предусмотренный для ограничения множества допустимых значений для некоторого типа данных.

    • Шаблон определения перечисления:
    [public] enum EnumName [implements Interface1, Interface2] {}
  13. Конструктор — это специальный метод, который автоматически вызывается при создании объекта и инициализирует его состояние.

    • Конструктор по умолчанию не создаётся, если в классе объявлен явно другой конструктор.
    • Шаблон определения конструктора:
    [public|protected|private] ClassName(Type param) {}
  14. Дженерики — реализация обобщенного программирования, включающая в себя поддержку обобщенных классов и обобщенных методов.

    • В первую очередь дженерики были нужны для создания типобезопасной библиотеки коллекций, т.е. с проверкой типов на этапе компиляции, а не в рантайме.
    • Пример определения дженериков:
    public class SomeClass<T1, T2, ...> {}
    <T1, T2, ..., E [extends|super] ClassName> R method(T1 p1, T2 p2, ...) throws E {}
  15. Итератор - объект, предоставляющий доступ к элементам коллекции и навигацию по ним.

    • Каждый класс коллекций наследуется от интерфейса Iterable.
    • Существуют 2 типа итераторов: Iterator и ListIterator. Второй наследуется от первого и предоставляет больше методов.
  16. Аннотации - дескрипторы, включаемые в текст программы. Используются для хранения метаданных программного кода, необходимых на разных этапах жизненного цикла программы.

    • Пример определения аннотации.
    import java.lang.annotation.*;
    @Target(value=ElementType.FIELD)
    @Retention(value= RetentionPolicy.RUNTIME)
    public @interface Name {
        String name();
        String type() defaultstring”;
    }
  17. Shadowing - сокрытие объявления может произойти, когда объявляется ещё одна сущность того же рода с тем же именем в более узкой области видимости. В таком случае к исходной сущности нельзя обращаться по простому имени.

  18. Obscuring может произойти, когда существует неоднозначность имени между разными пространствами имён (например, имя переменной совпадает с именем пакета). Такое случается крайне редко.

  19. Hiding - скрытие имен происходит во время наследования, если в родительском и дочернем классе есть одинаковые статические методы.

    • Пример сокрытия:
    public class Test {
        public static void testClassMethod() {
        }
    }
    public class StandartTest extends Test {
        public static void testClassMethod() {
        }
    }
  20. Overriding - процесс перегрузки метода, который происходит во время наследования, если в дочернем классе есть одинаковые нестатические методы.

    • Переруженный метод в Java принято помечать аннотацией @Override.
    • Пример перегрузки:
    public class Test {
        public void testInstanceMethod() {
        }
    }
    public class StandartTest extends Test {
        public void testInstanceMethod() {
        }
    }
  21. Исключение - ошибка, возникающая во время выполнения программы. Исключения сигнализируют о возникновении ошибочной ситуации, из-за которой программа не может выполняться дальше. Поэтому исключения вызывают раскрутку стека вызовов. Когда какой-либо метод выбрасывает исключение, виртуальная машина начинает выталкивать элементы из стека вызовов (как будто произошёл возврат из каждого метода) до тех пор, пока не найдёт обработчик, который сможет обработать это исключение. Если такой обработчик нашёлся, то управление передаётся в него, и код внутри этого обработчика может либо продолжить выполнение программы, либо выбросить ещё одно исключение.

    • Исключения в Java разделяются на checked, unchecked и errors.
    • Checked-исключения - наследники класса Exception. Метод обязан либо обработать эти исключения, либо явно объявить (с помощью декларации throws), что он их выбрасывает.
    • Uncheked-исключения - наследники класса RuntimeException. Их объявлять и отлавливать необязательно.
    • Специальные исключения (errors) - наследники класса 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 {}
    }
  22. JavaBeans - компоненты (бины), обеспечивающие основу для многократно используемых, встраиваемых и модульных компонентов ПО. Компоненты JavaBeans могут принимать различные формы, но наиболее широко они применяются в элементах графического пользовательского интерфейса. [[source]][javabeans]

    • Одна из целей создания JavaBeans — взаимодействие с похожими компонентными структурами.
    • Чтобы класс мог работать как bean, он должен соответствовать определённым соглашениям:
      • Класс должен иметь конструктор без параметров, с модификатором доступа public. Такой конструктор позволяет инструментам создать объект без дополнительных сложностей с параметрами.
      • Свойства класса должны быть доступны через get, set и другие методы (так называемые методы доступа), которые должны подчиняться стандартному соглашению об именах. Это легко позволяет инструментам автоматически определять и обновлять содержание bean’ов.
      • Класс должен быть сериализуем. Это даёт возможность надёжно сохранять, хранить и восстанавливать состояние bean независимым от платформы и виртуальной машины способом.
      • Класс должен иметь переопределенные методы equals(), hashCode() и toString().
    • Пример бина, как 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() {
            ...
        }
    }
  23. POJO (Plain Old Java Object) - простой Java-объект, не унаследованный от какого-то специфического объекта и не реализующий никаких служебных интерфейсов сверх тех, которые нужны для бизнес-модели. [[source]][pojo]

Дженерики

  1. Дженерики — реализация обобщенного программирования, включающая в себя поддержку обобщенных классов и обобщенных методов.

  2. Обобщенные классы - обобщенные (параметризованные) классы могут использоваться для следующих целей:

    • Коллекции и контейнеры: 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;
    }
    • Обобщенные DAO
    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; 
        }
    }
  3. Обобщенные методы - обобщенные (параметризованные) методы могут использоваться для следующих целей:

    • Обобщенные фабричные методы:
    public static <T extends Enum<T>> EnumSet<T> allOf(Class<T> clazz);
    public static <T> ImmutableList<T> of(T , T , 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);
  4. Wildcards - wildcards существуют трех типов:

    • Wildcards with upper bound:
    public static double sumOfList(List<? extends Number> list);
    • Unbounded wildcard
    void printCollection(Collection<?> c);
    • Wildcards with lower bound
    public static void addNumbers(List<? super Integer> list);

Мапы

  1. Интерфейс Map<K, V> представляет абстракцию ассоциативного массива (словаря, отображения). Он хранит пары (ключ, значчение) и поддерживает три основные операции: put, get, remove. При этом предполагается, что ключи уникальны. Если операция put вызывается с ключом, который уже есть в ассоциативном массиве, соответствующее значение будет заменено.

    • Абстрактный класс AbstractMap реализует большинство методов Map интерфейса.
    • Данный интерфейс предоставляет следующие методы: clear(), containsKey(), containsValue(), entrySet(), equals(), get(), hashCode(), isEmpty(), keySet(), put(), putAll(), remove(), size(), values().
  2. Интерфейс SortedMap<K, V> обозначает словарь, в котором на ключах задано отношение порядка. Аналогично SortedSet<T>, SortedMap<K, V> предоставляет дополнительные операции. Предполагается, что эти операции словарь способен выполнять эффективно.

    • Данный интерфейс наследуется от Map интерфейса.
    • Данный интерфейс предоставляет следующие методы: comparator(), firstKey(), headMap(), lastKey(), subMap(), tailMap().
  3. Реализация HashMap<K, V> - словарь на основе хеш-таблицы. Из-за этого все операции над HashMap очень эффективны. HashMap реализован как хеш-таблица на основе цепочек. Внутри он содержит массив «корзин», каждая из которых является односвязным списком. Поэтому элементы словаря должны корректно реализовывать методы equals() и hashCode(). Для идеальной хеш-функции эффективность операций константная.

    • Данная реализация наследуется от AbstractMap и реализует Map интерфейс.
    • Данная реализация предоставляет следующие методы: clone().
  4. Реализация LinkedHashMap<K, V> объединяет хеш-таблицу и связный список. Используется, когда необходимо сохранять порядок добавления элементов в словарь. Помимо структуры хеш-таблицы, LinkedHashMap добавляет новые записи в связный список. С помощью этого можно восстановить порядок добавления элементов. Эффективность операций у LinkedHashMap та же, что и у обычного HashMap, но из-за дополнительной структуры на элементах потребление памяти выше.

    • Данная реализация наследуется от HashMap и реализует Map интерфейс.
    • Данная реализация предоставляет следующие методы: removeEldestEntry().
  5. Реализация TreeMap<K, V> — это реализация словаря на основе красно-чёрного бинарного дерева поиска (дерево образуют ключи). Эта структура требует отношения порядка на элементах, поэтому TreeMap реализует интерфейс SortedMap. Поскольку внутри TreeMap используется бинарное дерево, то все операции имеют логарифмическую эффективность.

    • Данная реализация наследуется от AbstractMap и реализует SortedMap интерфейс.
    • Данная реализация предоставляет следующие методы: clone().
  6. Иерархия мапов
    Иерархия мапов

Модификаторы

  1. private (переменные / конструкторы / методы / внутренние классы) - члены класса доступны только внутри класса.

  2. package-private или default (переменные / конструкторы / методы / классы) - члены класса видны внутри пакета.

  3. protected (переменные / методы / конструкторы / внутренние классы) - члены класса доступны внутри пакета и в классах-наследника.

  4. public (все) - члены класса доступны всем.

  5. static (логические блоки / переменные / методы / классы) - статические блоки выполняются во время загрузки класса. К статическим методам и переменным можно обращаться через имя класса.

  6. abstract (методы / классы) - абстрактные классы должны наследоваться, а абстрактные методы - реализовываться.

  7. final (переменные / методы / классы) - переменные, которым было присвоино значение, не могут быть переприсвоены. Методы не могут быть перегруженны. Классы не могут быть наследованы.

  8. synchronized (методы / части метода) - метод может одновременно использоваться только одним потоком.

  9. transient (переменные) - переменная не сериализуется. Локальные переменные не могут быть объявлены как transient.

  10. volatile (переменные) - значение переменной, объявленной как volatile, измененное одним потоком, асинхронно меняется и для других потоков.

  11. native (методы) - обозначает, что метод написан на другом языке программирования.

  12. strictfp (методы / классы) - обеспечивает выполнение операций над числами типа float и double (с плавающей запятой) по стандарту IEEE 754.

ООП в Java

  1. ООП (Объектно Ориентированное Программирование) - методология программирования, основанная на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определенного класса, а классы в свою очередь образуют иерархию наследования.

  2. Инкапсуляция - сокрытие реализации.

    • Реализуется с помощью модификаторов видимости: default, public, protected, private.
  3. Полиморфизм - парадигма ООП. Существует несколько его разновидностей:

    • Ad-hoc (ситуативный) полиморфизм — функция по-разному работает с данными разных типов из заранее фиксированного набора. Реализуется с помощью перегрузки методов.
    • Параметрический полиморфизм — функция работает одинаково с данными произвольных типов. Реализуется с помощью дженериков и параметризованных классов.
    • Полиморфизм подтипов — функция работает одинако-во с данными типов, являющихся подтипами одного общего супер-типа, редоставляющего общий интерфейс. Реализуется с помощью наследования и иерархии классов.
    • Динамический полиморфизм — то, какой метод (из суперкласса или из подкласса) будет вызван, зависит от настоящего типа объекта, т.е. от того, объект какого класса на самом деле содержится в переменной. Реализуется с помощью позднего связыванания.
  4. Наследование - возможность создавать потомков и переопределять часть функциональности класса.

    • Реализуется с помощью ключевого слова extends.
    • Java не поддерживает множественное наследование классов.
  5. Абстракция - это выделение общих характеристик объекта, отличая от всех других объектов.

    • Реализуется с помощью абстрактных классов и интерфейсов.
  6. Класс — это описание структуры и поведения объектов.

  7. Объекты — это участки памяти виртуальной машины, содержащие своё состояние в виде полей.

Общее

  1. JRE (Java Runtime Environment) — минимальная реализация виртуальной машины, необходимая для исполнения Java-приложений, без компилятора и других средств разработки. Включает в себя:

    • Виртуальную машину — Java Virtual Machine
    • Библиотеки Java-классов.
  2. JDK (Java Development Kit) — бесплатно распространяемый компанией Oracle Corporation (ранее Sun Microsystems) комплект разработчика приложений на языке Java. Он включает в себя:

    • Компилятор Java (javac)
    • Стандартные библиотеки классов Java
    • Примеры, документацию, различные утилиты
    • Исполнительную систему Java (JRE).
  3. JVM (Java Virtual Machine) — виртуальная машина Java — основная часть JRE.

    • Виртуальная машина Java интерпретирует Байт-код Java, предварительно созданный из исходного текста Java-программы компилятором Java (javac).
    • JVM может также использоваться для выполнения программ, написанных на других языках программирования.
    • HotSpot - основная JVM для настольных компьютеров и серверов, выпускаемая корпорацией Oracle.
  4. Байт-код — набор инструкций, исполняемых виртуальной машиной Java.

    • Для обеспечения кроссплатформенности программа сначала компилируется в промежуточный язык низкого уровня — байт-код.
    • Если выполнение байт-кода на JVM нежелательно, исходный код на языке Java или Java байт-код может быть скомпилирован напрямую в нативный машинный код.
  5. Динамическая компиляция JIT (Just In Time) - технология увеличения производительности программных систем, использующих байт-код, путём компиляции байт-кода в машинный код или в другой формат непосредственно во время работы программы. Большинство реализаций JIT имеют последовательную структуру:

    • Сначала приложение компилируется в байт-код виртуальной машины среды исполнения (AOT-компиляция).
    • Потом JIT компилирует байт-код непосредственно в машинный код.
    • В итоге при запуске приложения тратится лишнее время, что, впоследствии, компенсируется более быстрой его работой.
  6. Garbage Collector - одна из форм автоматического управления памятью.

    • Все объекты к которым невозможно добраться с корневых точек будут считаться мусором.
    • HotSpot VM использует именно такой подход.
    • Память освобождается сборщиком мусора по его собственному "усмотрению"
@angstream555
Copy link

to override - переопределять, to overload - перегружать.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment