Java: fill the gaps
12.9K subscribers
7 photos
215 links
Привет! Меня зовут Диана, и я занимаюсь разработкой с 2013. Здесь пишу просто и понятно про джава бэк

🔥Тот самый курс по многопочке🔥
https://fillthegaps.ru/mt

Комплименты, вопросы, предложения: @utki_letyat
Download Telegram
Java 14 features

Меньше двух недель осталось до выхода новой версии java. 17 марта анонсирован релиз JDK 14. В нём будет 16 фич, давайте посмотрим на некоторые из них.

1️⃣ Текстовые блоки — многострочные строки, ограниченные тремя двойными кавычками.
String html = """
select *
from users
""";
То, ради чего многие перешли на котлин, теперь есть и в java.
Удобно для чтения и написания частей HTML, XML, SQL, JSON.

2️⃣ Изменения в switch.
появился способ не писать break. Если использовать вместо двоеточия стрелочку
то выполнится только код этого кейса.
case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);

Напомню, что если в обычной форме не написать в конце блока break, то поиск соответствий после выхода из блока продолжится. В примере напечатаются обе строки:
case 1: System.out.println("1");
default: System.out.println("0");

switch теперь возвращает значение. Если строк много, то используется слово yield.
int j = switch (day) {
case MONDAY -> 0;
case TUESDAY -> 1;
default -> {
int res = f(k);
yield res;
}
};

3️⃣ Сокращение размера кода при сужении типа. Каждому, кто переопределял метод equals, знаком этот паттерн:
if(o instanceof String) {
String s = (String) o;
// use s
}

Теперь проверка и приведение типа объединены:
if(o instanceof String str) {
// can use str here
}

Если в if несколько условий, то область видимости переменной зависит от типа их связи. В условиях, соединённых через И, переменную можно использовать:
if(o instanceof String s && s.length() > 5)

В условиях, соединённых через ИЛИ, переменная не будет видна:
if(o instanceof String s || s.length() > 5)

4️⃣ Больше информации в NullPointerException.
Теперь при возникновении исключения будет доступна не только строка, где это произошло, но и описание ситуации.
Exception in thread "main" java.lang.NullPointerException:
Cannot read field "j" because "b" is null
at Pr.main(Pr.java:5)

По умолчанию эта фича не работает, для её включения нужно установить флаг:
-XX:+ShowCodeDetailsInExceptionMessages

#core
👍72🔥2
10 must-have навыков java разработчика в 2020.

1️⃣ Понимать принципы CI/CD.
В 2020 разработчик представляет себе весь процесс релиза - от коммита до выхода в продакшн и умеет пользоваться инструментами devOps— Jenkins, Docker, Kubernetes, Chef, Ansible.

2️⃣ Применять фичи Java 8-13.
Новая версия Java выходит каждые полгода. Тренды и инструменты разработки меняются быстро, но язык программирования — основа каждой системы. Изучение его возможностей должно стать приоритетом.

3️⃣ Знать Spring framework и его проекты.
Большинство энтерпрайз решений используют Spring как основной фреймворк. К нему часто прибавляется Spring MVC, Spring Boot, Spring Data и Spring Cloud. Знать возможности спринга и уметь ими пользоваться — необходимый навык в 2020.

4️⃣ Писать качественные тесты.
Тестирование — основной инструмент повышения качества кода. Чем больше и сложнее продукт, тем выше его роль. Junit и Mockito — основные библиотеки для юнит-тестов, Testcontainers и Spring Test — для интеграционного.

5️⃣ Пользоваться библиотеками.
Вместо самописного велосипеда лучше использовать уже оптимизированные и протестированные методы из библиотек. Jackson and Gson для JSON, JAXB для работы с XML, SLF4j — для логгирования, Google Guava и Apache Commons помогут сконцентрироваться на бизнес-задачах.

6️⃣ Понимать работу JVM.
Из каких частей состоит JVM и как они взаимодействуют. JIT, JVM опции, виды и принципы сборки мусора, умение профилировать приложение и анализировать результаты — необходимые шаги к высокопроизводительным приложениям.

7️⃣ Применять паттерны проектирования
Это поможет писать тестируемый и расширяемый код. Паттерны GoF и параллельного программирования — базовый арсенал разработчика при решении задач.

8️⃣ Изучать другие языки программирования.
Изучение других подходов к решению задач расширяет кругозор и помогает в работе. Для Java разработчиков основной источник вдохновения - Kotlin, но изучить Scala, JavaScript, Go или Python — тоже хорошая идея.

9️⃣ Знать принципы разработки микросервисной архитектуры.
Микросервисы — глобальный тренд, всё больше проектов предпочитают этот подход монолиту. Spring Cloud и Spring Boot – основной инструментарий для построения микросервисов.

🔟 Эффективно пользоваться IDE.
Повысить продуктивность в несколько раз — это не шутка. Изучите комбинации горячих клавиш и доступные плагины для IDE – и жизнь больше не будет прежней.

#прочее
7👍4🔥1
5 неочевидных советов, чтобы пройти (почти) любое собеседование

Как обычно кандидаты готовятся к предстоящему интервью? Читают документации и ответы на распространённые технические вопросы. Факт, о котором часто забывают — на прохождение собеседования влияют совсем другие факторы.
Если Вас позвали на интервью — работодатель уже заинтересован в Вас и сформировал некоторые ожидания. Дело за малым - подтвердить указанные в резюме навыки и показать себя в выгодном свете.

5 важных рекомендаций для успешного интервью:

1️⃣ Улыбайтесь.
Решение о найме часто принимается в первые 2 минуты общения, а следующий час интервьюер ищет подтверждение сделанному выбору. Улыбка - самый простой способ повысить доверие и очаровать собеседника.

2️⃣ Подготовьте рассказ о предыдущем проекте.
Опыт - главный актив разработчика и правильно его преподнести — 70% успеха на собеседовании. Как это сделать — тема отдельного поста. Кратко - ценный сотрудник - это тот, кто видит общую картину проекта и понимает свой вклад в неё.

3️⃣ Говорите чётко и структурированно, не перебивайте.
Умение формулировать и доносить свои мысли - основа взаимодействия с будущими коллегами. Какими бы глубокими ни были Ваши знания java, для работы в команде нужны навыки эффективного общения.

4️⃣ Расскажите о своих приоритетах.
Работа на результат, чистый код или производительность - не просто красивые слова, а то, на чём основываются ежедневные решения. Постарайтесь донести свои ценности до интервьюера.
Подсказка: упоминайте приоритеты при ответах на технические вопросы. Сложный концептуальный вопрос — опишите несколько вариантов и упомяните, что решение лучше обсудить с опытными коллегами. Задача с запутанным синтаксисом - упомяните, что Вы за читаемость и никогда не будете так писать.

5️⃣ Задавайте много вопросов о будущем проекте и команде.
Во-первых, поймёте, подходит ли Вам эта работа.
Во-вторых, можно ещё раз указать на свои сильные стороны и широкий кругозор. Спросите, когда будет переход на новую версию спринга, какой у проекта процесс релиза, как проходит тестирование. Аккуратно поинтересуйтесь, можно ли будет повлиять на улучшение процесса — и можно считать, что оффер у Вас в кармане.

Удачных собеседований!

#собеседование
👍6🔥21
Блокировки в HotSpot JVM

Java Virtual Machine(JVM) - это посредник между скомпилированной кодом и операционной системой (ОС). Благодаря такой схеме можно легко запускать java приложения на разных платформах. Реализаций JVM много, но самой распространённой является бесплатная HotSpot от OpenJDK.

JVM не просто переводит java команды в команды ОС. Виртуальная машина реализуется так, чтобы выполнять код эффективнее и быстрее.
Рассмотрим, например, как HotSpot оптимизирует действие «взять блокировку».
У JVM есть 3 способа реализации:
▪️Fat или inflated : на основе мониторов объектов (мьютексов). Подходит для случаев, когда есть много претендентов на захват блокировки.
▪️Thin или deflated : с использованием CAS команд. Это быстрее, чем использовать мьютексы. Но из-за необходимости эксклюзивного доступа в условиях большой конкуренции между потоками этот подход неэффективен.
▪️Biased: оптимизированный тип блокировки для случаев, когда с объектом в основном работает один поток. При первом взаимодействии объект ассоциируется с потоком и дальнейшие действия происходят без лишних синхронизаций. Если другой поток захочет захватить блокировку, то начнётся глобальная перестройка или bulk revocation. Это очень неэффективно и для активно конкурирующих сценариев, например, producer-consumer, такой тип блокировки не подойдёт.

Biased блокировка отключена на старте приложения, потому что в этот момент происходит много междупоточных взаимодействий. Но спустя некоторое время она включается и является блокировкой по умолчанию.
Её можно отключить с помощью опции:
-XX:-UseBiasedLocking
Время включения после старта регулируется флажком
-XX:BiasedLockingStartupDelay=500
По умолчанию это значение равно четырём секундам.

Для большинства приложений вам не потребуется использовать эти опции. Но для специфичных случаев флажки JVM могут поднять производительность в разы.

#теория
👍2
Утренний java puzzle♨️

Проверь себя и узнай правильный ответ в статье через час.
Какую функциональность предоставляет HotSpot JVM?
anonymous poll

Только JVM – 144
👍👍👍👍👍👍👍 79%

JIT – 17
👍 9%

JRE – 14
👍 8%

JDK – 8
▫️ 4%

👥 183 people voted so far.
JDK, JRE, JVM, JIT и Java 11

Как связаны между собой эти аббревиатуры и что изменилось в java 11?

Жизненный цикл кода обычно описывают так:
1️⃣ Программист с помощью IDE (или блокнота) создаёт файлы с расширением .java
2️⃣ IDE или утилита javac компилирует их в байткод — файлы с расширением .class
3️⃣ JVM интерпретирует байткод в системные вызовы конкретной платформы.

Эта терминология не совсем точная. JVM — всего лишь спецификация, она предоставляет интерфейс для работы с классами, потоками, памятью, сборщиком мусора и тд. Это абстрактная сущность, физически её не существует.

Многие компании реализуют JVM - HotSpot, Azul, Excelsior и тд. Их продукт позволяет запускать программы и называется JRE (Java Runtime Environment). Помимо указанных в JVM методов JRE содержит библиотеки основных классов(rt.jar) и JIT(Just-in-time)-компилятор.
JVM функции обычно интерпретируются - просто исполняются строка за строкой. JIT-компилятор оптимизирует байткод для конкретной платформы и подставляет машинные команды прямо во время работы. Это сильно увеличивает производительность.

JDK(Java Development Kit) позволяет создавать и запускать программы. Он состоит из JRE и инструментов разработки, таких как компилятор javac, дебаггер jdb, генератор документации javadoc, архиватор jar и тд.

Кратко отношения между сущностями выглядят так:
JVM = спецификация
JRE = реализация JVM + JIT-compiler + библиотеки
JDK = JRE + инструменты разработки

JDK нужны только программистам, а тестовому окружению и продакшену для запуска программ хватает JRE. Поэтому на сайте вендоров JVM обычно представлены оба этих варианта - JDK и JRE для разных платформ.

Но всё изменилось после выхода Java 11. Теперь для скачивания доступна только JDK, а JRE отдельно не поставляется. Чтобы создать среду исполнения используется специальная утилита jlink, в ней указываются необходимые для приложения модули. Редко какой программе нужны все 75 модулей, поэтому полученная JRE занимает гораздо меньше памяти, не содержит лишних библиотек и работает быстрее.

Решение ориентировано на модульную архитектуру, тренд на которую начался в java 9. Второй фактор - популярность использования java на устройствах IoT. Здесь ключевую роль играет компактность JRE и ограниченность функций для повышения безопасности.

Cписок используемых модулей помогает получить утилита jdeps. К счастью, все популярные IDE уже поддерживают java 9, поэтому Вам вряд ли придётся самостоятельно формировать module-info.

#теория
👍4
Сегодня вышла JDK 14!

16 обновлений, среди которых:
компактный синтаксис record,
улучшенный switch,
многострочные текстовые блоки,
информативные NPE,
приведение типа прямо в instanceof.
2
Утренний java puzzle♨️

Сегодня разберём очень популярный вопрос на собеседованиях. Проверьте себя, а через час выйдет статья. Там будет правильный ответ и 3 бонуса, чтобы покорить сердце любого интервьюера
Integer a = 100;
Integer b = 100;
System.out.println(a == b);
Anonymous Poll
58%
true
31%
false
10%
когда как🤷‍♂️
Сравнение переменных на собеседованиях.

Начнём с основ. Переменная — именованное место в памяти для хранения какого-либо значения. Переменные в java делятся на 2 группы:
1️⃣ примитивные типы — int, char, long и тд. У них в памяти хранится само значение, поэтому следующий код выведет true:
int a = 500;
int b = 500;
System.out.println(a == b);
// true


2️⃣ ссылочные типы — Integer, Long, String и тд. Где-то в памяти лежит объект, а в этой переменной хранится указатель на него. При использовании оператора == сравниваются только ссылки, а не сами объекты. Поэтому даже если они по сути одинаковые, операция == вернёт false:
Integer a = 500;
Integer b = 500;
System.out.println(a == b);
// false


В рабочих проектах мы чаще работаем с объектами. А ещё часто используем небольшие числа, например, в циклах и счётчиках. Чтобы сократить количество создаваемых объектов, в java есть кэш для чисел от -128 до 127. Поэтому следующий код вернёт true:
Integer a = 100;
Integer b = 100;
System.out.println(a == b);
// true


Это правильный ответ на вопрос из предыдущего поста.
Примечание: это верно только при такой форме записи. Если использовать оператор new, то будет создан отдельный объект в памяти. Сравнение ссылок на два разных объекта всегда возвращает false:
Integer a = new Integer(50);
Integer b = 50;
System.out.println(a == b);
// false


Это базовая теоретическая часть, знакомая многим. Но на собеседовании нужно показать себя во всей красе, поэтому обязательно упомяните следующие 3 факта. Они серьёзно повысят Ваш рейтинг среди других кандидатов.
1️⃣ Для сравнения ссылочных типов по значению используется метод equals.
2️⃣ Механизм кэширования есть для Integer, Long, Byte, Short, Boolean и Character.
Нет для Float и Double.
3️⃣ Только для Integer — можно выставить значение верхнего диапазона кэширования с помощью опции VM. Если написать
-XX:AutoBoxCacheMax=2000
то закэшируются все Integer в диапазоне от -127 до 2000:
Integer a = 500;
Integer b = 500;
System.out.println(a == b);
// true

Вернёмся к исходному вопросу из предыдущего поста. Правильный ответ – true, но знание факта №3 даёт право отвечать на него «когда как».
👍7
Принцип подстановки Барбары Лисков: теория и практика.

SOLID - акроним, который содержит важные принципы объектно-ориентированного проектирования. Третий из них — Liskov Substitution Principle (LSP) часто вызывает трудности с пониманием из-за запутанной формулировки:
Пусть q(x) является свойством верным относительно объектов x некоторого типа T. Тогда q(y) также должно быть верным для объектов y типа S, где S является подтипом типа T.
По-простому: если заменить класс А на подкласс B, то система должна работать корректно и без неожиданных сайд-эффектов.
A service = new A();
A service = new B();
//всё ок


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

5 признаков того, что подкласс реализован правильно:
Синтаксические (для методов)
1️⃣ тип результата в переопределённом методе такой же, либо расширенный
Было: public Info getInfo()
public BigInfo getInfo()
public Object getInfo()
2️⃣ Подклассы не бросают дополнительных исключений, но могут уменьшить их список:
Было: public void save() throws FileNotFoundException
public void save()
public void save() throws InterruptedException
Java — типизированный язык, поэтому нарушения пунктов 1 и 2 контролируются компилятором.
3️⃣ типы параметров функций те же или менее строгие. Для Java это неприменимо, просто для справки:
Было: public void add(Account acc)
public void add(Object acc)
public void add(AdminAccount acc)
Поведенческие признаки:
4️⃣ метод подкласса делает то же, что и метод базового класса:
▪️если базовый метод countVisitors() только считает пользователей, то метод подкласса тоже должен просто считать пользователей, а не обновлять статистику и сохранять результат в БД.
5️⃣ метод подкласса взаимодействует с теми же сущностями, что и базовый
▪️ если в базовом методе увеличивается счётчик, то и в подклассе он увеличивается.
▪️ если в базовом классе есть переменная, которую базовый метод не меняет, то переопределённый метод тоже не должен её менять.
▪️ сценарии работы — если базовый класс предусматривает определённый порядок вызова методов, то подкласс тоже соблюдает этот протокол.

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

Вообще наследование — очень сильная связь между сущностями. Её ограничения могут перевесить преимущества по ходу развития проекта. Нарушения принципа подстановки — повод пересмотреть иерархию наследования или же вовсе от неё отказаться.
👍31
24 плагина Intellij IDEA для работы и души.

Сейчас на маркетплейсе IDE доступно больше 4 тысяч плагинов. Платные и бесплатные, они здорово помогают в решении ежедневных задач. Устанавливайте нужные вам и работайте комфортно и эффективно.

Работать с БД
▪️Database Navigator для RDBMS
▪️Mongo Plugin
▪️ledis для Redis
▪️Graph Database support для Neo4j

Установить единый кодстайл
Плагин и общий конфиг для команды помогут писать код единообразно
▪️CheckStyle-IDEA
▪️SonarLint

Найти баги
FindBugs-IDEA проверяет код на 200+ ошибочных паттернов

Решить проблемы с зависимостями
Maven Helper plugin поможет выявить конфликты и циклические зависимости

Править bash-скрипты
гораздо проще с плагином BashSupport

Увеличить скорость работы с IDE
Key promoter X научит сочетаниям клавиш для максимальной продуктивности

Проверить регулярные выражения
RegexpTester

Наглядно представить верхнеуровневые задачи
IDEA Mind Map для декомпозиции задач и мозговых штурмов

Легко ориентироваться в уровнях вложенности
▪️Rainbow Brackets - разноцветные скобки
▪️Indent Rainbow - разноцветные отступы

Почувствовать себя музыкантом
Fancy Music добавит звуки фортепиано для каждого нажатия клавиатуры

Поделиться кодом в Твиттере
▪️TweetCode
▪️IdeaTweet

Добавить спецэффекты
Power Mode II для эпичного кодинга

Поставить классный прогресс бар
▪️Nyan Progress Bar с радужной кошечкой
▪️Duck Progress Bar - для любителей уточек
▪️Hadouken Progress Bar - для уличных бойцов
▪️Dash Progress Bar - для тех, кто всегда готов постоять за друзей
▪️SSV Normandy Progress Bar - для фанатов Mass Effect
▪️StarTrek Progress Bar - для тех, у кого "Энтерпрайз" ассоциируется не только с работой
3
Утренний java puzzle♨️

Проверь себя и узнай правильный ответ в статье через час.
Сколько видов сборщика мусора есть в java на сегодняшний день?
Anonymous Poll
49%
4
34%
5
17%
6
Сборщики мусора. Плюсы и минусы G1.

Сборщик мусора(garbage collector) - компонент JVM, который размещает объекты в памяти. Выделяет место под новые и определяет те, которые уже не нужны.

В java есть 5 типов сборщика мусора - Serial Collector, Parallel Collector, Concurrent Mark Sweep (CMS), Garbage-First (G1) и Z Garbage Collector(ZGC). В java 8 вариантом по умолчанию является Parallel GC, в java 9 это G1. ZGC - самый новый, он появился в java 11.

Эффективность GC оценивается по следующим параметрам:
▪️Latency — сколько времени занимает сборка мусора. Измеряется в миллисекундах.
▪️Throughput — как часто она происходит. Пропускная способность считается в процентах времени VM и рассчитывается как обратная величина. Если сборка мусора занимает 5% времени,то throughput равен 95%.
▪️Footprint — сколько ресурсов использует GC. Учитывается количество памяти для корректной работы.

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

Основной принцип работы сборщика мусора — разделение объектов по поколениям.
▫️Недавно созданные объекты относятся к «молодым». Промежуточные объекты, итераторы, локальные переменные - самые вероятные кандидаты на удаление. На них сфокусирована основная часть внимания GC. Ещё они делятся на 2 подгруппы: только что созданные и выжившие после нескольких сборок мусора.
▫️Если объект пережил много циклов работы GC (по умолчанию 15), то он переходит в «старое» поколение и проверяется реже.
Деление на поколения не абстрактное. Если объект переходит в другое поколение, он физически меняет своё место в памяти, и все ссылки на него обновляются.

В ранних версиях сборщиков мусора память делилась на 4 региона:
🟥 Eden — здесь создавались новые объекты.
🟧 Survivor – для переживших несколько сборок мусора.
🟪 Tenured – для долгоживущих объектов.
🟦 Permanent – метаинформация JVM о классах, методах и тд.
Выглядело всё примерно так:
🟥🟥🟥🟥🟥🟥🟧🟧🟧🟪🟪🟦
В G1 область Permanent удалена, а метаинформация перенесена в отдельную часть памяти под названием Metaspace.
Второе изменение — память разделилась на 2000 регионов одного размера, по умолчанию 1МБ. Тип региона может меняться. Для больших объектов регионы объединяются.
Стало как-то так:
🟥🟪🟧🟧🟥🟪🟥🟥🟧🟪

Плюсы и минусы G1:
Выборочная обработка группы регионов – получаем высокий latency.
Предсказуемое время обработки.
Сборка мусора в основном выполняется параллельно с работой приложения.
Нет проблем с фрагментацией.
Затраты на поддержку такой системы чуть снижают throughput.
Целевое значение пропускной способности для G1 - 90%. Для Parallel GC это значение равно 99%.
Плохо работает с heap меньше 6Гб.

Чтобы проанализировать и оптимизировать работу G1, в первую очередь нужно включить логгирование, а уже затем экспериментировать с флажками JVM.
-Xloggc:/path/to/gc.log
-XX:+PrintGCDetails
-XX:+PrintGCApplicationStoppedTime
-XX:+PrintGCApplicationConcurrentTime


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

У всех есть коллега, который часто предлагает неожиданные решения. Иногда неподходящие, а иногда настолько изящные, что в голову приходит мысль: "Эх, почему не я это придумал".

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

Самый доступный способ — придумывать шутки.

Знаете, как пишется материал для КВН, фильмов, мемчиков и стендапов? Редко это лёгкий и остроумный полёт мысли. Часто этот процесс состоит из нескольких шагов:

1️⃣ Погружение в тему и сбор фактов.
2️⃣ Поиск парадоксов и неожиданных сопоставлений.
3️⃣ Поиск выразительной формы для максимального эффекта.

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

Первый шаг уже сделан - у вас есть огромный бэкграунд разработки. Настало время идти дальше! Следующий шаг - поиск несоответствий и противоречий.

Посмотрите на привычные вещи со стороны. Есть ли в них что-то нелогичное? Необязательно сразу придумывать шутку, главное — заметить что-нибудь интересное.
Например, вот нескольких идей, вдохновлённых java 8 и 9:

1️⃣ Stream API:
▫️ожидание: название наводит на мысль о работе с потоками данных, компактном описании бизнес-процессов.
▪️реальность1: обработка статичных коллекций без использования циклов.
▪️реальность2: для дебага и обработки исключений легче переписать обратно на циклы.

2️⃣ Parallel Streams:
▫️ожидание: существенный прирост производительности при добавлении .parallel()
▪️реальность: под большой нагрузкой работает в лучшем случае на 20% быстрее, в худшем - на 15% медленнее.

3️⃣ Выход java 9:
▫️ожидание: тренд на модульную архитектуру, новый взгляд на проектирование приложений.
▪️реальность: разработчики в восторге от List.of() и Map.of().

4️⃣ Развитие фичи pattern matching:
▫️ожидание: удобный апи для регулярных выражений.
▪️реальность: проверка и приведение типа объекта пишется в одну строку, а не в две.

5️⃣ Поддержка реактивного программирование в java 9:
▫️ожидание: сверхскорость выполнения кода, новый подход к разработке.
▪️реальность: интерфейсы для паттерна Observer.

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

Камон, шутки про java могут быть не только про кофе и многословность😉
Сколько времени Вы можете отвечать на вопрос "как создать поток"?
Anonymous Poll
75%
До 5 минут
16%
5-15 минут
9%
15-60 минут
Как создать поток: 7 вариантов ответа.

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

1️⃣ Синтаксический ответ — ожидаемый.
🅰️ реализовать интерфейс Runnable или Callable и передать новому объекту Thread:
Runnable action = () -> System.out.println("hey");
new Thread(action).start();
🅱️ расширить класс Thread, переопределить метод run, создать экземпляр этого класса:
class MyThread extends Thread {...}
new MyThread().star
t();

2️⃣ Углублённый ответ.
new Thread(...) приведёт к созданию в heap экземпляра класса Thread и сопутствующих объектов —program counter, хранилище thread-local переменных, нескольких стеков, объектов синхронизации и т.д. Вызов метода start() вызывает нативный метод start0(). Через JNI исполнится метод JVM JVM_StartThread, реализованный на C++, который вызывает метод ОС для создания потока. Для Unix это pthread_create.

3️⃣ Практический ответ.
Создание потока - ресурсоёмкая операция, поэтому лучше создать пул потоков, которые можно переиспользовать.
ExecutorService executor = Executors.newCachedThreadPool();
Runnable action = () -> System.out.println("hey");
executor.submit(action);

4️⃣ Неожиданный ответ.
Понятие потока в программировании очень размыто, особенно с учётом русского языка. Thread - структура для параллельного выполнения задач с помощью планировщика и потоков ОС.
Поток данных - тоже поток. В случае Stream API это скорее статичная коллекция, но можно рассказать интервьюеру основные методы его создания:
list.stream()
Stream.of(...)
Stream.range(...)
Arrays.stream(...)
Stream.generate(...)

5️⃣ Хайповый ответ.
Раз мы заговорили о потоке как потоке данных, то здесь можно свернуть в тему реактивного программирования. Самые популярные библиотеки для java это RxJava2, Project Reactor и Akka Streams. А также интерфейсы Flow API в java 9 и Reactive Streams.
Для примера рассмотрим создание потока в Reactor.
Поток из 0 или 1 элемента называется Mono:
Mono.just(1)
Mono.fromCallable(...)
Mono.fromFuture(...)
Mono.fromSupplier(...)
Поток из N элементов называется Flux:
Flux.just(1, 2, 3)
Flux.fromIterable(...)
Flux.fromStream(...)
Flux.range(...)

6️⃣ Big data oriented ответ.
В мире big data есть много фреймворков для обработки потоков данных. Apache Spark Streaming, Storm, Flink, Samza, Kafka Streams - если Вы работали с чем-то из этого списка, то обязательно поделитесь с интервьером этим опытом.

7️⃣ Менеджерский ответ.
Рассмотрим поток с нетехнической точки зрения. Поток - состояние, когда человек полностью включен в свою деятельность, совершенно сконцентрирован на ней и испытывает удовольствие от работы.
Задача руководителя - создать сотрудникам подходящие для этого условия. Можно использовать множество методов: регулярная обратная связь, увеличения прозрачности процессов и т.д.

Ответ на банальный вопрос "как создать поток" может различаться в зависимости от опыта и текущей должности. Вопросы на собеседованиях - лишь стартовая точка для обсуждений, не стесняйтесь повернуть разговор на обсуждение Ваших компетенций и сильных сторон.
👍52🔥1
Собеседование: план рассказа о прошлом опыте.

Техническое собеседование обычно состоит из трёх частей:
1️⃣ Синтаксические и алгоритмические задачки
2️⃣ Рассказ о прошлом опыте
3️⃣ Вопросы на свободную тему

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

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

🔶️Проекты, над которыми Вы работали больше 2 лет назад. 2-3 предложения о теме проекта и основных технологиях.
🔶️ Предпоследний проект — год-полтора назад. Тоже кратко, 4-5 предложений.
🔶️ Последний проект. Это самая актуальная и важная информация, поэтому уделите описанию большую часть времени.

Для описания проекта хорошо подходит шаблон «сверху вниз»:
1️⃣ Цель проекта: решаемые бизнес-задачи.
2️⃣ Общая схема: верхнеуровневая архитектура и основные технологии.
3️⃣ Контекст: компонент, который разрабатывала Ваша команда. Покажите на общей схеме, кратко опишите функции и уточните технологии. Расскажите о составе команды, процессе, по которому работали и с кем ещё взаимодействовали.
4️⃣ Ваша деятельность. Эта часть - кульминация, лучше подготовить её заранее. Кратко расскажите о фичах, которыми Вы занимались. Не углубляйтесь в бизнес-описание, лучше подробнее расскажите о результатах, решённых проблемах, какие подходы и инструменты использовали. Если какие-то из них упоминаются в вакансии — сделайте на них особый упор. Чем больше самопрезентация будет опираться на требования вакансии — тем больше шансов получить оффер.

Такое описание проектов максимально выделит Ваши навыки и достижения. Интервьюер увидит, что Вы:
▪️понимаете задачи бизнеса
▪️видите общую картину и свой вклад в неё
▪️понимаете процессы внутри команды
▪️умеете решать проблемы
▪️ориентированы на результат

Помните, что направление рассказа о предыдущем опыте — не углубляться в технические детали, а показать, что Вы ответственный сотрудник, решаете поставленные задачи и хорошо работаете в команде.
Ведь именно этого ждёт будущий работодатель.
👍2
Equality: best practices. Или как правильно переопределить метод equals.
Полный список в конце поста.

Базовая реализация в классе Object проверяет только равенство ссылок - по умолчанию каждый экземпляр класса равен только самому себе. Часто рекомендуют для новых классов переопределять метод equals и проверять равенство по значимым полям.

Несмотря на кажущуюся простоту, в реализации equals есть несколько тонких моментов. Кода в этом методе мало, выглядит он просто, а тесты на равенство редко кто пишет. Тем не менее часто встречается ситуация:
Странное поведение системы ➡️ неделя дебага по всей бизнес-логике ➡️ ошибка в equals ➡️ гнев и разочарование.

Простой способ не ошибиться — не переопределять equals вообще. Иногда это уместно:
1️⃣ Для перечислений (enum)
2️⃣ Когда важны сами экземпляры, а не данные внутри них. Пример - классы Thread, RecursiveTask.
3️⃣ Сравнение объектов вообще не предполагается. Пример - класс Pattern.
4️⃣ В базовом классе уже есть equals и нам подходит эта реализация.
5️⃣ Класс имеет модификатор доступа private или по умолчанию и мы уверены, что метод equals не будет вызван.

В остальных случаях его лучше переопределить. Во многих проектах при этом используется аннотация @EqualsAndHashCode библиотеки lombok, ограничения при её использовании мы тоже рассмотрим.

Итак, при реализации equals нужно учитывать следующие свойства:
1️⃣ Рефлексивность — экземпляр должен быть равен сам себе.
2️⃣ Консистентность — если экземпляры равны, то без внешних воздействий они должны оставаться равны.
Сравнивать только неизменяемые поля.
Чтобы обезопасить себя от проблем с equals по возможности используйте для ключей в Map не классы целиком, а их неизменяемые поля, например, id.
Если используете аннотацию @EqualsAndHashCode явно указывайте поля, по которым идёт сравнение. Это поможет избежать ошибок при добавлении в класс изменяемого поля.
@EqualsAndHashCode(of={“x”,“y”})
3️⃣ Симметрия.
Если в системе находятся объекты базового класса и его наследника нужно чётко понимать, как они будут между собой сравниваться.
Возьмём класс Точка, где равенство проверяется по координатам.
И его наследника — класс ЦветнаяТочка, где сравниваются координаты и цвет.
Точка обычная=new Точка(1,1);
Точка красная=new ЦветнаяТочка(1,1,RED);
Тогда обычная.equals(красная) будет true, а результат красная.equals(обычная) зависит от требований к системе — нужно ли игнорировать цвет в этом случае или нет.
4️⃣ Транзитивность.
Это свойство тоже легко нарушить, если мы имеем дело с иерархией:
Точка красная=new ЦветнаяТочка(1,1,RED);
Точка обычная=new Точка(1,1);
Точка синяя=new ЦветнаяТочка(1,1,BLUE);
Если мы решили игнорировать цвет при сравнении разных типов, то допустима такая ситуация:
красная.equals(обычная) - true
обычная.equals(синяя) — true
красная.equals(синяя) - true 😥
Для иерархий классов писать юнит-тесты на симметричность и транзитивность.
Не использовать @EqualsAndHashCode для иерархий классов.
🤔 Если в системе используются объекты базового и произвольного типов рассмотрите вариант замены наследования на композицию.
5️⃣ Сравнение существующего объекта с null должно возвращать false.
Добавить отдельную проверку if(o == null)

Итого:
1️⃣ Не переопределяйте equals, если сравнение не предполагается.
2️⃣ Используйте в equals только неизменяемые поля.
3️⃣ Для иерархии классов пишите тесты на симметричность и транзитивность.
4️⃣ Для ключей в Map желательно использовать неизменяемые поля, например, ID.
5️⃣ Не использовать @EqualsAndHashCode для иерархии классов.
6️⃣ При использовании @EqualsAndHashCode явно прописывайте поля.
7️⃣ Кратко проверить два поля на null и равенство можно через Objects.equals(this.a, а)
8️⃣ Проверяйте первыми поля, которые вероятнее всего отличаются.
9️⃣ Не забывайте про hashcode — используйте те же поля, что в методе equals.
👍31