ТОП-10 ошибок начинающих Java программистов

Подборка популярных ошибок начинающих Java программистов

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

Неправильное преобразование массива в ArrayList

Чаще всего это выглядит так:

Дальше идет работа с этим списком: попытки добавления/удаления элементов, обновление уже существующих т.д.

В такой ситуации следует помнить, что список, который возвращает метод Arrays.asList() является внутренним статическим классом внутри класса Arrays ( класс java.util.Arrays.ArrayList) и, как видите, это не экземпляр java.util.ArrayList класса. В экземпляра java.util.Arrays.ArrayList класса есть методы set(), get()contains()методы и нет возможностей добавления элементов, потому что его размер фиксируется.

Правильным выходом в данной ситуации будет создание экземпляра java.util.ArrayList класса. Сделать это можно следующим образом:

Отдельно хочу отметить, что это одна из самых популярных ошибок среди начинающих программистов. Она появляется по причине того, что человек начал изучать SDK, поверхностно ознакомился с методами для обработки массивов, нашел интересующий его метод, но не вник в детали того как он работает и делает ли он вообще то, что от него ожидают. Такой подход чаще всего встречается среди начинающих, которые в короткие строки перерабатывают множество новой информации по Java. Но ради справедливости стоит отметить, что и более опытные разработчики часто грешат этим.

Подробнее о работе с массивами читайте здесь. А о самом методе Arrays.asList() тут.

Сложная проверка на то, содержит ли массив значение

Еще одна интересная ошибка, которую постоянно допускают новички. Давайте рассмотрим на примере популярный вариант проверки:

Как видите, у нас есть метод для проверки того, содержит ли массив какой-то элемент. Его суть сводится к тому, что мы оборачиваем входной массив в HashSet и пользуемся стандартными методами коллекции для поиска элемента. Удобно ведь — все так делали 🙂 Такой метод работать будет, но работать дольше, чем другие способы, да и писать его дольше.

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

Лучшим выходом в данной ситуации я бы назвал использование такого способа:

Как видите, подход похож, но записывается всего в 1 строку. Или вспомнить самый простой и надежный способ:

Если бы выбирать из этих двух способов проверки содержит ли массив значение, то я бы выбрал первый — за удобство и лаконичность. А что используете Вы в такой ситуации? Пишите в комментариях.

Попытка удалить элемент во время обхода списка

Рассмотрим пример кода, в котором происходит попытка удалить элемент во время обхода элементов списка:

В ходе выполнения этого кода будет выброшено ConcurrentModificationException, так как нельзя удалять элементы во время итерирования по списку. Такая же ситуация будет и с for-each циклом. Удалять элементы безопасно можно только при использовании интерфейса Iterator, например, так:

Подробнее об исключении ConcurrentModificationException читайте здесь.

Всегда используют ArrayList и не знают где использовать LinkedList

Когда разработчик не знает разницы между ArrayList и LinkedList, то чаще всего предпочтение отдает ArrayList — это ведь просто и знакомо. Тем не менее, существует огромная разница в производительности между этими коллекциями. Если вкратце, то LinkedList желательно использовать, если имеется большое количество операции добавления или удаления. Лучше об этой коллекции и других читайте в обзорной статье Коллекции в Java.

Не знают в чем разница между изменяемостью или неизменяемостью объектов в Java

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

Если вкратце, то изменяемые объекты используются для того, чтобы избежать большого количества промежуточных объектов. Отличным примером будет конкатенация большого количества строк: если вы используете строку, то по ходу дела создается много объектов, которые должны немедленно отправиться на сборку мусора. Это напрасно тратит время процессора, поэтому правильным будет решение со StringBuilder.

Подробнее об этой теме читайте в статьях: ТОП-10 вопросов по строкамПочему строки неизменные?.

Не знают разницу между созданием строк с использованием конструктора и двойных кавычек («»)

Строки в Java можно создавать с помощью конструктора, например, с помощью двойных кавычек («»):

Казалось бы, эти строки полностью одинаковы, но есть ряд нюансов, о которых часто забывают начинающие Java разработчики. Смотрим на примере:

Понять почему происходит так, а не иначе Вам поможет статья Что такое пул строк в Java? и Почему строки в Java неизменные.

Не знают разницу между Hashtable или HashMap?

Одним из ключевых отличий Hashtable и HashMap является то, что Hashtable синхронизирована. Поэтому в большинстве случаев нужно использовать HashMap, а не Hashtable. Подробно об этом я писал в отдельной статье.

Не знают разницу между Set или Set<?>

Программисты, которые только начинают свой путь в Java, не знают разницу между Set и Set<?>. Это касается и других коллекций. Подробнее в этой статье.

Не используют правильные уровни доступа

Очень часто разработчики используют модификатор доступа public для полей класса. Да, в этом случае очень удобно и легко получить значение поля, но это считается плохим тоном в разработке на Java. Давайте полям класса уровень доступа как можно ниже.

На этом моя подборка заканчивается. Если у Вас есть что добавить к популярным ошибкам начинающих (и не очень) Java разработчиков, жду Вас в комментариях :).

3 thoughts to “Подборка популярных ошибок начинающих Java программистов”

  1. У меня пример с попыткой удаления элемента при обходе списка не выбросил исключение. Исключение выбрасывается только когда явно использую итератор, как в примере по ссылке.

  2. Вообще пример с попыткой получения ошибки ConcurrentModificationException при удалении элемента во время обхода списка некорректен. Чтобы получить эту ошибку нужно либо использовать итератор в явном виде, либо использовать цикл в стиле foreach. На stackoverflow разбирался вопрос почему не возникала ошибка при удалении элемента даже в случае использования итератора — оказывается, если удаляемый элемент в единственном числе и предпоследний, то все отработает нормально 🙂
    Так что имхо лучше заменить пример и добавить, что в документации сказано дословно «для удаления элементов из коллекций в циклах использовать итератор». Как вариант, понравилось решение:
    List listOfStrings = new ArrayList(Arrays.asList(«z», «x», «c», «v»));
    listOfStrings.removeIf(s -> s.equals(«x»));
    System.out.println(listOfStrings.toString());

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *