JavaRush /Java Blog /Random-TL /Mga pagkakamali ng mga baguhan na java programmer. Bahagi...
articles
Antas

Mga pagkakamali ng mga baguhan na java programmer. Bahagi 1

Nai-publish sa grupo

1. Ang pangalan ng klase ay iba sa pangalan ng file kung saan ito nakaimbak

Ang lahat ng java frameworks na ginamit ko, kabilang ang Javasoft JDKs, ay ipinapalagay na ang source code para sa isang klase na may pampublikong modifier ay naka-store sa isang file na may eksaktong kaparehong pangalan ng pangalan ng klase at isang .java extension. Ang pagkabigong sumunod sa convention na ito ay maaaring magdulot ng maraming problema na lalabas sa panahon ng compilation.
Ошибки начинающих java-программистов. Часть 1 - 1
Ang mga nagsisimulang mag-aaral (programmer) ay madalas na nakakalimutan ang tungkol sa convention na ito at, halimbawa, itakda ang pangalan ng file alinsunod sa takdang-aralin: Lab6.java. Maling halimbawa: Pangalan ng fileLab6.java
public class Airplane extends Vehicle
  Seat pilot;
  public Airplane() {
    pilot = new Seat();
  }
}
Nawastong halimbawa: FilenameAirplane.java
public class Airplane extends Vehicle
  Seat pilot;
  public Airplane() {
    pilot = new Seat();
  }
}
Paalala:ang pangalan ng klase ay ipinapalagay na nagsisimula sa malaking titik. Ang mga operating system na case sensitive sa mga pangalan ng file ay maaaring magpakita ng mga karagdagang problema, lalo na para sa mga mag-aaral na nag-aaral ng Java sa Unix na nakasanayan na sa DOS file name system. Ang klase MotorVehicleay dapat na nakaimbak sa isang file MotorVehicle.java, ngunit hindi sa isang motorvehicle.java.

2. Paghahambing gamit==

Sa Java, ang mga string ay mga bagay ng klase java.lang.String. Ang operator ==na inilapat sa mga bagay ay sumusuri para sa pagkakapantay-pantay ng mga sanggunian sa mga bagay! Minsan hindi nauunawaan ng mga mag-aaral ang semantika ng operator ==at subukang gamitin ito upang ihambing ang mga string. Maling halimbawa:
// проверим, equals ли первый аргумент "-a"
if (args[0] == "-a") {
    optionsAll = true;
}
Ang tamang paraan upang ihambing ang 2 string para sa pagkakapantay-pantay ay ang paggamit ng equals()class method java.lang.String. Nagbabalik ito truekung ang mga string ay magkapareho ang haba at naglalaman ng parehong mga character. (Tandaan: sa totoo lang hindi nito ginagarantiyahan ang pagkakapantay-pantay. Sa katunayan, equalssinusuri nito kung ang 2 string ay pantay na karakter ayon sa karakter) Nawastong halimbawa:
//  проверим, equals ли первый аргумент "-a"
if ("-a".equals(args[0])) {
    optionsAll = true;
}
Ang error na ito ay hangal, dahil sa katunayan ang Java code ay lumabas na syntactically tama, ngunit sa huli ay hindi ito gumagana tulad ng inaasahan. Sinusubukan din ng ilang estudyante na gumamit ng mga operator ng paghahambing >at sa halip na <=mga pamamaraan compareTo()ng klase java.lang.String. Mas madaling matukoy ang error na ito dahil nagiging sanhi ito ng mga error sa yugto ng compilation.

3. Nakalimutang simulan ang mga bagay na elemento ng array.

Sa Java, ang hanay ng mga bagay ay talagang hanay ng mga sanggunian sa bagay. Ang paglikha ng isang array ay simpleng paglikha ng isang hanay ng mga sanggunian na hindi tumuturo sa anumang bagay (iyon ay, ang mga ito ay null). Upang aktwal na lumikha ng isang "buong" hanay ng mga bagay, kailangan mong simulan ang bawat elemento ng array. Hindi ito naiintindihan ng maraming estudyante; naniniwala sila na sa pamamagitan ng paglikha ng isang hanay ng mga bagay, awtomatiko silang lumikha ng mga bagay sa kanilang sarili. (Sa karamihan ng mga kaso, dinadala ng mga mag-aaral ang konseptong ito mula sa C++, kung saan ang paglikha ng isang hanay ng mga bagay ay nagreresulta sa paglikha ng mga bagay mismo sa pamamagitan ng pagtawag sa kanilang default na tagapagbuo.) Sa halimbawa sa ibaba, nais ng mag-aaral na lumikha ng 3 bagay ng klase StringBuffer. Ang code ay mag-iipon nang walang mga error, ngunit ang isang pagbubukod ay magaganap sa huling linya NullPointerException, kung saan ang isang hindi umiiral na bagay ay ina-access. Maling halimbawa:
// Создаем массив из StringBuffer
StringBuffer [] myTempBuffers;
myTempBuffers = new StringBuffer[3];
myTempBuffers[0].add(data);
Whatбы не допускать эту ошибку, необходимо не забывать проинициализировать элементы массива. Исправленный пример:
// Создаем массив из StringBuffer и инициализируем элементы
StringBuffer [] myTempBuffers;
myTempBuffers = new StringBuffer[3];
for (int ix = 0; ix < myTempBuffers.length; ix++)
     myTempBuffers[ix] = new StringBuffer();

myTempBuffers[0].add(data);

4. Помещение в один файл сразу нескольких классов с модификатором public

Файлы с исходным java-codeом определенным образом связаны с классами, содержащимися в этих fileх. Связь можно охарактеризовать так: Любой Java-класс хранится не более чем в одном файле. В любой файл с исходным codeом можно поместить не более 1-го класса с модификатором public. Если в файле с исходным codeом есть класс с модификатором public, file name и Name класса должны быть строго одинаковыми (прим. перев.: до регистра, см. п.1) Иногда студенты забывают о 2-ом правиле, что приводит к ошибкам на этапе компиляции. Сообщение об ошибке для 2-го и 3-го правила будет одинаковым (в чем собственно и заключается трудность распознания этой ошибки).

5. Подмена поля класса локальной переменной.

Java позволяет объявлять внутри метода переменные, чье Name совпадает с полями класса. В таком случае преимущество будет отдано локальным переменным, и они будут использоваться instead of полей. Компилятор выдаст ошибку, если переменные с одинаковыми именами будут разных типов. Если же они одинаковых типов, ошибки компиляции не будет, и будут непонятны причины неправильной работы программы. Ошибочный пример:
public class Point3 {
    int i = 0;
    int j = 0;
    int k = 0;

    public boolean hits(Point[] p2list) {
      for(int i = 0; i < p2list.length; i++) {
        Point p2 = p2list[i];
        if (p2.x == i && p2.y == j)
          return true;
      }
      return false;
    }
}
Есть несколько способов, How исправить эту ошибку. Наиболее простой — обращаться к полям класса с помощью неявного указателя this: this.Name_поля. Лучший способ — это переименовать поле класса or локальную переменную, тогда подмены не произойдет. (прим. перев.: 2-ой способ - не наш метод. К тому же он не гарантирует, что я когда нибудь случайно не подменю поле переменной. Еще большая трудность возникнет при наследовании, когда я вообще не вижу, Howие поля есть у класса) Исправленный пример:
// One way to fix the problem
  int i = 0;
  int j = 0;
  int k = 0;

  public boolean hits(Point[] p2list) {
    for(int i = 0; i < p2list.length; i++) {
      Point p2 = p2list[i];
      if (p2.x == this.i && p2.y == this.j)
        return true;
    }
    return false;
  }

  // *****************************
  // Лучший способ
  int x = 0;
  int y = 0;
  int z = 0;

  public boolean hits(Point[] p2list) {
    for(int i = 0; i < p2list.length; i++) {
      Point p2 = p2list[i];
      if (p2.x == x && p2.y == y)
        return true;
    }
    return false;
  }
Еще одно возможное место появления этой ошибки — задание имени параметра метода таким же, How и Name поля класса. Это хорошо выглядит в конструкторах, но для обычных методов не подходит.

прим. перев.

немного сумбурно, но смысл такой

public class Test {
   private int param = 0;

   public Test(int param) {
      this.param = param;
   }
}

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

6. Забыл вызвать конструктор родителя (суперкласса)

Когда класс расширяет другой класс, каждый конструктор подкласса должен вызвать Howой либо конструктор суперкласса. Обычно это достигается вызовом конструктора суперкласса методом super(x), помещенным в первой строке конструктора. Если в первой строке конcтруктора нет вызова super(x), компилятор самостоятельно вставляет этот вызов, но без параметров: super(). (прим. перев.: х...се, а я и не знал ) Иногда студенты забывают об этом требовании. Обычно это не является проблемой: вызов конструктора суперкласса вставляется компилятором и все работает отлично. Однако если у суперкласса нет конструктора по умолчанию (прим. перев.: то есть конструктора без параметров), то компилятор выдаст ошибку. В примере ниже все конструкторы суперкласса java.io.File имеют 1 or 2 параметра: Ошибочный пример:
public class JavaClassFile extends File {
    String classname;
    public JavaClassFile(String cl) {
        classname = cl;
    }
}
Решением проблемы является вставка явного вызова правильного конструктора суперкласса: Исправленный пример:
public class JavaClassFile extends File {
    String classname;
    public JavaClassFile(String cl) {
        super(cl + ".class");
        classname = cl;
    }
}
Более неприятная ситуация возникает, когда у суперкласса есть конструктор по умолчанию, но он не fully инициализирует an object. В таком случае code скомпorруется, но результат работы программы может быть неправильным or может возникнуть исключение.

7. Неправильный перехват исключений

Система обработки исключений в Java достаточно мощная, но трудная для понимания новичками. Студенты, хорошо владеющие C++ or Ada, обычно не испытывают сложностей, в отличие от программистов C и Fortran. Примеры ниже показывают некоторые распространенные ошибки. В данном примере для исключения не указано Name. На эту ошибку укажет компилятор на этапе компиляции, так что ее легко исправить самостоятельно. Ошибочный пример:
try {
    stream1 = new FileInputStream("data.txt");
} catch (IOException) {
    message("Could not open data.txt");
}
Исправленный пример:
try {
   stream1 = new FileInputStream("data.txt");
} catch (IOException ie) {
   message("Could not open data.txt: " + ie);
}
Порядок расположения блоков catch определяет очередность перехвата исключений. Нужно учитывать, что каждый такой блок перехватит все исключения указанного класса or любого его подкласса. Если не учесть это, то можно получить недостижимый блок catch, на что укажет компилятор. В примере ниже SocketException является подклассом IOException. Ошибочный пример:
try {
    serviceSocket.setSoTimeout(1000);
    newsock = serviceSocket.accept();
} catch (IOException ie) {
    message("Error accepting connection.");
} catch (SocketException se) {
    message("Error setting time-out.");
}
Исправленный пример:
try {
    serviceSocket.setSoTimeout(1000);
    newsock = serviceSocket.accept();
} catch (SocketException se) {
    message("Error setting time-out.");
} catch (IOException ie) {
    message("Error accepting connection.");
}
Если в codeе возможно появление исключения, которое не перехватавается ни одним блоком try-catch, то это исключение следует объявить в заголовке метода. (Для исключений — подклассов класса RuntimeException это не обязательно). Студенты иногда забывают о том, что вызов метода может порождать исключение. Проще всего это исправить, помещая вызов метода в блок try-catch. Ошибочный пример:
public void waitFor(int sec) {
    Thread.sleep(sec * 1000);
}
Исправленный пример:
public void waitFor(int sec) throws InterruptedException {
    Thread.sleep(sec * 1000);
}

8. Метод доступа имеет тип void

Это очень простая ошибка. Студент создает метод для доступа к переменной, но указывает, что метод ничего не возвращает (помещает модификатор void в загогловок метода). Whatбы исправить эту ошибку, нужно указать правильный тип возвращаемого значения. Ошибочный пример:
public class Line {
    private Point start, end;
    public void getStart() {
      return start;
    }
}
Исправленный пример:
public class Line {
    private Point start, end;
    public Point getStart() {
      return start;
    }
}
Указание неправильного возвращаемого типа порождает целый класс ошибок. Обычно компилятор распознает эти ошибки и сообщает о них, так что студенты могут самостоятельно их исправить. Author: А.Грасоff™ Читать продолжение Ссылка на первоисточник: Ошибки начинающих java-программистов
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION