Java — настолько популярный и развитый язык, что контента на любую связанную с ним тему хоть отбавляй. Будь то технические разборы, обзоры популярных библиотек с открытым исходным кодом, статьи о поиске работы Java-программистом, сравнение с другими языками — всего не перечесть. Поиск по слову «java» в гугле выдал мне около 1,56,00,00,000 (?) результатов.
![Колоссальный переизбыток java-контента Колоссальный переизбыток java-контента](https://habrastorage.org/getpro/habr/upload_files/4d8/eed/8fd/4d8eed8fd47c674bb8ae8fcca625b4e5.png)
Чем НЕ является эта статья
Превалирующая на просторах интернета подкатегория — это контент для новичков. То есть книги для изучения java. Или, чего на порядок больше, статьи с заголовком “Ресурсы для изучения Java”. Я ни в коем случае не дискредитирую их. Даже напротив, я считаю, что чтение книг — один из лучших способов структурированного и достаточно глубокого изучения любого языка программирования. Но такого рода статьи в основном предлагают учащемуся случайный набор книг, не уделяя внимания порядку, в котором их нужно читать.
Также прошу не путать эту статью с теми, которые имеют в названии слова “Java” и “roadmap”, но уходят в перечисление всех существующих технологий. Или с теми, которые слишком подробно описывают каждую языковую конструкцию.
![](https://habrastorage.org/getpro/habr/upload_files/e24/619/7a3/e246197a3c94c478a099b71183c5d238.jpeg)
Учащиеся могут утонуть в океане “обучающего контента по Java”.
Из моих предыдущих статей вы, возможно, уже знаете, что я адвокатирую за то, чтобы люди тратили время на углубленное изучение материала и достигали в нем хорошего уровня компетенции. И я также настаиваю на том, что, чтобы развить свои профессиональные качества до такого уровня, нужно уделять обучению достаточно много времени. Эта статья также не очередной случайный набор ресурсов, это вполне конкретный roadmap по освоению языка до уровня разработчика, имеющего 6-7 лет опыта работы. Однако, чтобы стать таким же сильным разработчиком, вам определенно нужно посвятить время (не менее года), чтобы научиться чему-то должным образом. Поэтому я настоятельно рекомендую вам не позволять себе тратить драгоценное время, необходимое для полноценного обучения, “разбираясь по необходимости” или занимаясь “обучением на рабочем месте”. Давайте перестанем притворяться, что мы можем работать и учиться одновременно. Итак, вот полный roadmap. Следуйте ему, и вместе с советами, приведенными в конце, у вас будет все для того, чтобы стать профессионалом в Java за 1/5 времени, которое требуется другим разработчикам.
Roadmap
TL;DR — короткая версия
Ниже я перечислю ряд ресурсов вместе с описанием их содержания. Но по большому счету процесс обучение Java делится на 3 этапа: основы Java, шаблоны проектирования и производительность Java.
![Roadmap изучения Java Roadmap изучения Java](https://habrastorage.org/getpro/habr/upload_files/729/a31/ff8/729a31ff84c7fa5023767246870645f1.png)
А теперь перейдем к списку книг, из которых, собственно, и сформирован этот roadmap.
Основы языка
Java. Библиотека профессионала, том I и II, Кей Хорстманн (Core Java, Cay Horstmann)
![](https://habrastorage.org/getpro/habr/upload_files/573/cf9/3b0/573cf93b0b9f8473fa9c507773c12a2b.png)
Эти книги можно купить на Amazon (Core Java, том 1) и (Core Java, том 2):
Прочитав эти книги от корки до корки, вы сформируете очень хорошее представление о языковом ландшафте. Как для книги, охватывающей такую обширную область, объяснения вполне доступные. Она также достаточно хорошо раскрывает нюансы языковых конструкций и подводные камни. Эти книги наполнены примерами кода, и самое замечательное, что автор позаботился о том, чтобы этот код был чем-то большим, нежели простая демонстрации работы языковой фичи. Эти примеры почти всегда демонстрируют, как данная фича применима к реальному варианту использования. Наконец, эти книги рассказывают не только о языке, но и о связанных с ним библиотеках, и том, что вы вообще можете делать с помощью java (особенно во втором томе).
2. Java. Эффективное Программирование, Джошуа Блох (Effective Java, Joshua Bloch)
![](https://habrastorage.org/getpro/habr/upload_files/c83/295/11d/c8329511d666e216966bc37ae457c527.png)
Эту книгу можно купить здесь. Эта книга посвящена использованию эффективных и практичных конструкций в Java для выполнения определенных типов задач, которые довольно часто возникают во время работы. В ней также объясняется, почему данный конкретный способ, который они используют для выполнения задачи, является наилучшим, и почему другие способы работают не так хорошо.
Прочтение и практическая отработка содержания двух вышеупомянутых книг поможет закрепить синтаксис, наиболее эффективные идиомы и шаблоны использования в вашей памяти. Главное — читать, практиковать и рассуждать. К этому моменту вы уже должны научиться думать на Java как на своем родном языке. Есть еще одна хорошая книга для глубокого изучения одной из самых сложных тем в Java, а именно параллелизма.
3. Java Concurrency на практике, Брайан Гетц (Java Concurrency in Practice, Brian Goetz)
![](https://habrastorage.org/getpro/habr/upload_files/c20/7ba/56c/c207ba56ce4ff944b4a33ada27d3237e.png)
Эту книгу можно купить здесь. Эта книга подробно описывает конструкции параллелизма в Java и устраняет множество заблуждений, которые обычно возникают у людей относительно того, как устроены потоки и параллелизм в Java. Прочтение этой книги, скорее всего, не вызовет у вас ощущения, что параллелизм — это просто, но вы сформируете кристально четкое представление о том, что именно происходит, когда вы используете объекты параллелизма тем или иным образом. Кроме того, она демонстрирует корректные способы реализации некоторых популярных видов задач, подразумевающих параллелизм.
Если вы сомневаетесь, что эта книга все еще может быть полезной для вас, несмотря на то, что она уже достаточно старая, рекомендую вам почитать этот пост.
На этом этапе вы уже должны достигнуть уровня Java-разработчика с 3-летним опытом.
Что ж, вы практически полностью разобрались с языком Java и его применением для решения различных задач. Пора переходить к изучению паттернов проектирования в java. До сих пор вы изучали только идиомы, но теперь вам нужно научиться организовывать сущности Java (классы, объекты, интерфейсы и т.д.) таким образом, чтобы программа была гибкой и удобочитаемой. Официальным термином, используемым интервьюерами для проверки ваших навыков в этой области, служит LLD (low level design – архитектура низкого уровня).
LLD
Эта часть целиком посвящена LLD (Low Level Design). Для изучения этой области я бы посоветовал вам следующие книги. Отчасти потому, что они рассматриваю LLD в применении к Java:
Объектно-ориентированный анализ и проектирование, Бретт Д. Маклафлин, Дэвид Уэст и Гэри Поллис (Head First Object-Oriented Analysis and Design, Brett D. McLaughlin, David West and Gary Pollice)
![](https://habrastorage.org/getpro/habr/upload_files/bac/bec/a68/bacbeca680cb8cb95337b7a0d0c55c8a.png)
Купить можно здесь. Эта книга посвящена ПРИНЦИПАМ разработки хороших программ на Java. Как и все книги Head First, она написана очень ясным и легким для понимания языком. Авторы стараются использовать сразу несколько средств для объяснения концепции, чтобы она как можно лучше усвоилась сознанием. Не пропускайте эту книгу, так как она хорошо подготовит вас к изучению паттернов проектирования, которые следует изучить из следующей книги.
2. Паттерны объектно-ориентированного проектирования, Эрих Гамма (Design Patterns, Erich Gamma)
![](https://habrastorage.org/getpro/habr/upload_files/55d/a09/c47/55da09c4753a5af95ea6897e493bb9b5.png)
Купить эту книгу можно здесь. Это именно так книга, по которой следует изучать паттерны проектирования. В ней подробно рассмотрены все основные паттерны. Однако она определенно не рассчитана для начинающих. И здесь на помощь приходит предыдущая книга. В этой же книги паттерны и их применение изложены в энциклопедическом формате. Кроме того, примеры написаны на языке под названием Smalltalk. Это чистый объектно-ориентированный язык, почти как Java.
Две вышеупомянутые книги помогут вам освоить практическое мастерство LLD в Java. Это должно придать вам чувство уверенности при работе со сложными конструкциями технического кода и паттернами, с которыми вы можете столкнуться в своей повседневной работе. Кроме того, вы сможете применять изученные паттерны к новым задачам, возникающим перед вами в работе.
На этом этапе вы уже должны достигнуть уровня Java-разработчика с 4-летним опытом.
Производительность Java
Теперь пришло время разобраться с производительностью Java. Этот раздел подготовит вас к пониманию того, как именно Java устроена внутри, на уровне JVM. Вы должны научиться оптимизировать производительность JVM и разрабатывать код таким образом, чтобы он был максимально эффективным. В этом вам помогут следующие книги:
Эффективный Java. Тюнинг кода на Java 8, 11 и дальше, Скотт Оукс (Java Performance — In-Depth Advice for Tuning and Programming Java 8, 11, and Beyond, Scott Oaks)
![](https://habrastorage.org/getpro/habr/upload_files/5fa/823/d6f/5fa823d6fb5aea6bf8da2c7f2bd00452.png)
Купить эту книгу можно здесь. Автор этой книги придерживается мнения, что любой, кто работает с Java, должен знать, как код ведет себя в JVM, и обладать навыком производить тюнинг для повышения производительности. Это обновленное второе издание содержит подробные сведения о производительности Java-приложений как с использованием JVM, так и платформы Java.
2. Java: оптимизация программ. Практические методы повышения производительности приложений в JVM, Бенджамин Эванс и Джеймс Гоф (Optimizing Java: Practical Techniques for Improved Performance Tuning, Benjamin J Evans and James Gough)
![](https://habrastorage.org/getpro/habr/upload_files/80e/ecd/c4e/80eecdc4e7f9371a00bc17d671606034.png)
Купить эту книгу можно здесь. Если предыдущая книга была больше о теории, то эта больше о практических методах, которые вы будете использовать для измерения и повышения производительности Java-приложений в своей работе. Это руководство является “недостающим звеном”, целью которого является перевод тюнинга производительности Java из области догадок и фольклора в экспериментальную науку. Вы узнаете, как последовательно и систематически подходить к проблемам производительности, решать проблемы с производительностью в производственной среде, изучая основные виды проблем с производительностью в Java, а также выявлять и решать проблемы с производительностью до того, как они вообще возникнут.
После завершения обучения по книгам в этом разделе вы достигните уровня Java-разработчика с 7-летним опытом!
Если вы все-таки дочитали до этого места, я умоляю вас углубиться в изучение Java — это продвинет вашу работу и карьеру. Не довольствуйтесь лишь основами для работы и преодолейте проблемы с неуверенностью. Я обещаю вам, что если вы прочитаете эти книги в порядке, который я здесь упомянул, и попрактикуетесь в них, то вы станете настолько хороши, что никто не сможет оспорить ваш авторитет как профессионального Java-разработчика, где бы вы ни работали.
Поздравляю, этот roadmap, как мне кажется, может сделать даже из новичка Java-разработчика с эквивалентом 7-8 лет опыта работы за относительно короткий промежуток времени в 1.5 года. Это среднее время, которое, по моим оценкам, потребуется людям, чтобы выучить и усвоить все из упомянутого выше материала. А получить уровень знаний человека с 7-летним стажем за 1.5 года — это очень даже не плохо. Я бы очень хотел, чтобы у меня был такой roadmap, когда я только начинал. Я не мог воспользоваться чем-то подобным в свое время, но вы, безусловно, можете. Так что вперед! Дерзайте!
P.S: Если вас интересуют дополнительные рекомендации о том, как правильно изучать технические предметы, перейдите по ссылкам, которые я указал ниже. В них обсуждаются практические приемы, которые можно использовать для изучения чего-либо таким образом, чтобы это навсегда сохранилось в вашей памяти.
Подробное изучение технологии — часть 1
Подробное изучение технологии — часть 2
Подробное изучение технологии — часть 3
Как работают веб-приложения на Java на практике? Обсудим эту тему на открытом уроке, который пройдет в рамках специализации Java-разработчик. Поговорим о том, как работают современные веб-приложения, а именно их серверная часть. Посмотрим, как на практике можно создать свое серверное приложение. Урок будет особенно полезен начинающим разработчикам.
Комментарии (25)
panzerfaust
16.06.2023 15:15+1Поздравляю, этот roadmap, как мне кажется, может сделать даже из новичка Java-разработчика с эквивалентом 7-8 лет
В годах Меркурия считаете?
auddu_k
16.06.2023 15:15+1На этом этапе вы уже должны достигнуть уровня Java-разработчика с 4-летним опытом
Улыбнуло)
А если я сначала прочитаю вот это всё, а потом 4 года от строчки до строчки, что получится?
А если сначала четыре года, а потом начать читать?
:-)
breninsul
16.06.2023 15:15+4Честно говоря, Kotlin не имеет минусов перед Java, но имеет поюсы.
Ужасающая многословность java превращает код в череду проверок на налл, где постоянно будут ошибки из-за копипастов, а также ужасный JPA и практика использовать геттеры-сеттеры
Tellamonid
16.06.2023 15:15Всё, что сейчас добавляют в Джаву, сделано позже, чем в Котлине, но при этом лучше, чем в Котлине. Целая команда крутых архитекторов сильно продумывает фичи, и как правило, делает несколько PoC, прежде, чем выпустить фичу. И получается очень хорошо: и с записями, и с value-типами, и проектом Loom, и много с чем ещё. Loom вообще хороший пример, как надо делать фичи. В Котлине корутины сделаны раньше, но далеко не так элегантно, приходится размечать асинхронный код.
APXEOLOG
16.06.2023 15:15Мне нравится как сейчас развивается Java, но писать по-прежнему приятнее на Kotlin. Потому что Kotlin - это в первую очередь про сахар, а большинство JEP'ов - про низкоуровневый функционал.
В целом я вижу только плюсы - в итоге можно будет писать на Kotlin с использованием всех новых плюшек
poxvuibr
16.06.2023 15:15а также ужасный JPA
А JPA то вам чем не угодил?
и практика использовать геттеры-сеттеры
Как геттеры и сеттеры мешают программисту?
breninsul
16.06.2023 15:15-1очень легко мешает.
Если есть сеттеры - обьект мутабельный.
Ты передал его как аргумент и не можешь быть уверен в его состоянии.
При переносе с ДТО в энтити и наоборот вы контролируете количество полей исключительно руками, когда allArgsConstructor требует все (нужные) поля.
JPA требует конструктор без аргументов и не final переменные (hibernate позволяет обойти, но через костыли).
Составные ключи через костыли.
Кастомные типы, массивы и даже егамы не поддерживаются по дефолту, не говоря про незаменимый jsonb.
Есть способы и готовые библиотеки заставить jsonb работать, но абсолютно через задницу, синтаксиса по работе с полями jsonb нет, надо использовать нативыные запросы.
Как происходит получение вложенных списков?
Например пользователь со списком привязанных к нему банк. карт.
Идет join , запрос возвращает количество строк равное количеству карт, orm по хэшу пользователя их группирует. Как только списков становится несколько - оно перестает работать. ORM банально не может знать что к чему группировать, это же просто набор строк. Не говоря, что это затратные операции. При этом вы в sql можете вернуть список карт как массив или jsonb. Избегая n+1 проблемы, кстати.
У вас есть транзакция. Большинство операций читающие. Вы создали энтити. Есть 1 операция, где надо изменить сумму. Как вы это реализуете? JPA подталкивает вас не думать об этом, сделать trx.setSum(trx.getSum()+diff)
Только вот у нас есть параллельные транзакции? Вы повесите select for update на всю энтити? Сделаете несколько энтити на разные операции, чтения/обновления? Очень удобный маппинг выйдет. При это м sql вам даже не надо читать обьект, просто update trx t set sum=t.sum+:diff. Оно вынуждает вас городить кучу ненужного, запутывающего кода на простейшие операции
Lazy поля. Иногда вам не нужен внутренний список, иногда нужен. Вы или делаете lazy, теряя перформанс на лишний запрос, или получаете список там, где могли этого избежать. При этом мы обязаны помнить про лэйзи поля, работа с ними должна быть в той-же транзакции. Что это за абстракция такая, которая течет не начав работать?
poxvuibr
16.06.2023 15:15+2Если есть сеттеры - обьект мутабельный.
Ааа, акцент на сеттерах, а геттеры просто были упомянуты за компанию. Я не так понял ))
Ты передал его как аргумент и не можешь быть уверен в его состоянии.
В том числе поэтому мы мапим энтити в ДТО.
JPA требует конструктор без аргументов и не final переменные (hibernate позволяет обойти, но через костыли).
Hibernate позволяет возвращать из запросов ДТО, или можно сразу использовать Spring Projections.
Как только списков становится несколько - оно перестает работать.
Тут надо уточнить, что речь о том, что у пользователя может быть список карт и ещё, допустим, список машин. И тогда у ОРМ будет проблема выбора этого списка одним запросом. Из-за ограничений классического SQL.
И понятно, что сначала надо вытащить пользователей с картами и ещё одним запросом вытащить машины. И точно также всё будет если использовать SQL.
При этом вы в sql можете вернуть список карт как массив или jsonb.
Если использовать такие штуки, как массивы и jsonb для формирования полей в ответе, то можно добиться примерно того же эффекта, что Hibernate производит с помощью @BatchSize . Времени придётся потратить больше, кода написать больше, но да, возможно даст похожие результаты.
Если прямо сразу хранить списки в jsonb, то впринципе при использовании чистого SQL получится, написав больше кода и потратив больше времени, достичь похожих результатов.
Может быть получится выиграть немного производительности или уменьшить количество трафика между БД и приложением. А может и нет, не уверен.
Избегая n+1 проблемы, кстати.
Как и в случае с @BatchSize
У вас есть транзакция. Большинство операций читающие. Вы создали энтити. Есть 1 операция, где надо изменить сумму. Как вы это реализуете?
Update Trx t set t.sum = t.sum + : diff
JPA подталкивает вас не думать об этом, сделать trx.setSum(trx.getSum()+diff)
Можно и так, особенно, если энтити уже всё равно вычитаны.
Только вот у нас есть параллельные транзакции?
В смысле что-то, что одновременно меняет сумму в одной транзакции? Так они же специально создаются, чтобы засунуть туда только одно изменение. Может вы про то, что нужно изменять сумму, доступную на счету?
Вы повесите select for update на всю энтити?
На эту СУБД-транзакцию, да.
При это м sql вам даже не надо читать обьект, просто update trx t set sum=t.sum+:diff.
Прямо как в JPQL, да.
Вы или делаете lazy, теряя перформанс на лишний запрос, или получаете список там, где могли этого избежать.
Мы всегда делаем lazy и используем join fetch или энтити графы или @BatchSize, когда не хотим делать лишних запросов ))
Что это за абстракция такая, которая течет не начав работать?
Как абстракция JPA действительно не очень, это скорее набор инструментов, который уже делает то, что в случае использования чистого SQL вам пришлось бы писать руками. Но надо понимать как им пользоваться, тут никуда не денешься.
breninsul
16.06.2023 15:15-1В смысле что-то, что одновременно меняет сумму в одной транзакции? Так они же специально создаются, чтобы засунуть туда только одно изменение. Может вы про то, что нужно изменять сумму, доступную на счету?
у вас же не serializeble изоляция?
Тогда по сути паралельные транзакций не будет. Но это обычно не то, чего мы хотим от приложения
Иначе очень легко.
Транзакция 1 - читает из БД. Сумма=1
Транзакция 2 - читает из БД. Сумма=1
Транзакиция 1 увеличивает сумму на 2.
Транзакиция 2 увеличивает сумму на 3.
В итоге имеем 4 вместо 6ти.
breninsul
16.06.2023 15:15И нет, batch size делает вообще не это, batch size делает ровно то, чего от нее ожидаешь по названию
"
@BatchSize
specifies a "batch size" for fetching instances of this class by identifier. Not yet loaded instances are loaded batch-size at a time (default 1)."Я же говорю про inner select и CTE.
Hibernate можно постараться приказать делать inner select, только он будет игнорировать указания в ряде случаев (и не упадет с ошибкой)
breninsul
16.06.2023 15:15*также можно использовать группировку.
В общем вы просто можете получить вложенный список как вложенный список (чудо).
И нет, производительность не немного отличается, а очень-очень сильно отличается. Это легко можно или проверить, или загуглить.
APXEOLOG
16.06.2023 15:15+1Как геттеры и сеттеры мешают программисту?
Раздуванием кода.
Во-первых, я обязан использовать lombok (или генерить десятки-сотни однотипных аксессоров в IDE, что еще хуже)
Во-вторых, весь код напичкан префиксами get/set. И это не приносит абсолютно никакой пользы, просто увеличивает длину строк
Я считаю, что `getX / setX` - это подход полезный 20 лет назад, когда код писали в блокноте. Так же как и именование переменных с префиксом типа (`iVar, sVar`) и прочие конвенции. Но в современном мире, где у нас есть отличные IDE с подсветкой синтаксиса, автокомплитом, поиском по коду и т.д. это просто не нужно
cupraer
16.06.2023 15:15+14После прочтения тонны макулатуры, почти каждый сможет обсуждать язык на уровне разработчика с опытом в 3–5–7–9 лет.
Но писать код они по-прежнему будут на уровне джуна с нулевым опытом.
Leetc0deMonkey
16.06.2023 15:15+5Нынешняя система собесов такая что да, нужно уметь "обсуждать". А как там кодит кандидат в реальных условиях - это уже потом вскроется. Главное проскочить собес. Спрос рождает предложение. Вот и продавцы курсов подтягиваются. Ничего личного, просто бизнес.
ifFamous
16.06.2023 15:15Подтверждаю. Как раз изучаю java и действительно, одно дело знать что-то и совсем другое написать код, используя эти знания. Плюс, всегда вылезает куча каких-то моментов, которые вскрываются при написании кода)
MSid
16.06.2023 15:15Я думал тут будут БД, кубы, облака... Что за разработчик с 4 годами опыта который только джаву знает? Свой инструмент конечно надо знать на отлично, но важно знать не только его. Хотите переплюнуть профессиональных разработчиков прочитав пару книг и не решив ни одной задачи бизнеса? А ещё наверное на синьера собеситься можно после этих книг?)
dmserebr
16.06.2023 15:15Крайне спорный подход - изучать крайне тонкие нюансы программирования на Java (чтобы "казаться" разработчиком с 5-7-летним опытом) и при этом полностью игнорировать Spring, работу с БД, фреймворки для написания тестов и вообще принципы написания тестов.
Все же вероятность стать реально востребованным разработчиком довольно мала, если даже хорошо знать особенности самого языка и runtime, но при этом отойти на шаг влево или вправо - все, "не знаю, не сталкивался".
dyadyaSerezha
Это точно был Гугл? Мой выдает правильное группирование - 1,290,000,000.
Firsto
Кстати, это 1,56 араб или 156 крор в индийской нумерации. ¯\_(ツ)_/¯
Странно, что результаты разные...