❓Почему так?
✅ Чтобы обеспечить однозначность и приоритет классов JDK. При такой схеме невозможно создать свой класс с именем
❓Почему для классов JDK используется 2 загрузчика?
✅ Bootstrap работает на уровне виртуальной машины и загружает необходимый минимум классов на старте приложения. Extension ClassLoader - java объект, который загружает дополнительные модули JDK по мере необходимости.
❓Почему для отложенной загрузки классов нужны разные ClassLoader?
✅ Для безопасности классов JDK. Cуществует 4 модификатора доступа - private, protected, public и default. Последний ещё называют "доступ по умолчанию". Он даёт доступ к классам и методам того же пакета. Если мы назовём класс java.lang.Smth, он сможет работать с классами из пакета java.lang. Поэтому класс получает доступ к default полям другого класса только если:
🔸У него совпадает название пакета.
🔸Загружен тем же ClassLoader'ом.
JDK классы используют Bootstrap/Extension загрузчик, а наш java.lang.Smth - Application загрузчик, поэтому внутренние классы JDK недоступны классу Smth.
❓Что изменилось в java 9?
✅ Схема взаимодействия загрузчиков осталась той же. Поскольку JDK библиотеки
1️⃣ Изменились внутренние классы и методы загрузчиков. Проекты, которые используют загрузчики классов напрямую, столкнулись с проблемами совместимости.
2️⃣ Extension ClassLoader переименован в Platform ClassLoader. Теперь он загружает классы из модулей JDK и сторонних библиотек, одобренных Java Community: JDBC, JMS, JAX-RS и т.д.
✅ Чтобы обеспечить однозначность и приоритет классов JDK. При такой схеме невозможно создать свой класс с именем
java.lang.String. ❓Почему для классов JDK используется 2 загрузчика?
✅ Bootstrap работает на уровне виртуальной машины и загружает необходимый минимум классов на старте приложения. Extension ClassLoader - java объект, который загружает дополнительные модули JDK по мере необходимости.
❓Почему для отложенной загрузки классов нужны разные ClassLoader?
✅ Для безопасности классов JDK. Cуществует 4 модификатора доступа - private, protected, public и default. Последний ещё называют "доступ по умолчанию". Он даёт доступ к классам и методам того же пакета. Если мы назовём класс java.lang.Smth, он сможет работать с классами из пакета java.lang. Поэтому класс получает доступ к default полям другого класса только если:
🔸У него совпадает название пакета.
🔸Загружен тем же ClassLoader'ом.
JDK классы используют Bootstrap/Extension загрузчик, а наш java.lang.Smth - Application загрузчик, поэтому внутренние классы JDK недоступны классу Smth.
❓Что изменилось в java 9?
✅ Схема взаимодействия загрузчиков осталась той же. Поскольку JDK библиотеки
(rt.jar, tools.jar) теперь разбиты на модули, работа с ними поменялась:1️⃣ Изменились внутренние классы и методы загрузчиков. Проекты, которые используют загрузчики классов напрямую, столкнулись с проблемами совместимости.
2️⃣ Extension ClassLoader переименован в Platform ClassLoader. Теперь он загружает классы из модулей JDK и сторонних библиотек, одобренных Java Community: JDBC, JMS, JAX-RS и т.д.
У Вас есть домашний проект?
Anonymous Poll
11%
Да, активно развиваю
29%
Да, но редко им занимаюсь
51%
Нет, но хочу начать
8%
Нет и не планирую
Домашний проект: от выбора темы до пункта в резюме.
Написать работающую систему - важный шаг в обучении программированию. Закрепить теорию на практике, закрыть пробелы и попробовать новые технологии можно с помощью домашнего проекта. Давайте разберём популярные вопросы по этой теме:
❓Что писать?
Необязательно придумывать стартап, который изменит мир. Но если идей совсем нет:
1️⃣ Реализуйте с нуля текущий рабочий проект. Это очень удобно:
✅ Знакомая предметная область
✅ Понятные задачи
✅ Можно обсудить с коллегами непонятные места и текущие решения
2️⃣ Если рабочий проект надоел или не нравится, напишите свою версию популярной системы: Tinder, Яндекс.Маркет, «Кто хочет стать миллионером?» и тд. Помните, Вы пишете не "очередной велосипед", а тренируетесь и изучаете лучшие практики.
✅ Понятный функционал
✅ Современные подходы и технологии
❌ Детали реализации оригинала не всегда доступны, поэтому не с чем сравнить результат
❓Как работать над проектом?
Здесь Вы сами себе проджект-менеджер:
▫️Опишите функции до начала работы. Ориентируйтесь на текущие навыки и добавьте небольшой челлендж
▫️Декомпозируйте и отсортируйте задачи
▫️Составьте план
▫️Поставьте нестрогие дедлайны
▫️Двигайтесь от простого к сложному. Напишите основу на чистой java, добавьте maven/gradle, затем Spring, Spring Boot, базу данных и другие технологии
▫️Пишите тесты, это поможет найти узкие места
▫️Напишите эмулятор запросов, нагрузите приложение и изучите профайлеры
❓Нужно ли добавлять проект в резюме?
Как хотите🙂 Это большой бонус, если:
🔸Вы только начинаете карьеру разработчика.
🔸Домашний проект больше соответствует вакансии, чем текущее место работы.
🔸Вы хотите показать область своих интересов. Это полезно при собеседовании в компанию с большим количеством проектов.
❓Как подготовить проект к показу?
Прежде чем добавлять ссылку на проект в резюме, сделайте 2 несложных шага:
1️⃣ Добавьте файл
▪️О чём проект
▪️Основные функции
▪️Архитектуру (нарисуйте схему)
▪️Используемые технологии
2️⃣ Проработайте структуру проекта - дайте модулям и классам понятные имена. Функции, указанные в
Эти простые действия помогут сориентироваться в проекте и лучше оценить Вашу работу.
Написать работающую систему - важный шаг в обучении программированию. Закрепить теорию на практике, закрыть пробелы и попробовать новые технологии можно с помощью домашнего проекта. Давайте разберём популярные вопросы по этой теме:
❓Что писать?
Необязательно придумывать стартап, который изменит мир. Но если идей совсем нет:
1️⃣ Реализуйте с нуля текущий рабочий проект. Это очень удобно:
✅ Знакомая предметная область
✅ Понятные задачи
✅ Можно обсудить с коллегами непонятные места и текущие решения
2️⃣ Если рабочий проект надоел или не нравится, напишите свою версию популярной системы: Tinder, Яндекс.Маркет, «Кто хочет стать миллионером?» и тд. Помните, Вы пишете не "очередной велосипед", а тренируетесь и изучаете лучшие практики.
✅ Понятный функционал
✅ Современные подходы и технологии
❌ Детали реализации оригинала не всегда доступны, поэтому не с чем сравнить результат
❓Как работать над проектом?
Здесь Вы сами себе проджект-менеджер:
▫️Опишите функции до начала работы. Ориентируйтесь на текущие навыки и добавьте небольшой челлендж
▫️Декомпозируйте и отсортируйте задачи
▫️Составьте план
▫️Поставьте нестрогие дедлайны
▫️Двигайтесь от простого к сложному. Напишите основу на чистой java, добавьте maven/gradle, затем Spring, Spring Boot, базу данных и другие технологии
▫️Пишите тесты, это поможет найти узкие места
▫️Напишите эмулятор запросов, нагрузите приложение и изучите профайлеры
❓Нужно ли добавлять проект в резюме?
Как хотите🙂 Это большой бонус, если:
🔸Вы только начинаете карьеру разработчика.
🔸Домашний проект больше соответствует вакансии, чем текущее место работы.
🔸Вы хотите показать область своих интересов. Это полезно при собеседовании в компанию с большим количеством проектов.
❓Как подготовить проект к показу?
Прежде чем добавлять ссылку на проект в резюме, сделайте 2 несложных шага:
1️⃣ Добавьте файл
README.md в корневую директорию. Иногда это единственное, на что посмотрит посторонний человек. Не пожалейте времени, тщательно опишите:▪️О чём проект
▪️Основные функции
▪️Архитектуру (нарисуйте схему)
▪️Используемые технологии
2️⃣ Проработайте структуру проекта - дайте модулям и классам понятные имена. Функции, указанные в
README, должно быть легко найти в коде. Эти простые действия помогут сориентироваться в проекте и лучше оценить Вашу работу.
Forwarded from Java Developer
Java 25 лет!
Java, выпущенная в 1995 году под руководством Джеймса Гослинга, используется на 3 миллиардах устройств по всей планете, от мобильного телефона и PC, до холодильника и компьютера в автомобиле.
Более 10 миллионов разработчиков пишут на Java и других мощных языках, которые используют JVM: Kotlin, Scala, Groovy, Jython, JRuby, Clojure.
Поздравляю всех причастных: разработчиков, тестировщиков, менеджеров, аналитиков! Java — это сила!
Мы не знаем точно, что будет дальше в мире технологий, но Java явно войдет в историю. Быть причастным к этому и кодить на одном языке с массой крутых разработчиков очень приятно! С 25-летием, родная
@java_developer
Java, выпущенная в 1995 году под руководством Джеймса Гослинга, используется на 3 миллиардах устройств по всей планете, от мобильного телефона и PC, до холодильника и компьютера в автомобиле.
Более 10 миллионов разработчиков пишут на Java и других мощных языках, которые используют JVM: Kotlin, Scala, Groovy, Jython, JRuby, Clojure.
Поздравляю всех причастных: разработчиков, тестировщиков, менеджеров, аналитиков! Java — это сила!
Мы не знаем точно, что будет дальше в мире технологий, но Java явно войдет в историю. Быть причастным к этому и кодить на одном языке с массой крутых разработчиков очень приятно! С 25-летием, родная
@java_developer
Best practices: как проверять входные данные.
Запросы пользователей и ответы сторонних систем иногда приходят некорретными или в неправильном формате. Проверить данные можно по-разному, посмотрим разные варианты на простом примере:
1️⃣ Оставить как есть: тогда JVM выбросит
2️⃣ Добавить проверку и самим бросить исключение:
Начнём с производительности. Запустим каждый вариант миллион раз:
▪️14 мс - JVM исключение
▪️2 мс - явный выброс исключения
▪️0,03 мс - null
▪️0,03 мс - Optional.empty()
Что это значит?
1️⃣ Создание исключения гораздо дольше, чем выход из метода. Время уходит на создание стек-трейса - чем он глубже, тем хуже производительность. Стек-трейс из сервиса на Spring Boot собирается в 50-100 раз дольше, чем стек-трейс из метода main.
2️⃣ Если исключение явно создаётся в коде, JVM переиспользует ранее собранный стэк-трейс. Так получается выигрыш в 5-10 раз, но разница с вариантом без исключения всё ещё внушительна.
По этим цифрам легко решить, что исключения - удар по производительности. 10 лет назад была тенденция избегать исключений любой ценой. Например, возвращать из метода пару (результат, код_ошибки).
В 2020 это уже не актуально. Если взаимодействие в системе не построено на исключениях, то это капля в море относительно других операций. В примере сверху исключение создаётся миллион раз подряд - такого в продакшене обычно нет.
Исключения делают код чище:
🔹Понятное возвращаемое значение
🔹В части throws явно обозначены непредвиденные ситуации
🔹Логика метода и обработка ошибок разделены
Теперь сравним создание исключения и возврат null с точки зрения дизайна.
Исключение подразумевает обработку ошибки, например:
🔸Показать пользователю сообщение.
🔸Прекратить работу с файлом.
🔸Поменять формат данных.
Optional.empty(), null или объект по умолчанию возвращается, когда реагировать на ситуацию необязательно. Например, когда данные быстро устаревают. Возвращаемый тип Optional удобнее использовать: не нужно смотреть в документации, возвращает ли функция пустой результат, и как он обозначается: null, -1 или 0.
Запросы пользователей и ответы сторонних систем иногда приходят некорретными или в неправильном формате. Проверить данные можно по-разному, посмотрим разные варианты на простом примере:
String info(Request req) {
return req.toString(); }
Для нормальной работы параметр req не должен быть пустым. Мы можем:1️⃣ Оставить как есть: тогда JVM выбросит
NullPointerException(NPE)2️⃣ Добавить проверку и самим бросить исключение:
if (req==null) throw new NPE();3️⃣ Добавить проверку и вернуть null:
if (req==null) return null;4️⃣ Добавить проверку и вернуть Optional.empty():
if (req==null) return Optional.empty();Оценим их с точки зрения производительности и дизайна.
Начнём с производительности. Запустим каждый вариант миллион раз:
▪️14 мс - JVM исключение
▪️2 мс - явный выброс исключения
▪️0,03 мс - null
▪️0,03 мс - Optional.empty()
Что это значит?
1️⃣ Создание исключения гораздо дольше, чем выход из метода. Время уходит на создание стек-трейса - чем он глубже, тем хуже производительность. Стек-трейс из сервиса на Spring Boot собирается в 50-100 раз дольше, чем стек-трейс из метода main.
2️⃣ Если исключение явно создаётся в коде, JVM переиспользует ранее собранный стэк-трейс. Так получается выигрыш в 5-10 раз, но разница с вариантом без исключения всё ещё внушительна.
По этим цифрам легко решить, что исключения - удар по производительности. 10 лет назад была тенденция избегать исключений любой ценой. Например, возвращать из метода пару (результат, код_ошибки).
В 2020 это уже не актуально. Если взаимодействие в системе не построено на исключениях, то это капля в море относительно других операций. В примере сверху исключение создаётся миллион раз подряд - такого в продакшене обычно нет.
Исключения делают код чище:
🔹Понятное возвращаемое значение
🔹В части throws явно обозначены непредвиденные ситуации
🔹Логика метода и обработка ошибок разделены
Теперь сравним создание исключения и возврат null с точки зрения дизайна.
Исключение подразумевает обработку ошибки, например:
🔸Показать пользователю сообщение.
🔸Прекратить работу с файлом.
🔸Поменять формат данных.
Optional.empty(), null или объект по умолчанию возвращается, когда реагировать на ситуацию необязательно. Например, когда данные быстро устаревают. Возвращаемый тип Optional удобнее использовать: не нужно смотреть в документации, возвращает ли функция пустой результат, и как он обозначается: null, -1 или 0.
Что вернётся из try-catch-finally?
Вопросы такого типа популярны на собеседованиях. Поведение
Чтобы решать такие задачки, воспользуйтесь следующей моделью:
Результатом блока
🔸Ничего
🔸Возврат значения
🔸Исключение
Представим, что результат записывается в переменную result. В начале работы там "ничего".
Блоки обрабатываются в строгом порядке:
1️⃣ try
2️⃣ catch
3️⃣ finally
На каждом шаге переменная result может быть перезаписана. Итоговое значение result и будет результатом выполнения. Особый случай — при вызове
Разберём пример из опроса:
▫️try установит результат на "вернуть try".
▫️Блока catch нет.
▫️В finally результат меняется на "вернуть finally".
Итог: вернётся "finally"
Другой пример:
▫️Блок catch пропускается, т.к нет подходящего типа исключения.
▫️В блоке finally результат не переопределяется.
Итог: выброс NPE.
Этот пример важен, потому что такие ошибки часто встречаются на практике. Блок finally - не оберег от исключений. Если результат "исключение" дальше не переопределён, он пробрасывается в вышестоящий метод.
Вопросы такого типа популярны на собеседованиях. Поведение
try-catch-finally в спецификации описывается через 24 предложения "если". Логика запутанная, и легко допустить ошибку.Чтобы решать такие задачки, воспользуйтесь следующей моделью:
Результатом блока
try-catch-finally могут быть 3 варианта:🔸Ничего
🔸Возврат значения
🔸Исключение
Представим, что результат записывается в переменную result. В начале работы там "ничего".
Блоки обрабатываются в строгом порядке:
1️⃣ try
2️⃣ catch
3️⃣ finally
На каждом шаге переменная result может быть перезаписана. Итоговое значение result и будет результатом выполнения. Особый случай — при вызове
System.exit(0) выполнение прекращается сразу же .Разберём пример из опроса:
▫️try установит результат на "вернуть try".
▫️Блока catch нет.
▫️В finally результат меняется на "вернуть finally".
Итог: вернётся "finally"
Другой пример:
try { throw new NPE(); }
catch (SecurityEx e)
{ return "ex"; }
finally {}
▫️В блоке try результатом станет "NPE".▫️Блок catch пропускается, т.к нет подходящего типа исключения.
▫️В блоке finally результат не переопределяется.
Итог: выброс NPE.
Этот пример важен, потому что такие ошибки часто встречаются на практике. Блок finally - не оберег от исключений. Если результат "исключение" дальше не переопределён, он пробрасывается в вышестоящий метод.
Что вернёт метод?
Anonymous Quiz
7%
NullPointerException
20%
exception
67%
finally
6%
Ошибка компиляции
Stream API: ускоряемся🚀
Stream API помогает писать выразительный код, который быстро работает. Несложными действиями можно повысить скорость ещё больше:
1️⃣ Добавить parallel().
Для поддержки параллельности нужны дополнительные ресурсы, и прирост скорости заметен только если в коллекции много элементов. Если:
N – количество элементов,
Q – количество операций над каждым элементом,
то при N*Q>10000 можно смело добавлять parallel()
2️⃣ Добавить или удалить sorted(), unordered().
🔸sorted(): отсортировать стрим и добавить свойство «отсортирован».
🔸unordered(): выставить свойство «порядок не важен».
Источник данных и методы sorted, unordered, dictinct,... определяют свойства стрима: конечный размер, уникальность, отсортированные значения и другие. Благодаря этому некоторые методы оптимизируют работу. Если порядок не важен, параллельная обработка будет быстрее. Если список уже отсортирован, удаление повторяющихся элементов distinct() займёт меньше времени. Иногда наоборот — дополнительные ограничения замедляют работу.
Другие специфичные примеры.
3️⃣ Пользоваться специальными методами.
Чем меньше операций, тем быстрее всё работает. Проверить, что ни один элемент не удовлетворяет условию можно так:
none
Больше примеров
4️⃣ Объединить однотипные операции.
Чаще это касается сложной фильтрации:
Stream API помогает писать выразительный код, который быстро работает. Несложными действиями можно повысить скорость ещё больше:
1️⃣ Добавить parallel().
Для поддержки параллельности нужны дополнительные ресурсы, и прирост скорости заметен только если в коллекции много элементов. Если:
N – количество элементов,
Q – количество операций над каждым элементом,
то при N*Q>10000 можно смело добавлять parallel()
2️⃣ Добавить или удалить sorted(), unordered().
🔸sorted(): отсортировать стрим и добавить свойство «отсортирован».
🔸unordered(): выставить свойство «порядок не важен».
Источник данных и методы sorted, unordered, dictinct,... определяют свойства стрима: конечный размер, уникальность, отсортированные значения и другие. Благодаря этому некоторые методы оптимизируют работу. Если порядок не важен, параллельная обработка будет быстрее. Если список уже отсортирован, удаление повторяющихся элементов distinct() займёт меньше времени. Иногда наоборот — дополнительные ограничения замедляют работу.
Другие специфичные примеры.
3️⃣ Пользоваться специальными методами.
Чем меньше операций, тем быстрее всё работает. Проверить, что ни один элемент не удовлетворяет условию можно так:
filter(...).findFirst().isPresent()
а можно короче, понятнее и быстрее:none
Match(...)
Иногда стримы даже не нужны, много полезных методов есть в интерфейсе Collections. Например, максимальный элемент в списке быстрее найти через Collections.max(...), чем с использованием стрима.Больше примеров
4️⃣ Объединить однотипные операции.
Чаще это касается сложной фильтрации:
filter(1).filter(2).filter(3)
можно ускорить в 2-4 раза, если объединить условия:filter(1 & 2 & 3)❤3
IntelliJ IDEA: быстрый поиск.
Двойное нажатие Shift - универсальный шорткат для поиска. Он поможет:
✅ Найти класс, метод или файл.
✅ Открыть настройки: Tab Size, Code style, ...
✅ Выполнить команду:
Optimize imports,
Push (в репозиторий),
Show history,
Rename,
Presentation Mode
...и многие другие. Просто нажмите Shift-Shift, начните набирать слово и выберите подходящий вариант из списка.
Двойное нажатие Shift - универсальный шорткат для поиска. Он поможет:
✅ Найти класс, метод или файл.
✅ Открыть настройки: Tab Size, Code style, ...
✅ Выполнить команду:
Optimize imports,
Push (в репозиторий),
Show history,
Rename,
Presentation Mode
...и многие другие. Просто нажмите Shift-Shift, начните набирать слово и выберите подходящий вариант из списка.
👍2❤1
Скомпилируется ли код выше?
Anonymous Poll
63%
Да
18%
Нет, в метод нужно передать (Long) intValue
19%
Нет, в метод нужно передать (long) intValue
Система типов и проверка аргументов.
Язык программирования строится на многих формальных теориях. Одна из них - система типов. От неё зависит реализация языка, скорость компиляции и работы программы. Тема этого поста: как проверяются аргументы метода. Кажется, что ничего сложного здесь нет, но каждый язык делает это по-своему.
Первый вопрос: когда происходит проверка? В зависимости от ответа типизация может быть:
🔸Cтатической
🔸Динамической
При статической тип указателя навсегда закрепляется при создании:
✅ Отлавливается много ошибок.
✅ Быстро работает в рантайме.
✅ Предсказуемое поведение.
✅ Легко тестировать.
При динамической типизации указатель не имеет типа. Во время работы программы в переменную можно записать любые значения:
Java является языком со статической типизацией.
Второй вопрос, на который отвечает система типов: что делать, если метод принимает тип А, но приходит объект типа Б? Можно:
▪️Бросить ошибку.
▪️Преобразовать Б в тип А.
У языка сильная типизация, если допустимо мало преобразований. Если много, то типизация слабая. Речь идёт о неявных преобразованиях, которые делает компилятор или исполняющая среда.
Пример:
Компилятор java может перевести:
- подкласс в суперкласс
- long в int и наоборот
- int в Integer и наоборот
и так далее. Некоторые правила работают в одних условиях, некоторые в других. В целом java считается языком с сильной типизацией.
Вернёмся к вопросу перед постом. Метод
int → long
long → Long
Компилятор может выполнить только один шаг, второе преобразование делает программист. Поэтому подходящий ответ:
Язык программирования строится на многих формальных теориях. Одна из них - система типов. От неё зависит реализация языка, скорость компиляции и работы программы. Тема этого поста: как проверяются аргументы метода. Кажется, что ничего сложного здесь нет, но каждый язык делает это по-своему.
Первый вопрос: когда происходит проверка? В зависимости от ответа типизация может быть:
🔸Cтатической
🔸Динамической
При статической тип указателя навсегда закрепляется при создании:
String str;Ассоциированный объект имеет тот же тип или производный. Т.к типы известны заранее, проверка аргументов происходит во время компиляции.
✅ Отлавливается много ошибок.
✅ Быстро работает в рантайме.
✅ Предсказуемое поведение.
✅ Легко тестировать.
При динамической типизации указатель не имеет типа. Во время работы программы в переменную можно записать любые значения:
value = "а"Аргументы проверяются во время вызова метода. Такие программы в разы короче и легко адаптируются к изменениям.
value = 4
Java является языком со статической типизацией.
Второй вопрос, на который отвечает система типов: что делать, если метод принимает тип А, но приходит объект типа Б? Можно:
▪️Бросить ошибку.
▪️Преобразовать Б в тип А.
У языка сильная типизация, если допустимо мало преобразований. Если много, то типизация слабая. Речь идёт о неявных преобразованиях, которые делает компилятор или исполняющая среда.
Пример:
5L + 1
Язык Ruby не разрешает складывать числа разных типов, а java приведёт единицу к типу long и выполнит сложение. Выражение 5 + trueв java вызовет ошибку компиляции. JavaScript спокойно переведёт true в единицу.
Компилятор java может перевести:
- подкласс в суперкласс
- long в int и наоборот
- int в Integer и наоборот
и так далее. Некоторые правила работают в одних условиях, некоторые в других. В целом java считается языком с сильной типизацией.
Вернёмся к вопросу перед постом. Метод
id ожидает аргумент типа Long, а передаётся примитивный int. В правилах преобразований нет перехода int → Long, поэтому будет ошибка компиляции. Достичь цели можно в 2 шага:int → long
long → Long
Компилятор может выполнить только один шаг, второе преобразование делает программист. Поэтому подходящий ответ:
(long) intValueJava 8-11: новые методы String.
Чтобы не писать велосипеды и не добавлять в проект лишние библиотеки, посмотрите на новые методы в классе String:
🔸Соединить строки через разделитель:
▪️с начала строки:
🔸Проверить, что строка пуста:
🔸Создать стрим из строки. Можно разделить текст
▪️по линиям:
Чтобы не писать велосипеды и не добавлять в проект лишние библиотеки, посмотрите на новые методы в классе String:
🔸Соединить строки через разделитель:
String.join("-","1","2");
// 1-2
Можно использовать со списком строк:List<String> list = ...;🔸Убрать пробелы и служебные символы
String.join("-", list);
▪️с начала строки:
str.stripLeading();
▪️в конце строки: str.stripTrailing();
▪️с обеих сторон:str.strip();
В классе уже присутствует метод trim(), который тоже стирает неподходящие символы. strip() корректнее определяет недопустимые символы, в том числе экзотические виды пробелов ('\u00A0', '\u2007', '\u202F').🔸Проверить, что строка пуста:
str.isBlank()На замену StringUtils.isBlank() из библиотеки Apache Commons.
🔸Создать стрим из строки. Можно разделить текст
▪️по линиям:
str.lines()
▪️по символам: str.chars()
🔸Продублировать строку:"<td>".repeat(3);
// <td><td><td>Изучаете новую технологию? Не забывайте про контекст.
В интернете полно статей о языках программирования, фреймворках и библиотеках. Большинство из них показывают синтаксис на простых, но часто нереалистичных примерах. Этой информации хватает для собеседований, докладов и расширения кругозора. Однако для продуктивной работы важен не только синтаксис, но и контекст использования. Он включает в себя ответы на вопросы:
🔷Какую проблему решает Х?
🔷Какие альтернативы для решения этой же проблемы?
🔷В каких условиях Х лучше, чем альтернативы?
🔷За счёт чего Х лучше?
К сожалению, в статьях редко рассматриваются эти вопросы. Однако сценарии использования инструментов и альтернатив входят в понятие "опыт" разработчика и высоко ценятся на рынке.
Рассмотрим пример. Любой курс по многопоточности начинается с понятия потока и изучения класса Thread. Обычно автор описывает жизненный цикл потока, доступные методы и показывает пример создания потока с интерфейсами Runnable и Callable.
Можно ли на основе только этих знаний решать задачи? Можно, но вряд способ будет оптимальным. Посмотрим на класс Thread поближе и попробуем ответить на вопросы выше:
❓Какие задачи можно решать в отдельных потоках?
🔸Обработка большого количества данных
🔸Слабосвязанные подзадачи
❓Есть ли альтернативы для этих задач?
Обрабатывать данные можно с помощью ForkJoinPool. Для выполнения подзадачи в другом потоке есть ExecutorService. Можно использовать виртуальные потоки: Kotlin continuations, библиотеку Quasar и другие.
❓Когда ручное управление потоком лучше, чем варианты выше?
Сложно сказать. ForkJoinPool и ExecutorService эффективнее используют ресурсы и предоставляют высокоуровневый интерфейс, поэтому ими легко пользоваться. Виртуальные потоки лучше работают с маленькими задачами и блокирующими вызовами.
Класс Thread появился в java 1.2. Это низкоуровневый инструмент, в 2020 году с ним решаются только очень специфичные задачи. Для популярных задач появилось много специализированных классов и фреймворков.
Обзорные статьи и доклады - это стартовые точки при изучении технологий. Нужно двигаться к пониманию, как и когда это применять на практике. Как это сделать? Лёгкого пути нет, нужно по крупицам собирать общую картину из разных источников и, конечно, читать посты на @java_fillthegaps💪
В интернете полно статей о языках программирования, фреймворках и библиотеках. Большинство из них показывают синтаксис на простых, но часто нереалистичных примерах. Этой информации хватает для собеседований, докладов и расширения кругозора. Однако для продуктивной работы важен не только синтаксис, но и контекст использования. Он включает в себя ответы на вопросы:
🔷Какую проблему решает Х?
🔷Какие альтернативы для решения этой же проблемы?
🔷В каких условиях Х лучше, чем альтернативы?
🔷За счёт чего Х лучше?
К сожалению, в статьях редко рассматриваются эти вопросы. Однако сценарии использования инструментов и альтернатив входят в понятие "опыт" разработчика и высоко ценятся на рынке.
Рассмотрим пример. Любой курс по многопоточности начинается с понятия потока и изучения класса Thread. Обычно автор описывает жизненный цикл потока, доступные методы и показывает пример создания потока с интерфейсами Runnable и Callable.
Можно ли на основе только этих знаний решать задачи? Можно, но вряд способ будет оптимальным. Посмотрим на класс Thread поближе и попробуем ответить на вопросы выше:
❓Какие задачи можно решать в отдельных потоках?
🔸Обработка большого количества данных
🔸Слабосвязанные подзадачи
❓Есть ли альтернативы для этих задач?
Обрабатывать данные можно с помощью ForkJoinPool. Для выполнения подзадачи в другом потоке есть ExecutorService. Можно использовать виртуальные потоки: Kotlin continuations, библиотеку Quasar и другие.
❓Когда ручное управление потоком лучше, чем варианты выше?
Сложно сказать. ForkJoinPool и ExecutorService эффективнее используют ресурсы и предоставляют высокоуровневый интерфейс, поэтому ими легко пользоваться. Виртуальные потоки лучше работают с маленькими задачами и блокирующими вызовами.
Класс Thread появился в java 1.2. Это низкоуровневый инструмент, в 2020 году с ним решаются только очень специфичные задачи. Для популярных задач появилось много специализированных классов и фреймворков.
Обзорные статьи и доклады - это стартовые точки при изучении технологий. Нужно двигаться к пониманию, как и когда это применять на практике. Как это сделать? Лёгкого пути нет, нужно по крупицам собирать общую картину из разных источников и, конечно, читать посты на @java_fillthegaps💪
👍6