"Здравей, Амиго! Нека продължим да говорим за грешките. Този път ще изследваме грешки, за които компилаторът не винаги ще ти помогне. Обърни внимание и ще научиш нещо за себе си."

„Готов съм да те изслушам, Диего. Надявам се, че това няма да е много неудобно за мен.“

Сравняване на обекти с==

„Нашият списък с най-любими грешки на начинаещи програмисти започва със сравняване на обекти (особено низове) с помощта на ==оператора“

Пример:

Scanner console = new Scanner(System.in);
String s1 = console.nextLine();
String s2 = console.nextLine();
if (s1 == s2)
{
   System.out.println("The strings are equal");
}

„Правих това доста често. Сега мога ясно да видя, че този code никога няма да покаже „Низовете са равни“, защото изразът ifсравнява препратки към два различни обекта на низ.“

„Да. Ето защо правилният вариант би бил:

Scanner console = new Scanner(System.in);
String s1 = console.nextLine();
String s2 = console.nextLine();
if (s1.equals(s2))
{
   System.out.println("The strings are equal");
}

Смяна на Stringобект

"Начинаещите програмисти често забравят, че всички обекти на класа са неизменни и че всеки метод на Stringкласа връща нов обект - текущият обект никога не се променя."

„Не беше толкова отдавна, когато научих Howво означава неизменно , но мисля, че съм направил това.

„Доста съм сигурен в това. Пример:

String s = "Hello";
s.toUpperCase (); // Convert to uppercase

„Този ​​code е много подобен на правилния code, но няма да работи според очакванията. Методът не toUpperCase()променя обекта, на който е извикан. Правилният code ще изглежда така:

String s = "Hello";
String result = s.toUpperCase(); // Convert to uppercase

„Точно така. Направих го, но дори не разбрах Howво не е наред. Благодаря ви за пояснението!“

Забравяне на инициализиране на обекти, които са елементи на масив

„Друга често срещана грешка е да забравите да инициализирате променлива на масив. Пример:

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

„Този ​​code няма да работи: трябва изрично да зададете променливата на масива, равна на препратка към контейнерния обект, който ще съхранява елементите на масива. Правилна version:

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

Използване на локална променлива instead of променлива на екземпляр.

„Новаците не обичат да измислят дълги и смислени имена за променливи.“

„Това е толкова вярно. За да върша нещата бързо, понякога давам имена на променливи като a, bи i.“

„Не правете това. Това е жестоко нещо, когато codeът има няколко такива променливи:

Поставете числото 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;
    }
  }
}

„Много по-трудно е да се правят грешки в codeа с подходящи имена. Правилната version изглежда така:

Поставете числото 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 < 10; i++)
      {
         a[i] = value;
      }
   }
}

Премахване на артикул от колекция

„Разгледахте ли вече колекциите?“

— Буквално само с едно око.

"Ако не знаете за Howво говоря, тогава си направете бележка, за да погледнете в бъдеще. Много често има ситуации, когато определен елемент трябва да бъде премахнат от колекция. Кодът изглежда приблизително така това:

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);

„Този ​​code няма да работи, защото не можете да използвате цикъл, 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 колекциите имат removeIf()метод, към който можете да подадете правило (ламбда функция), което показва кои елементи да бъдат премахнати. Пример:

Решение 2
ArrayList<Integer> list = new ArrayList<Integer>();
Collections.addAll(list, 0, -5, -7, -12, 5, 15);

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

Поставяне на няколко класа с publicмодификатора в един файл

"Може да има само един публичен клас във файл. Повече класове могат да бъдат декларирани във файл, но те трябва or да са вътрешни класове на публичен клас, or да нямат модификатора. Пример public:

Съдържание на file Solution.java Забележка
public class Solution
{
}
public class Main
{
}
Това не е позволено: два публични класа в един файл.
public class Solution
{
}
class Main
{
}
Но можете да направите това. Основният клас не е публичен
public class Solution
{
  public static class Main
  {
  }
}
И вие можете да направите това. Основният клас е вложен клас

Извикване на обикновени (нестатични) методи на клас от статичния main()метод

„Понякога начинаещи програмисти се опитват да получат достъп до нестатични променливи и методи от main()метода or други статични методи. Такъв code няма да работи, разбира се.

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

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

mainМетодът може да препраща само към статични методи/променливи. Е, or първо трябва да създаде екземпляр на 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();
  }
}

Деклариране на конструктор като метод

„Друга често срещана грешка е неправилното деклариране на конструктор на клас. Името на конструктора трябва да е същото като името на класа, а конструкторът няма тип резултат. Най-често срещаните грешки изглеждат така:

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;
   }
}
Всичко това е правилно.

Неправилно наследяване на интерфейси

„Създателите на Java се опитаха да я направят много близка до английския, така че избраха различни ключови думи за определени свързани понятия.

Когато клас наследява клас, трябва да използвате extendsключовата дума:

class Pet
{
}

class Cat extends Pet
{
}

„Когато клас наследява интерфейс or по-точно го имплементира, трябва да използвате ключовата implementsдума:

interface Meow
{
}

class Cat implements Meow
{
}

„Когато интерфейс наследява интерфейс, използвайте extendsключовата дума:

interface Meow
{
}

interface Voice extends Meov
{
}

Пропускане breakв switchизявление

„И последната грешка за днес, но не и последната за начинаещи, е пропускът да се включи изявление breakв switchизявление. Пример:

погрешно вярно
LocalDate date = LocalDate.now();
DayOfWeek day = date.getDayOfWeek();
switch (day)
{
   case MONDAY:
      System.out.println("Monday");
   case TUESDAY:
      System.out.println("Tuesday");
   case WEDNESDAY:
      System.out.println("Wednesday");
   case THURSDAY:
      System.out.println("Thursday");
   case FRIDAY:
      System.out.println("Friday");
   case SATURDAY:
      System.out.println("Saturday");
   case SUNDAY:
      System.out.println("Sunday");
}
LocalDate date = LocalDate.now();
DayOfWeek day = date.getDayOfWeek();
switch (day)
{
   case MONDAY:
      System.out.println("Monday");
      break;
   case TUESDAY:
      System.out.println("Tuesday");
      break;
   case WEDNESDAY:
      System.out.println("Wednesday");
      break;
   case THURSDAY:
      System.out.println("Thursday");
      break;
   case FRIDAY:
      System.out.println("Friday");
      break;
   case SATURDAY:
      System.out.println("Saturday");
      break;
   case SUNDAY:
      System.out.println("Sunday");
      break;
}

„Знаеш ли, Диего... Съдейки по набора от грешки, които представи тук, имам чувството, че си чел личния ми дневник... Или си ме гледал How решавам задачи.“

„Ха! Не се съмнявайте в това. Прочетох, проследих и продължавам да го правя. Така че бъдете нащрек!“

"???"

"Не се притеснявай. Просто се шегувам. Бъди бдителен и прави по-малко глупави грешки."