Авторские Материалы о событиях в Израиле на Ближнем Востоке и в мире

IsraMir.com - Израильская журналистика

Default color brown color green color red color blue color
Вы сейчас тут: Новости arrow Техотдел arrow Свет ученья arrow Работа над ошибками-3
Skip to content
Работа над ошибками-3 Версия для печати Отправить на e-mail
Sunday, 19 March 2006 | А.Грасоffб сайт SQL.Ru для раздела Ученье – свет
Работанадошибками-3isramir.comМы продолжаем публикацию чрезвычайно, на мой взгляд, полезного материала, описывающего некоторое количество достаточно распространенных ошибок у начинающих программистов при работе в Java.
Сегодня – еще три раздела; по правде говоря, с некоторыми сталкивался и я сам...
 
9. Вызов нестатичных методов класса из метода main()

Входной точкой любой Java программы должен быть статичный метод main:
public static void main(String[] args) {
  ...
}

Так как этот метод статичный, нельзя из него вызывать нестатичные
методы класса. Об этом часто забывают студенты и пытаются вызывать
методы, не создавая экземпляр класса. Эту ошибку обычно допускают в
самом начале обучения, когда студенты пишут маленькие программы.

Ошибочный пример:
public class DivTest {
    boolean divisible(int x, int y) {
        return (x % y == 0);
    }
 
    public static void main(String[] args) {
        int v1 = 14;
        int v2 = 9;
 
        // на следующие строки компилятор выдаст ошибку
        if (divisible(v1, v2)) {
            System.out.println(v1 + " is a multiple of " + v2);
        } else {
            System.out.println(v2 + " does not divide " + v1);
        }
    }
}

Есть 2 способа исправления ошибки: сделать нужный метод статичным
или создать экземпляр класса. Чтобы правильно выбрать нужный способ,
задайте себе вопрос: использует ли метод поля или другие методы класса.
Если да, то следует создать экземпляр класса и вызвать у него метод,
иначе следует сделать метод статичным.

Исправленный пример 1:
public class DivTest {
    int modulus;
 
    public DivTest(int m) {
      modulus = m;
    }
   
    boolean divisible(int x) {
        return (x % modulus == 0);
    }
 
    public static void main(String[] args) {
        int v1 = 14;
        int v2 = 9;
 
        DivTest tester = new DivTest(v2);
 
        if (tester.divisible(v1) {
            System.out.println(v1 + " is a multiple of " + v2);
        } else {
            System.out.println(v2 + " does not divide " + v1);
        }
    }
}

Исправленный пример 2:
public class DivTest {
    static boolean divisible(int x, int y) {
        return (x % y == 0);
    }
 
    public static void main(String[] args) {
        int v1 = 14;
        int v2 = 9;
 
        if (divisible(v1, v2)) {
            System.out.println(v1 + " is a multiple of " + v2);
        } else {
            System.out.println(v2 + " does not divide " + v1);
        }
    }
}


10. Использование объектов класса String как параметров метода.
В Java класс java.lang.String хранит строковые данные. Однако, строки в Java
(1) обладают постоянством (то есть их нельзя изменять),
(2) являются объектами.

Поэтому с ними нельзя обращаться как просто с буфером символов, это
неизменяемые объекты. Иногда студенты передают строки, ошибочно
расчитывая на то, что строка-объект будет передана как массив символов
по ссылке (как в C или C++). Компилятор обычно не считает это ошибкой.

Ошибочный пример.
public static void main(String args[]) {
   String test1 = "Today is ";
   appendTodaysDate(test1);
   System.out.println(test1);
}
 
/* прим. редактора: закомментированный метод должен иметь модификатор
    static (здесь автором допущена ошибка №9)
public void appendTodaysDate(String line) {
    line = line + (new Date()).toString();
}
*/
 
public static void appendTodaysDate(String line) {
    line = line + (new Date()).toString();
}

В примере выше студент хочет изменить значение локальной переменной test1,
присваивая новое значение параметру line в методе appendTodaysDate.
Естественно это не сработает. Значение line изменится, но значение test1
останется прежним.

Эта ошибка возникает из-за непонимания того, что (1) java объекты всегда
передаются по ссылке и (2) строки в Java неизменяемы. Нужно осмыслить, что
объекты-строки никогда не изменяют своего значения, а все операции над
строками создают новый объект.

Чтобы исправить ошибку в примере выше, нужно или возвращать строку из
метода, или передавать объект StringBuffer как параметр методу вместо String.

Исправленный пример 1:
public static void main(String args[]) {
   String test1 = "Today is ";
   test1 = appendTodaysDate(test1);
   System.out.println(test1);
}
 
public static String appendTodaysDate(String line) {
    return (line + (new Date()).toString());
}

Исправленный пример 2:
public static void main(String args[]) {
   StringBuffer test1 = new StringBuffer("Today is ");
   appendTodaysDate(test1);
   System.out.println(test1.toString());
}
 
public static void appendTodaysDate(StringBuffer line) {
    line.append((new Date()).toString());
}
 
Примечание.
Вообще-то понять в чем ошибка не так просто, так как объекты передаются по ссылке, то значит line ссылается туда же, куда и test1. А значит создавая новый line, мы создаем новый test1. В неправильном примере все выглядит так, как будто передача String идет по значению, а не по ссылке.


11. Объявление конструктора как метода
Конструкторы объектов в Java внешне похожы на обычные методы. Единственные
отличия - у конструктора не указывается тип возвращаемого значения и
название совпадает с именем класса. К несчастью, Java допускает задание
имени метода, совпадающего с названием класса.

В примере ниже, студент хочет проинициализировать поле класса Vector list
при создании класса. Этого не произойдет, так как метод 'IntList' - это не
конструктор.

Ошибочный пример.
public class IntList {
    Vector list;
 
    // Выглядит как конструктор, но на самом деле это метод
    public void IntList() {
        list = new Vector();
    }
 
    public append(int n) {
        list.addElement(new Integer(n));
    }
}

Код выдаст исключение NullPointerException при первом же ображении к полю
list. Ошибку легко исправить: нужно просто убрать возвращаемое значение
из заголовка метода.

Исправленный пример:
public class IntList {
    Vector list;
 
    // Это конструктор
    public IntList() {
        list = new Vector();
    }
 
    public append(int n) {
        list.addElement(new Integer(n));
    }
}
 
Продолжение следует
 
 

Добавить комментарий

:D:lol::-);-)8):-|:-*:oops::sad::cry::o:-?:-x:eek::zzz:P:roll::sigh:


Автотранслитерация: выключена

Защитный код

Powered by jComments