JavaRush /Курси /Java Syntax Zero /Поширені помилки програмістів-початківців

Поширені помилки програмістів-початківців

Java Syntax Zero
Рівень 12 , Лекція 6
Відкрита

1. Порівняння об'єктів за допомогою оператора ==

Улюблена помилка програмістів-новачків — порівняння об'єктів (зокрема рядків) за допомогою оператора ==. Приклад:

Scanner console = new Scanner(System.in);
String s1 = console.nextLine();
String s2 = console.nextLine();
if (s1 == s2)
{
   System.out.println("Рядки однакові");
}

Такий код ніколи не виведе напис «Рядки однакові», тому що в операторі if відбувається порівняння посилань на два різні рядкові об'єкти.

Правильний варіант коду такий:

Scanner console = new Scanner(System.in);
String s1 = console.nextLine();
String s2 = console.nextLine();
if (s1.equals(s2))
{
   System.out.println("Рядки однакові");
}


2. Змінення об'єкта String

Часто програмісти-новачки забувають, що всі об'єкти класу є незмінними (immutable) й усі методи класу String повертають новий об'єкт, а поточний об'єкт ніколи не змінюється.

Приклад:

String s = "Привіт";
s.toUpperCase(); // перетворення рядка у верхній регістр

Такий код дуже схожий на правильний, але він не працюватиме. Метод toUpperCase() не змінює об'єкт, для якого його викликано. Правильний код матиме такий вигляд:

String s = "Привіт";
String result = s.toUpperCase(); // перетворення рядка у верхній регістр


3. Не ініціалізовано об'єкти, які є елементами масиву

Ще одна поширена помилка програмістів-початківців — вони забувають ініціалізувати змінну-масив. Приклад:

int[] array;
array[0] = 1;
array[0] = 2;

Такий код не працюватиме: змінній array потрібно явно присвоїти посилання на об'єкт-контейнер, який буде зберігати елементи масиву.

int[] array = new int[10];
array[0] = 1;
array[0] = 2;


4. Підміна поля класу локальною змінною

Новачки не люблять придумувати довгі й осмислені імена для змінних. Вони часто дають змінним імена a, b, i тощо. Це може обернутися суттєвими помилками в коді, коли таких змінних декілька:

Записати число 99 у 100 комірок масиву
class Solution
{
  public static int a = 99;
  public static int i = 100;

  public static void main(String[] args)
  {
    int[] a = new int[i];
    for (int i = 0; i < 10; i++)
    {
      a[i] = a;
    }
  }
}

Наведений вище код не скомпілюється. Виправлений код матиме такий вигляд:

Записати число 99 у 100 комірок масиву
class Solution
{
   public static int value = 99;
   public static int count = 100;

   public static void main(String[] args)
   {
      int[] a = new int[count];
      for (int i = 0; i < count; i++)
      {
         a[i] = value;
      }
   }
}


5. Видалення елемента колекції

Досить часто трапляються ситуації, коли потрібно видалити з колекції певний елемент. Цей код може мати такий вигляд:

ArrayList<Integer> list = new ArrayList<Integer>();
Collections.addAll(list, 0, -5, -7, -12, 5, 15);

for (Integer value: list)
   if (value < 0)
      list.remove(value);

Такий код не працюватиме, тому що не можна проходити колекцію по елементах за допомогою циклу for-each і водночас змінювати цю саму колекцію.

Є кілька варіантів розв'язання проблеми. По-перше, можна проходити одну колекцію, а змінювати іншу:

Варіант 1
ArrayList<Integer> list = new ArrayList<Integer>();
Collections.addAll(list, 0, -5, -7, -12, 5, 15);

ArrayList<Integer> copy = new ArrayList<Integer>(list);
for (Integer value: copy)
   if (value < 0)
      list.remove(value);

По-друге, починаючи з Java 8 у колекцій з'явився метод remove If(), в який можна передати правило (лямбда-функцію), що вказує, які елементи потрібно видалити.

Приклад:

Варіант 2
ArrayList<Integer> list = new ArrayList<Integer>();
Collections.addAll(list, 0, -5, -7, -12, 5, 15);

list.removeIf( x-> x<0 );


6. Розміщення в одному файлі декількох класів із модифікатором public

Кожен файл може містити тільки один публічний клас. Файл може містити оголошення й інших класів, але вони мають бути або внутрішніми класами публічного класу, або ж не повинні мати модифікатора public. Приклад:

Вміст файлу Solution.java Примітка
public class Solution
{
}
public class Main
{
}
Так не можна: два публічні класи в одному файлі.
public class Solution
{
}
class Main
{
}
А так можна. Клас Main — непублічний
public class Solution
{
  public static class Main
  {
  }
}
Так теж можна. Клас Main — вкладений клас


7. Виклик звичайних методів класу зі статичного методу main()

Часом програмісти-новачки звертаються до нестатичних змінних і методів із методу main() або інших статичних методів. Такий код, звісно, не працюватиме:

public class Solution
{
   public int n = 100;
   public int[] createArray()
   {
      return new int[n];
   }

   public static void main(String[]args)
   {
      int[] array = createArray();
   }
}

Метод main може звертатися тільки до статичного методу чи змінної. Можна також спочатку створити об'єкт класу Solution, а вже потім викликати нестатичні методи для цього об'єкта. Приклад:

Варіант 1 Варіант 2
public class Solution
{
  public static int n = 100;

  public static int[] createArray()
  {
    return new int[n];
  }

  public static void main(String[]args)
  {
    int[] array = createArray();
  }
}
public class Solution
{
  public int n = 100;

  public int[] createArray()
  {
    return new int[n];
  }

  public static void main(String[]args)
  {
    Solution sol = new Solution();
    int[] array = sol.createArray();
  }
}


8. Оголошення конструктора як методу

Ще одна поширена помилка — неправильне оголошення конструктора класу. Ім'я конструктора має збігатися з іменем класу, а типу результату конструктор не має. Приклади найчастіших помилок:

public class Person
{
   private String value;

   void Person(String value)
   {
      this.value = value;
   }
}




Тип результату тут не потрібен
public class Person
{
   private String value;

   constructor(String value)
   {
      this.value = value;
   }
}




Неправильне ім'я конструктора. Ім'я конструктора має збігатися з іменем класу
public class Person
{
   private String value;

   Person(String value)
   {
      value = value;
   }
}






Пропущено this — змінну value буде присвоєно самій собі
public class Person
{
   private String value;

   Person(String value)
   {
      this.value = value;
   }
}




Усе правильно


9. Неправильне успадкування інтерфейсів

Розробники Java намагалися зробити її якомога ближчою до англійської мови, тому для деяких споріднених понять вони вибрали різні ключові слова.

Коли клас успадковується від класу, потрібно використовувати ключове слово extends:

class Pet
{
}

class Cat extends Pet
{
}

Коли клас успадковується від інтерфейсу, потрібно використовувати ключове слово implements:

interface Meow
{
}

class Cat implements Meow
{
}

Коли інтерфейс успадковується від інтерфейсу, потрібно використовувати ключове слово extends:

interface Meow
{
}

interface Voice extends Meow
{
}


10. Пропуск слова break в операторі switch

І остання помилка в нашому переліку, але не остання для новачків — це пропуск оператора break в операторі множинного вибору switch. Приклад

Неправильно Правильно
LocalDate date = LocalDate.now();
DayOfWeek day = date.getDayOfWeek();
switch (day)
{
   case MONDAY:
      System.out.println("Понеділок");
   case TUESDAY:
      System.out.println("Вівторок");
   case WEDNESDAY:
      System.out.println("Середа");
   case THURSDAY:
      System.out.println("Четвер");
   case FRIDAY:
      System.out.println("П'ятниця");
   case SATURDAY:
      System.out.println("Субота");
   case SUNDAY:
      System.out.println("Неділя");
}
LocalDate date = LocalDate.now();
DayOfWeek day = date.getDayOfWeek();
switch (day)
{
   case MONDAY:
      System.out.println("Понеділок");
      break;
   case TUESDAY:
      System.out.println("Вівторок");
      break;
   case WEDNESDAY:
      System.out.println("Середа");
      break;
   case THURSDAY:
      System.out.println("Четвер");
      break;
   case FRIDAY:
      System.out.println("П'ятниця");
      break;
   case SATURDAY:
      System.out.println("Субота");
      break;
   case SUNDAY:
      System.out.println("Неділя");
      break;
}

Коментарі (22)
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ
Гаркін Рівень 14
11 травня 2024
ArrayList в Java https://javarush.com/groups/posts/2354-arraylist-v-java . (классное примечание в конце - Методы ArrayList в Java изучаются на курсе JavaRush. Первое знакомство происходит на седьмом уровне квеста Java Syntax, на лекции “Класс ArrayList” ). Насолоджуйтесь. Коллекции в Java | Java Collections https://javarush.com/groups/posts/1937-klass-collections
oleh ronin Рівень 47
24 жовтня 2023
Агов народ,те що в лекціях трапляється матеріал який ще не вчили, таким чином JavaRush привчає вас гуглити інформацію яка вам портібна. Так уже сталось що повністю вивчити мову Java неможливо. Правильно поставлене питання по проблемі в гугл - це вже 70% вирішення проблеми. Так що не "плюйтесь" тут що ми такого не вчили, і "JavaRush зкатились", тут нам на благо))
29 лютого 2024
Категорически не согласен. Я тут только потому, что меня за вменяемые деньги "ведут" от простого к сложному. Иначе читай книги, смотри лекции и ПАРЬСЯ. Я через это прошел на других курсах. Поэтому готов смотреть дополнительно только по пройденной теме, как у меня это было со "switch". Никак не срабатывал return в операторе. Ответ нашел на стороннем ресурсе, т.к. подробнейшая статья тут не помогла.
hidden #3421731 Рівень 28
7 квітня 2024
Вам не подобається що тут вам розжовують але іноді вам приходиться жувати самостійно. Я правильно ваш комент зрозумів?
9 квітня 2024
Не все тут розжовують, як Ви написали. І так, я хочу, щоби незабезкоштовно розжовували. І цей курс саме так себе позиціонує. Тому я тут і займаюсь.
hidden #3421731 Рівень 28
9 квітня 2024
ага зрозумів
PAMPERS Рівень 26
26 липня 2023
лутаєм матерію хлопци
Kostiantyn Bogatyrchuk Рівень 14 Expert
25 лютого 2023
"Видалення елемента колекції" - ще не проходили цей матеріал. П.с. після 10 рівня десь російськомовні коментатори пропали ? 😲 П.П.С. прикол. переглянув перші уроки, а там ВЖЕ немає російськомовних коментарів, хоча раніше було повним повно. це мене на україномовну верісю сайту перевели? чи що трапилося? Навряд ДжаваРаш відмовилися би від російкомовної клієнтури. Бляха-муха!!! 100%!!! Коли я проходив Додаткові лекції до рівня 10 , там було +200 лайків, і дохріна коментрів! зараз глянув - 12лайків, 2коментарі. Мало того. я сам там комент писав, і його там немає. Схоже що я зараз перебуваю на версії сайту, для україномовної публіки. от так от поворот))))))) і шо ви друзі думаєте?? я таки правий)))))))) зміна мови інтерфейсу нічого не вирішує, а інкогніто владка, або VPN показують зовсім інші коментарі. Доречі моїх коментарів, які я майже на кожному уроці писав Українською, більше на російськомовній стороні не існує. Напевно щоб солов'їна "очи чёрные" не мозолила. Чесно, якби коменти, не пропали би, у мене підозра і не виникла би, в Україні достатньо російськомовних. Тепер я зрозумів де собака закопана. Якось стало дискомфортно у середині, як наче у лице плюнули. Гразд, ще заробляти на росіянах, але видаляти коментарі написані українською... Це типу щоб ми їм своєю мовою на психіку їм не діяли
Anonymous #2979179 Рівень 13
19 вересня 2023
Напевно щоб не було конфліктів та щоб вони себе відчували як в дома 😂 . Ну то таке росіяни купують курс кошти йдуть трохи на зсу .
hidden #3421731 Рівень 28
7 квітня 2024
хіба джава раш це не російський проект ?.якщо так то скоріше навпаки кошти йдуть
Anonymous #2979179 Рівень 13
12 квітня 2024
Сказано що ні
Roma Chernesh Рівень 16
19 січня 2023
Порівняння рядків за допомогою оператора == Хто згоден, що куди логічніше було б зробити "==" порівнянням двох рядків? Маю на увазі, якщо колись комусь знадобиться порівняти два посилання, для нього/неї була би string.equals(string2). А так виходить, що всім ці порівняння посилань не потрібні, але для них віділенно зручний оператор "==", а для функції, яка всім потрібна майже завжди - якась неінтуітивна формула. *Розумію, що ніхто цього змінювати в Java не буде, але просто цікаво, чи я один так гадаю, чи ішні люди теж так думають.
SoniaSapsan Рівень 17
19 січня 2023
здається тільки ти один, бо так вже склалося, що об'єкти працюють із методами, а не із операторами. З операторами переважно працюють примітивні типи даних.
Roma Chernesh Рівень 16
19 січня 2023
туше ;) а було б зручно...
les_yeux_blancs Рівень 50
24 квітня 2023
працюють з операторами й обʼєкти, просто що порівняння порівнює значення, що лежать за адресою, що зберігається у змінній, а змінні, що зберігають обʼєкти, як відомо, зберігають адресу першого блоку памʼяті, що зберігає сам обʼєкт доречі, в C#, якщо я не помиляюся, можна перевантажувати оператори (==, <, > тощо), що дає змогу зробити як раз те, про що ти написав (можна побачити приклади тут: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/operator-overloading). Як бонус у них ще й дженеріки справжні, але ось проблеми з портативністю (точно до .NET Core)
Roma Chernesh Рівень 16
10 травня 2023
Спасибі за роз'яснення!
1 січня 2023
Я щось не памятаю щоб проходили лекцію з колекціями
Бородатий Рівень 17
15 грудня 2022
Гарно побалували нас легшими завданнями ))
Pan Vitali Moroz Рівень 51
22 вересня 2022
побачимось на іншому боці лабіринту
dianosauric Рівень 42
22 вересня 2022
Сподіваюсь, що в майбутньому будуть подібні лекції з помилками та задачами з минулого. Вони дають змогу закріпити пройдений матеріал :3
FAUST_ua Рівень 29
6 серпня 2022
Помилка з майбутнього. Оператор switch вивчається на 14 рівні.
Illia Pakhuta Рівень 51
6 жовтня 2023
Я думав я вже головой поїхав...