Статьи

Топ 10 + 1 распространенных ошибок, которые каждый ученик Java делает

Говорят: «Твой друг проглотит твои ошибки, твой враг представит их на тарелке». Я определенно не ваш враг, но я хочу представить вам некоторые ошибки, характерные для каждого начинающего Java-студента, и я сделаю это прямо здесь, на этой «табличке» блогов. Конечно, есть только некоторые из них, я собрал из курсов CodeGym.cc аналитической системы. Если вы еще не знаете, CodeGym — практический курс Java с нуля до уровня выше среднего.

Итак, вот они.

0. Назначение или сравнение (= или ==)?

Это одна из первых ошибок студентов, которые изучают Java с нуля. Легко спутать, что = является оператором присваивания, тогда как == является реляционным оператором. Это естественная ошибка, потому что в математике «=» ближе к « == » в Java, чем к «=» в Java. Обычно компилятор отлавливает такие ошибки, однако они могут быть скрыты от него. Например:

1
2
3
4
boolean myBoolean;
If (myBoolean = true) {
doSomething;
}

Увидеть? В любом случае этот блок будет истинным, потому что вы назначаете его истинным …

1. Сравнение строк с оператором ==.

Через некоторое время после того, как вы выполнили свои первые задачи на Java (обычно есть некоторые проблемы с выводом на консоль и арифметическими проблемами), вы изучаете класс String. Однако новички часто забывают, что конкретная строка не является представителем примитивного типа, такого как char или int, это объект. Вы не можете сравнивать объекты, используя оператор ==. Не забывайте использовать функцию string.equals (Object object) для сравнения строк (или других объектов), а не оператор == . Равно проверяет содержимое строки, а оператор == проверяет, равны ли ссылки на объекты.

Если честно, строковые константы обычно «интернированы». Это означает, что две константы с одним и тем же значением могут фактически сравниваться с == , но на самом деле не полагайтесь на это. Используйте .equals.

2. Разные имена класса и файла, в котором находится его код.

Эта ошибка была очень популярна (может быть, даже лидер всех) несколько лет назад. Теперь даже новички используют современные IDE, и он находится на грани исчезновения. В любом случае, полезно иметь в виду, что в Java имя файла и имя класса должны совпадать. Если вы назовете свой файл, например, Test.java, и напишите там код класса CodeGymTest:

1
2
3
4
5
6
7
//File name: Test.java
 
public class CodeGymTest {
   public static void main(String[] args) {
        System.out.println("Hello world");
   }
}

Вы получите следующий вывод:

1
2
3
4
5
Test.java:9: error: class CodeGymTest is public, should be
                    declared in a file named CodeGymTest.java
public class CodeGymTest
^
1 error

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

3 Доступ к нестатическим членам из основного метода или других статических методов

Довольно часто начинающие не знают, как работать со статическим контекстом. Статическая переменная является общей для всех экземпляров класса. Следовательно, существует только одна его копия, которая используется всеми объектами. Поэтому мы не можем работать с нестатической переменной «статическим способом». Эта ошибка обычно происходит в main()method (which is static!), when novice programmer attempts получить доступ к переменной или методу экземпляра. Если вы попробуете такой код

1
2
3
4
5
6
7
public class MyExample {
    public String myString; 
 
public static void main(String[] args) {
        myString = “non static String”;   
}
  }

У нас есть ошибка компиляции:

non-static variable number cannot be referenced from a static context .

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

1
2
3
4
5
6
7
8
9
public class MyExample {
    public String myString; 
 
public static void main(String[] args) {
MyExample myExample = new myExample();
 
        myString = “non static String”;   
}
  }

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

4. Индекс массива выходит за пределы массива

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

1
2
3
4
String[] name = { "Snoopy", "Woodstock", "Charlie Brown" };
for (int i = 0; i <= name.length; i++) {
    System.out.println(name[i]);
}

Цикл начинается с нулевого элемента «Снупи», затем переходит к первому «Вудстоку» и второму «Чарли Брауну»… и пытается напечатать третий элемент, но у нас его нет (наш «третий» является «Второй», такой как «первый», равен нулю). Здесь ошибка довольно очевидна, но это не всегда так.

Циклы и массивы довольно жесткие для новичков. Однако практика делает бриллианты. В CodeGym есть сотни задач Arrays & Cycles. Попробуйте решить их (пока это бесплатно!), Чтобы получить уверенные навыки.

5. Путинга «;» неправильно в циклах или условных выражениях

В блоке ниже вы не печатаете ни одного из элементов массива. Во-первых, цикл заканчивается на «;» так что ничего не происходит. Более того: программа не будет работать, потому что ваш int работает только внутри цикла и заканчивается на «;».

1
2
3
4
5
6
7
8
public static void main(String[] args)  {
 
            int [] myArray = {2,5,7};
            for (int i=0; i<3; i++);
            {
                System.out.println(myArray[i]);
            }
        }  

Если вы попробуете что-то вроде этого:

01
02
03
04
05
06
07
08
09
10
public static void main(String[] args)  {
 
            int [] myArray = {2,5,7};
            int i = 0;
 
            for (i=0; i<3; i++);
            {
                System.out.println(myArray[i]);
            }
        }

У вас есть java.lang.ArrayIndexOutOfBoundsException, потому что System.out.println пытается напечатать элемент № 3 и только этот, но у нас нет такого члена массива. Последний является вторым, и это 7.

Та же история с ; и условия. Например:

1
2
3
4
5
6
7
public static void main(String[] args)  {
 
            int [] myArray = {2,5,7};
           if (myArray[0] > myArray[1]);
            System.out.println("it is");
        }
    }

Условие здесь не выполняется, но «оно» будет напечатано из-за «;» после, если строительство.

Если вы начнете изучать CodeGym, вы получите первые задачи по программированию с циклами квеста Java Syntax уровня 4 . Я полагаю, вы забудете о таких ошибках, решающих достаточно проблем.

6. Отсутствует ключевое слово break в конструкции Switch-Case

Смущает отсутствие ключевого слова «break» в том, что нет ошибки компилятора. Однако ваш код работает неправильно.

Посмотрите на пример кода ниже, где мы забыли поставить разрыв в «case 0». Программа будет работать, но она печатает как «0», так и «1», потому что конструкция переключателя завершает свою работу с перерывом.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
public static void switchCasePrimer() {
        int counting = 0;
 
        switch (counting) {
            case 0:
                System.out.println("0");
            case 1:
                System.out.println("1");
                break;
            case 2:
                System.out.println("2");
                break;
            default:
                System.out.println("Default");
        }
}

Это правило имеет исключение. Блок переключателей может завершить свою работу с оператором возврата

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
public class test {
    public static void main(String[] args) {
        System.out.println(showSwitch(1));
    }
 
    public static int showSwitch(int condition) {
        switch (condition) {
            case 1:
                System.out.println(1);
                return 1;
            case 2:
                System.out.println(2);
                return 4;
            case 3:
                System.out.println(3);
                return 8;
            default:
                System.out.println("default");
                return 256;
        }
    }
}

В этом случае коммутатор завершает свою работу сразу после случая 1.

7. Беспорядок с передачей по значению и передачей по ссылке

Если вы передаете примитивный тип данных, такой как char, int или double, методу, вы передаете по значению. Это означает, что копия типа данных будет продублирована и передана вашему методу. Если эти данные изменяются внутри метода, они не влияют на «исходные» данные вне метода.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
public class Main {
 
    public static void swap(int i, int j)
    {
        int temp = i;
        i = j;
        j = temp;
        System.out.println("from swap method i = " + i + ", j = " + j);
    }
 
 
    public static void main(String[] args) {
 
 
        int i1 = 1;
        int j1 = 2;
        swap(i1,j1);
        System.out.println("from main method i = " + i1 + ", j = " + j1);
 
    }
}

Когда вы передаете Java-объект, например, массив или строку, методу, это означает, что вы передаете ссылку (адрес ваших данных), а не дубликат. Поэтому, если вы измените данные в методе, они также будут изменены и вне его.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Main {
 
    static int[] outer = new int[3];
 
    public static void swap(int[] array) {
        System.out.println("(swap) Before swap :" + Arrays.toString(array));
        int first = array[0];
        int last = array[array.length - 1];
        array[0] = last;
        array[array.length - 1] = first;
        System.out.println("(swap) After swap :" + Arrays.toString(array));
    }
 
 
    public static void main(String[] args) {
        outer[0] = 0;
        outer[1] = 1;
        outer[2] = 2;
 
        swap(outer);
 
        System.out.println("(main) After swap :" + Arrays.toString(outer));
    }

8. Попытка работать с неинициализированным полем или переменной

Работа с типом объекта без инициализации довольно опасна.

Переменные класса инициализируются значением по умолчанию (0 для int, 0.0 для double, false для логического, null для не примитивных типов (объектов).

1
2
3
4
5
6
7
8
public class Test2 {
    static String test;
 
    public static void main(String[] args) {
      
     System.out.println(test);
    }
}

Выход:

1
Null

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

1
2
3
4
5
6
7
public class Test2 {
 
    public static void main(String[] args) {
        String test2;
     System.out.println(test2);
    }
}

Выход:

1
Error:(6, 28) java: variable test2 might not have been initialized 

9. Забыть о целочисленном делении

Если вы разделите одно int на другое int, вы снова получите int. Так что ½ = 0, а не 0,5 в этом случае:

1
2
3
4
5
6
public static void main(String[] args) {
 
        int i = 1;
        int j = 2;
  int k = i/j; //here we’ve got 0
  }

Вы можете узнать о делении и реальных типах из Java Синтаксического квеста CodeGym и решить множество задач кодирования, связанных с темой.

10. Беспорядок с порядком вызова конструкторов в дочерних объектах

Когда вы пытаетесь создать экземпляр класса Child, сначала вызывается Child, а затем Parent. Порядок выполнения конструкторов в отношениях Parent-Child строится от базового (Parent) класса к наследуемому (Child).

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
public class Test3 {
    static class Parent {
        Parent() {
            System.out.println("a Parent is created");
        }
    }
    static class Child extends Parent {
        Child(){
            System.out.println("a Child is created");
        }
    }
 
    public static void main(String[] args) {
        Child child = new Child();
    }
}

Выход:

1
2
a Parent is created
a Child is created

Если вы присоединитесь к CodeGym, вы встретите ООП и наследование в Java Core Quest . В этой теме действительно много заданий. Так что рано или поздно вы получите тонкое понимание принципов ООП.

Выводы

Я предполагаю, что нет статьи, которая могла бы накапливать все потенциальные ошибки начинающих студентов Java. Тем не менее, такие списки очень полезны, чтобы избежать популярных ошибок … и успеть найти менее тривиальные вопросы! Praemonitus, praemunitus (* предупрежден, значит вооружен).

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

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

PS: Вы когда-нибудь делали ошибки из этой статьи? С какими ошибками вы столкнулись во время обучения? Расскажите нам в комментариях!