Ошибки начинающих java программистов

Время на прочтение
10 мин

Количество просмотров 16K

С какими трудностями встречается начинающий разработчик java?

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

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

Контрольный список ошибок:

  1. Опечатки. Досадные опечатки, которые не сразу обнаруживаются
  2. Присвоение в условии вместо сравнения
  3. Логические ошибки в условии
  4. Неправильное сравнение строк
  5. Неправильная инициализация переменных примитивных типов
  6. Неправильное использование double
  7. Неправильный тип возвращающего значения в конструкторе.
  8. Деление на ноль. POSITIVE_INFINITY
  9. Не учет порядка инициализации класса
  10. Локальная переменная скрывает переменную класса
  11. Игнорирование автоматически приведение типов в арифметических выражениях
  12. Бесконечный цикл с byte, который трудно обнаружить.
  13. Имя класса отличается от имени файла, в котором он хранится.
  14. Не проинициализированы объекты, являющиеся элементами массива.
  15. Помещение в один файл сразу нескольких классов с модификатором public

Подводные камни Java

Все языки программирования имеют свои достоинства и недостатки. Это обусловлено многими причинами. Язык Java не исключение. Я попытался собрать некоторые очевидные и не очевидные трудности, с которыми сталкивается начинающий программист Java. Уверен, что опытные программисты также найдут в моей статье что-то полезное. Практика, внимательность и полученный опыт программирования, помогут избавить вас от многих ошибок. Но некоторые ошибки и трудности лучше рассмотреть заранее. Я приведу несколько примеров с кодом и объяснениями. Многие объяснения вам станут понятны из комментариев к коду. Практика дает очень многое, так как некоторые правила не столь очевидны. Некоторые лежат на поверхности, некоторые скрыты в библиотеках языка или в виртуальной машине java. Помните, что java это не только язык программирования с набором библиотек, это еще и виртуальная машина java.

Для статьи я специально написал работающий код с подробными комментариями. Для написания статьи с примерами кода использовалась java 8. Для тестирования код java помещен в отдельные пакеты.

Пример: «package underwaterRocks.simple;»

С какими трудностями сталкиваются начинающие?

Опечатки

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

Пример кода:

Файл: «Simple.java»

/*
учебные пример
; после условия и блок 
*/
package underwaterRocks.simple;

/**
 *
 * @author Ar20L80
 */
public class Simple {
    public static void main(String[] args) {
        int ival = 10;
        if(ival>0);
        {
            System.out.println("Этот блок не зависит от условия");
        }
    }
}

Объяснение: «Точка с запятой означает конец оператора. В данном случае ‘;’ — это конец пустого оператора. Это логическая ошибка. Такую ошибку бывает трудно обнаружить.

Компилятор сочтет, что всё правильно. Условие if(ival>0); в данном случае не имеет смысла. Потому как означает: если ival больше ноль, ничего не делать и продолжить. Очевидное решение — убрать точку с запятой.»

Присвоение в условии вместо сравнения

В условии присвоение переменной.

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

 boolean myBool = false;
if(myBool = true) System.out.println(myBool);

В данном коде if(myBool = true) означает: «Присвоить переменной myBool значение true,
если выражение истинно, выполнить условие следующее за скобками.»

В данном коде условие будет всегда истинно. И System.out.println(myBool); будет выполнено всегда, независимо от условия.

== — это сравнение на равенство.
= — это присвоение, вы можете проговорить a = 10; как: «а присвоить значение 10».

Условие в скобках возвращает логическое значение.
Не важно в каком порядке вы запишите. Вы можете сравнить так: (0 == a) или (5 == a)
Если вы забудете один знак равенства, например так (0 = a) или (5 = a), то компилятор сообщит вам об ошибке. Вы присваиваете значение, а не сравниваете.
Вы также можете записать в удобочитаемой форме какой-то интервал.
Например: вам нужно написать: a больше 5 и меньше 10.
Вы пишите так: (a>4 && a<10), но с таким же успехом вы можете написать: (4<a && a<10),
теперь вы видите, что a находится в интервале между 4 и 10, исключая эти значения. Это более наглядно. Сразу видно, что, значение переменной а находится в интервале между 4 и 10 ( ]4,10[ ), исключая эти граничные значения.

Пример в коде(интервал ]3,9[ ):
if(3<a&&a<9) выполнить;

Логическая ошибка

if(условие){} if(условие){} else{} — else относится к ближайшему if.
Часто это бывает причиной ошибок начинающих.

Неправильное сравнение строк

Начинающие довольно часто используют == вместо .equals для сравнения строк.

Инициализация переменных

Рассмотрим инициализацию переменных примитивного типа.

Примитивы (byte, short, int, long, char, float, double, boolean).

Начальные значения.

byte	0
short	0
int	0
long	0L
float	0.0f
double	0.0d
char	'\u0000'
String (or any object)  	null
boolean	false (зависит от jvm)

Примечание:

Локальные переменные немного отличаются;
Компилятор никогда не присваивает значение по умолчанию неинициализированной локальной переменной.

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

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

Подтверждение этого примечания в коде:

Файл: «MyInitLocal.java»


/*
учебные пример
инициализация переменных класса и локальных переменных
 */
package underwaterRocks.myInit;

/**
 *
 * @author Ar20L80
 */
public class MyInitLocal {
    float classes_f;
    int classes_gi;
    public static void main(String[] args) {
        float f;
        int i;
        MyInitLocal myInit = new MyInitLocal();
        
        /* в этом месте переменные уже инициализированы параметрами по умолчанию.*/
        System.out.println("myInit.classes_f = " + myInit.classes_f);
        System.out.println("myInit.classes_gi = " + myInit.classes_gi);
        
      //  System.out.println("f = " + f); // ошибка. Локальная переменная не инициализирована
      //  System.out.println("f = " + i); // ошибка. Локальная переменная не инициализирована
        
    }
}

Диапазоны значений:

byte (целые числа, 1 байт, [-128, 127])
short (целые числа, 2 байта, [-32768, 32767])
int (целые числа, 4 байта, [-2147483648, 2147483647])
long (целые числа, 8 байт, [-922372036854775808,922372036854775807])
float (вещественные числа, 4 байта)
double (вещественные числа, 8 байт)
char (символ Unicode, 2 байта, 16 бит, [0, 65535])
boolean (значение истина/ложь, используется int, зависит от JVM)

char: The char data type is a single 16-bit Unicode character. It has a minimum value of ‘\u0000’ (or 0) and a maximum value of ‘\uffff’ (or 65,535 inclusive).

Документация Oracle >>

Попытаемся инициализировать переменную типа long числом: 922372036854775807.
У нас ничего не выйдет. Потому как, это целочисленный литерал типа int.
Правильная инициализация литералом типа long: 922372036854775807L;

Пример кода:

Файл: «MyInitLocalLong.java»


/*
 учебные пример
 Инициализация long локально 
 */
package underwaterRocks.myInit;

/**
 *
 * @author Ar20L80
 */
public class MyInitLocalLong {
    public static void main(String[] args) {
      //  long al = 922372036854775807; //ошибка integer number too large
        long bl = 922372036854775807L; // так правильно  
    }
}

На что следует обращать внимание при инициализации переменной.

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

При использовании оболочек типа Integer, следует обратить внимание на авто упаковку и авто распаковку данных типов.

Неправильное использование double

Здесь нужно пояснить. Речь идет не о неправильном использовании типа double.
Используем мы правильно. Только результат может удивить начинающего программиста.
Файл: «MinusDouble.java»


/*
  учебный пример 
 */
package underwaterRocks.tstDouble;

/**
 *
 * @author vvm
 */
public class MinusDouble {
    public static void main(String[] args) {
        double a = 4.64;
        double b = 2.64;
        System.out.println("a-b = "+(a-b));
    }
}
/*
Вывод программы
run:
a-b = 1.9999999999999996
*/

Примечание о типе double. Плавающая точка позволяет считать с заданной относительной погрешностью и огромным диапазоном. В научных расчетах часто нужна относительная погрешность.

Неправильное сравнение double

Рассмотрим тип double.

Пример кода:

Файл: «MyDouble.java»

/*
 учебные пример
 Сравнение double
 Осторожно - double.
 */
package underwaterRocks.myDouble;

/**
 *
 * @author Ar20L80
 */
public class MyDouble {
    public static void main(String[] args) {
        double dx = 1.4 - 0.1 - 0.1 - 0.1 - 0.1;
        System.out.println("dx = " + dx); // dx = 0.9999999999999997
        System.out.print("Сравнение (dx == 1.0):");
        System.out.println(dx == 1.0); // false, потому что 1.0 не равно 0.9999999999999997
        
        /*как правильно сравнивать double*/
        final double EPSILON = 1E-14;
        double xx = 1.4 - 0.1 - 0.1 - 0.1 - 0.1;
        double xy = 1.0;
        /* сравниваем xx c xy */
        if (Math.abs(xx - xy) < EPSILON)
            System.out.println(xx + " это примерно равно " + xy + " EPSILON = " + EPSILON);
    } 
}
 

Тип double удобен там, где не нужна высокая точность. Для финансовых операций этот тип не годится. Хотя некоторые, не очень честные компании, использую тип double, для округления в нужную им сторону. Для финансовых операций в финансовых расчётах используется класс BigDecimal, так как вещественные примитивные типы не годятся для этой цели по причинам потери точности и ошибках результатах округления. Однако, более точные результаты дает использование класса BigInteger.

Конструктор класса

Конструктор класса совпадает с именем класса и ничего не возвращает, даже void.

Пример кода:

Файл: «MyConstructor.java»

/*
 учебные пример
 Конструктор ничего не возвращает, даже void
 То что с void  - обычный метод класса
 */
package underwaterRocks.myConstructor;

/**
 *
 * @author Ar20L80
 */
public class MyConstructor {
    public MyConstructor(){
        System.out.println("Я конструктор без void");
    }
    public void MyConstructor(){
        System.out.println("Я конструктор c void");
    }
    public static void main(String[] args) {
        MyConstructor myconst = new MyConstructor();
        myconst.MyConstructor(); // вызов обычного метода
    }
}

Как мы видим в коде два метода с одинаковыми именами: MyConstructor() и MyConstructor(). Один из методов ничего не возвращает. Это и есть конструктор нашего класса. Другой метод с void — это обычный метод класса. В случае, когда вы не создали конструктор или создали, по вашему мнению конструктор класса с void, то компилятор создаст конструктор по умолчанию и вы будете удивлены, почему ваш конструктор не работает.

Деление на ноль

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

Файл: «DivisionByZero.java»


/*учебный пример*/
package divisionByZero;
import static java.lang.Double.POSITIVE_INFINITY;

/**
 *
 * @author Ar20L80
 */
public class DivisionByZero {
    public static void main(String[] args) {
    try{
        float f = 12.2f;
        double d = 8098098.8790d;
        System.out.println(f/0); 
        System.out.println(d/0);  
        System.out.println(POSITIVE_INFINITY == f/0);
        System.out.println(POSITIVE_INFINITY == d/0);
    }
    catch (NumberFormatException ex) { 
            System.out.println("NumberFormatException"); 
        } 
        catch (ArithmeticException ex) { 
            System.out.println("ArithmeticException"); 
        }  
    }
    
}

Выполнение кода выведет:

Infinity
Infinity
true
true

Деление целого типа на ноль даст ArithmeticException.

В классе java.lang.Double определена константа POSITIVE_INFINITY;

public static final float POSITIVE_INFINITY = 1.0d / 0.0d; 

Она преобразуется в строку равную Infinity.

Порядок инициализации

Файл: «InitClass.java»


/*
 учебные пример
 инициализация класса
 */
package myInitClass;

/**
 *
 * @author Ar20L80
 */
public class InitClass {
    InitClass(){ // конструктор класса
        System.out.print("Конструктор"); 
    }
    { // блок инициализации
        System.out.print("3 "); 
    } 
    
    public static void main(String[] args) { 
        System.out.print("2"); 
        new InitClass(); 
    } 
    
    static { // статический блок инициализации
        System.out.print("1"); 
    } 
}

Вначале выполняются все статические блоки, затем блоки инициализации, затем конструктор класса.

Выведется: «123 Конструктор»

Локальная переменная скрывает переменную класса
Хотя современные IDE легко обнаруживают такую ошибку, хотелось бы рассмотреть такую ошибку подробнее. Начнем с классического присвоения переменной в конструкторе. Пример правильный. Тут никакой ошибки нет.


 public class MyClass {
   private int val = 0;

   public MyClass(int val) {
      this.val = val;
   }
}
 

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

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

Приведение типов в арифметических выражениях выполняется автоматически

Это может стать причиной досадных ошибок.

        
         // byte a = 1;
        // byte b = 1;
        // byte с = a + b; // ошибка

        //  byte a = (byte) 1;
        // byte b = (byte) 1;
        //  byte с = a + b; // ошибка
    
      // одно из возможных решений — явное преобразование в арифметических выражениях.
        byte a = 1;
        byte b = 1;
        byte c = (byte) (a + b);
   
    
        // одно из возможных решений — использование final
        // final byte a = 1;
        // final byte b = 1;
        // byte c = a + b; // автоматического приведения не будет, поскольку a и b final
    

Одно из возможных решений при работе со строкой:

byte bHundr = Byte.parseByte("100"); //  явное приведение строки к типу byte

Еще одна ошибка приведена в следующем коде.


for (byte i = 1; i <= 128; i++) {
            System.out.println(i);
        }

В данном случае получится бесконечный цикл.

Объяснение. Тип byte [-128, 127]. 128 уже не входит в этот диапазон. Происходит переполнение, и цикл повторяется. Необходимость использования byte в данном случае сомнительная. Хотя имеет место в редких случаях. Рекомендация — использовать int вместо byte. Другая рекомендация — не использовать цикл в вашем алгоритме.

Не проинициализированы объекты, являющиеся элементами массива


       int[] cats = new int[10];
       
       for(int i=0; i<cats.length;i++){
           System.out.println("cats " + i + " = " + cats[i]);
       }
 

В этом примере у нас массив элементов примитивного типа. И ничего страшного не происходит, когда мы их не проинициализировали. Им будет присвоено значение по умолчанию. В данном случае значение = 0.

Рассмотрим другой пример уже не с примитивами в массиве, а с объектами в массиве.


 public class ArrInitObj {
    public static void main(String[] args) {
        MyObj[] cats = new MyObj[10];
        for(int i=0; i<cats.length;i++){
           System.out.println("cats " + i + " = " + cats[i]);
           System.out.println("cats " + i + ".val = " + cats[i].val);
           // мы поймали исключение java.lang.NullPointerException
       }
    }
}
class MyObj{
    public int val;
}

Решение данной проблемы — инициализация всех переменных объекта перед их использованием. Инициализацию можно произвести в конструкторе класса MyObj.

Имя класса отличается от имени файла, в котором он хранится
Современная IDE легко определяет данный вид ошибки. Однако такие ошибки встречаются, хотя и довольно редко. Тут поможет внимательность, учет отличия в именах прописных и строчных букв.

Помещение в один файл сразу нескольких классов с модификатором public
Ошибка довольно редкая. IDE сразу выдаст вам предупреждение.
Имя файла должно совпадать с именем public класса.

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

Надеюсь, статья вам понравилась и оказалась полезной. Буду рад вашим комментариям, замечаниям, предложениям, пожеланиям. Продолжение следует. Вернее дополнение следует.

Ссылки
Рекомендации об оформлении кода на Javа от Oracle >>>

Какие ошибки чаще других встречаются у новичков в программировании? Возможно, они всегда путают равенство (==) с присвоением (=), или & с &&? Или же, возможно, они используют неправильные разделители в цикле for (for (int i = 0, i < 5, i++))?

Чтобы ответить на этот вопрос, исследователи рассмотрели ошибки более чем 250 000 Java-новичков со всего мира. Используя большое количество данных (исходный код более чем 37 миллионов компиляций, если быть точнее), они выявили наиболее распространенные ошибки студентов, впервые изучавших Java. Также они выяснили, как много времени занимала учёба на собственных ошибках. Результаты оказались поразительными.

На данный момент этот блок не поддерживается, но мы не забыли о нём!Наша команда уже занята его разработкой, он будет доступен в ближайшее время.

The Blackbox data collection project

Изучение нового языка программирования — это всегда вызов, поскольку вы должны научиться выражать свои сложные мысли, используя ограниченную, формальную грамматику. Естественно, многие новички делают ошибки при программировании. Чтобы пролить немного света на то, какие ошибки чаще всего делают новички, исследователи из университета Кента (Великобритания) рассмотрели код, который был собран почти у 265 000 студентов по всему миру.

Проект под названием Blackbox data collection построен на основе BlueJ, бесплатной Java IDE, спроектированной специально для новичков. BlueJ пытается устранить барьеры на пути к успеху для новичков, например, выделяя начало и конец блока кода. Это облегчает студентам процесс визуального сканирования кода на наличие лишних фигурных скобок. Ещё одна особенность данной IDE — это возможность проверки объектов прямо во время работы программы. Таким образом, это помогает пониманию принципов работы программы, а также отладке.

Blackbox также работает как расширение для BlueJ, которое собирает различную анонимную информацию о том, как используется программное обеспечение. К примеру, оно собирает информацию о том, какие функции выполняются и когда, а также с какими ошибками и как часто. Количество данных огромно. Только за один учебный год (2013—2014) было обработано 37 158 094 компиляций, 19 476 087 из которых были успешными, остальные же 17 682 007 — неудачными.

В то время как большинство людей и помыслить не может об обработке такого большого количества данных, Амджад АльТадмри (Amjad Altadmri) и Нейл Браун (Neil Brown) рассмотрели каждый из 46 448 212 файлов, участвовавших в 37 миллионах компиляций, рассмотренных выше. Они также отслеживали изменения в файлах в течение длительного периода времени. При каждой компиляции учёные проверяли исходный код для того, чтобы присвоить ему одну из 18 возможных категорий ошибок (которые они обозначили буквами от А до R). Они также подсчитали количество времени, которое потребовалось студенту для того, чтобы исправить свою ошибку (путём проверки файла, в котором ошибка уже отсутствовала).

На данный момент этот блок не поддерживается, но мы не забыли о нём!Наша команда уже занята его разработкой, он будет доступен в ближайшее время.

10 наиболее распространённых ошибок начинающих Java-программистов

АльТадмри и Браун были удивлены, обнаружив, что те ошибки, которые эксперты и преподаватели считали наиболее распространёнными, таковыми на самом деле не являются.

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

Однако, если обратиться к собранным данным, возникает чёткий рейтинг из 10 наиболее часто встречающихся ошибок (буквами от А до R обозначены 18 категорий ошибок, принимавших участие в исследовании):

С. Несбалансированные скобки, фигурные скобки или кавычки, а также использование этих символов попеременно, например: while (a == 0].

I. Вызов методов с неправильными аргументами или типами аргументов, например: list.get("abc").

O. Контрольный поток может достигнуть конец non-void метода без возвращения, например:

			public int foo(int x) {
    if (x < 0)
    return 0;
    x += 1;
}
		

А. Путаница с операторами присвоения (=) и сравнения (==), например: if (a = b).

N. Игнорирование или отбрасывание возвращаемого значения метода с non-void типом возвращения, например: myObject.toString();.

B. Использование == вместо .equals для сравнения строк.

M. Попытка вызвать non-static метод так, если бы это был static метод, например: MyClass.toString();.

R. Попытка класса реализовать интерфейс, но отсутствие реализации всех необходимых методов, например: class Y implements ActionListener { }.

P. Вызов типов параметров при вызове метода, например: myObject.foo(int x, String s);.

E.  Неправильная расстановка запятых в условиях if, а также циклах for и while, например: if (a == b); return 6;.

Наиболее частая ошибка — это C (забытые скобки, ошибки в их расстановке) — как раз то, чему пытается противостоять BlueJ, используя подсветку. Данный вывод может быть признаком того, что ошибки типа С будут ещё чаще встречаться в IDE, которые не предоставляют никаких средств для отладки.

Удивительно, но следующие ошибки не попали в ТОП-10:

D. Путаница с использованием операторов «короткого замыкания» (&& и ||) и обычных операторов логики (& и |).

J. Отсутствие скобок после вызова метода, например: myObject.toString;.

Q. Присваивание переменной значения с типом, несовместимым с типом переменной, например: int x = myObject.toString();.

F. Неправильные разделители цикла for (использование запятой вместо точки с запятой), например: for (int i=0, i < 6, i++).

H. Использование ключевых слов в качестве имён переменных или методов, например: int new;.

На данный момент этот блок не поддерживается, но мы не забыли о нём!Наша команда уже занята его разработкой, он будет доступен в ближайшее время.

Сколько времени занимает учёба на своих ошибках

Кроме того, когда Браун и АльТадмри изучили, сколько времени требуется, чтобы студенты исправили ошибку, стало ясно, что наиболее распространённая ошибка (ошибка С) была также одной из самых быстронаходимых. Другие ошибки было найти труднее. Среди таких ошибок была путаница между операторами & и | или && и || (ошибка D), использование == вместо .equals для сравнения строк (ошибка B) и игнорирование или отбрасывание возвращаемого значения метода с non-void типом возвращения (ошибка N). Они оставались незамеченными более чем 1 000 секунд (после чего отслеживание не продолжалось) или не были найдены вообще никогда.

Медиана, показывающая соотношение время-исправление (time-to fix), показана на рисунке ниже.

P.S. От редактора: забавно, но в статье про самые распространённые ошибки программистов автором была допущена самая распространённая ошибка программистов — не закрыта скобка тега . Будьте внимательны к своему коду!

Собрали наиболее распространенные ошибки начинающих Java-разработчиков. Они помогут избежать проблем в учебе и дальнейшей работе.

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

Пренебрегают существующими библиотеками

Часто начинающие разработчики игнорируют бесчисленное количество библиотек, написанных на Java. Прежде чем изобретать колесо, попробуйте найти доступные библиотеки, многие из них были доведены до идеала за годы своего существования и бесплатны в использовании. Это могут быть библиотеки для ведения журнала, такие как logback и Log4j, или сетевые библиотеки, такие как Netty или Akka. 

Не проверяют возвращаемое значение методов

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

Не используют модификатор final

Модификатор final позволяет объявить переменную, константу или метод, которые нельзя изменять после их создания. Начинающие Java-разработчики часто не используют модификатор final, что может привести к проблемам, особенно если они работают с многопоточными приложениями. Чтобы избежать этой ошибки, используйте модификатор final там, где это необходимо.

Не используют try-catch блоки

Try-catch блоки позволяют обрабатывать исключения, которые могут возникнуть во время выполнения программы. Начинающие Java-разработчики часто не используют try-catch блоки, что может привести к тому, что программа просто остановится, если возникнет исключение. Чтобы избежать этой ошибки, используйте try-catch блоки там, где это необходимо.

Не удаляют объекты из памяти

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

Мы попросили менторов Kata Academy сказать, какие самые распространенные ошибки Java-программиста могут встретиться новичкам. И вот какие ответы получили.

vddv

Основные ошибки: чрезмерно перегруженный код, большие методы, некорректный нейминг методов и переменных. Часто новички совершают ошибки при работе с гитом. Ещё не перепроверяют работу приложения/сервиса перед деплоем, излишняя самоуверенность может приводить к нелепым поломкам. После обучения многие забывают стандарты написания кода, совершают «детские» ошибки из-за невнимательности.

ht

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

jy

Не хватает студентам знаний из книги Clean code, Robert Martin. Далее непонимание, что такое бизнес логика и, как следствие, определение её в коде. Многие новички не понимают, зачем и для чего нужны паттерны проектирования, как выглядит паттерн Singlеton на примере Java-класса, хотя бы самую простую реализацию.

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

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

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

List<String> list = Arrays.asList(array);

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

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

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

List<String> safeList = new ArrayList<String>(Arrays.asList(array));

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

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

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

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

private boolean containsValue(String[] array, String whatToCheck) {

    Set<String> set = new HashSet<String>(Arrays.asList(array));

    return set.contains(whatToCheck);

}

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

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

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

Arrays.asList(array).contains(whatToCheck);

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

...

for(String string: array) {

    if(string.equals(whatToCheck)) {

return true;

    }

}

return false;

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

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

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

List<String> listOfStrings = new ArrayList<String>(Arrays.asList(«z», «x», «c», «v»));

for (int i = 0; i < listOfStrings.size(); i++) {

    if (listOfStrings.get(i).equals(«x»)) {

        listOfStrings.remove(i);

    }

}

System.out.println(listOfStrings.toString());

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

List<String> listOfStrings = new ArrayList<String>(Arrays.asList(«z», «x», «c», «v»));

Iterator<String> iterator = listOfStrings.iterator();

while (iterator.hasNext()) {

    String s = iterator.next();

    if (s.equals(«x»)) {

iterator.remove();

    }

}

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

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

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

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

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

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

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

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

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

// с использованием двойных кавычек

String x = «Java»;

// с использованием конструктора

String y = new String(«Java»);

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

String stringOne = «Java»;

String stringTwo = «Java»;

System.out.println(stringOne == stringTwo);  // получим true

System.out.println(stringOne.equals(stringTwo)); // тоже получим true

String stringThree = new String(«Java»);

String stringFour = new String(«Java»);

System.out.println(stringThree == stringFour);  // получим false

System.out.println(stringThree.equals(stringFour)); // получим true

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

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

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

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

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

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

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

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

When we talk about advanced yet programming languages, Java is one of the best. It is a widely used developing program for developing applications & software. For newbies, it’s hard to learn Java. Mostly, in the start, the freshers make errors in their programming.

In this article, we will concern about some common beginner mistakes in Java programming

Some Common Mistakes

Not Comprehending the Basics of Java Programming

Object-based development is a crucial aspect of Java programming. Newbies often create the error of not fully understanding the basics of Java programming, such as classes, objects & inheritance. It can direct to errors & inefficient code. It is vital to have a solid foundation in programming to evolve into a professional Java programmer.

Not Correctly Declaring Variables

One of the most typical mistakes that beginners do in Java programming is not announcing variables. Declaration of variables with a data type is a must-do practice in Java programming. You can use the information type such as int, float, or string. Failure to declare variables can result in syntax errors and program crashes. It is crucial to declare variables correctly to avoid these errors.

Not Properly Closing Resources

Another common mistake that beginners make in Java programming is not properly closing resources, such as database connections, file streams, and network sockets. If you face failed to close resources, then it can lead to memory leaks. With this, the program can slow down or crash. It is essential to close resources properly to avoid these problems.

Not Handling Exceptions

Exceptions are a part of Java developers that are used to handle errors and unexpected events that can occur during program execution. Beginners often make the mistake of not handling exceptions correctly, leading to program crashes & unexpected results. It is crucial to handle exceptions properly to ensure the program runs smoothly.

Using Inefficient Data Structures

Java delivers different data structures. The structures are arrays, lists, & maps. You can use them to store & manipulate data. However, beginners often make the mistake of using inefficient data structures that can slow down the program’s performance. It is necessary to choose the proper data structure. It is needed for the task at hand to deliver optimal performance.

Not Using Comments

Comments are an essential part of Java programming and are used to explain the code’s purpose and functionality. Beginners often make the mistake of not using comments, making it difficult for others to understand their code. It is crucial to use comments to make the code more readable and understandable.

Not Testing Code

Testing is an essential part of Java programming & is used to ensure the program’s functionality and performance. Beginners often make the mistake of not testing their code, leading to errors and bugs. It is crucial to test the code entirely to confirm it is error-free & performs as expected.

Not Following Naming Conventions

Java has specific naming conventions for variables, classes, and methods. Beginners often make the mistake of not following these conventions. It leads to confusion and errors. It is vital to follow the naming patterns to create code more readable & understandable.

Using Nested Loops Inefficiently

Nested loops are an effective tool in Java programming. But newbies often use them inefficiently, leading to poor performance. It is crucial to use nested loops only when necessary and to optimize them to ensure optimal performance.

Not Using Java Libraries

Java has an extensive array of libraries. You can use it to complete common tasks. These tasks include parsing data, handling dates and times, and encrypting data. Beginners often make the mistake of not using these libraries, leading to the reinvention of the wheel and inefficient code. It is crucial to use Java libraries whenever possible to save time and improve code quality.

Hard-Coding Values

Hard-coding values, such as constants and file paths, directly into the code can make it difficult to modify the code later. Beginners often make the mistake of hard-coding values instead of using configuration files or environment variables. It is crucial to avoid hard coding values to make the code more flexible and maintainable.

Not Using Object-Based Design Practices

Object-based design is various best practices for developing & executing object-oriented software. Beginners often make the mistake of not using these patterns, leading to poorly designed and inefficient code. It is essential to learn & use this kind of design pattern to make sure code quality & maintainability.

Conclusion

By avoiding these common beginner mistakes and practicing good programming habits, beginners can become proficient Java programmers and develop efficient and reliable software applications.

Hope this article is helpful to you. In conclusion, Java programming is a complex and challenging task, especially for beginners. However, by understanding the basics of object-oriented programming, properly declaring variables, closing resources, handling exceptions, using efficient data structures, using comments, and testing code, beginners can avoid common mistakes and become proficient Java programmers.

  • Related Articles
  • What are common Python programming mistakes programmers do?
  • Common Mistakes Beginner Project Managers Make
  • Common Mistakes Beginner Quality Managers Make
  • Common Mistakes Beginner DevOps Professionals Make
  • What Are Some Common Social Media Marketing Mistakes Businesses Make?
  • What are some common mistakes hiring managers to see on resumes?
  • What are some good beginner’s projects in Python?
  • What are some common funeral etiquette?
  • What are some common forms of scamming?
  • Common Mistakes in Project Scope Management
  • Beginner Tips for Learning Python Programming
  • What are common programming errors or ‘gotchas’ in Python?
  • The Most Common Email Marketing Mistakes
  • What are some of the common types of Hacking?
  • What Are Some Common Project Management Metrics to Track?
Kickstart Your Career

Get certified by completing the course

Get Started

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