Назад
Вперед
1.3. Как обойтись без указателей
В примере демонстрируется использование
ссылок как альтернативы указателям.
Исходный текст примера
Архив проекта для Java WorkShop 2.0
Немного теории
Известно, что в языке программирования Java нет
указателей. Отсутствие указателей уменьшает
вероятность возникновения ошибок, связанных с их
неправильным использованием. Например, одной из
типичных ошибок является выход за границы
массива или адресного пространства процесса в
процессе изменения значения указателя.
Тем не менее, в Java есть такое понятие, как ссылки
на объекты классов. В каком-то смысле их можно
рассматривать как указатели, над которыми нельзя
выполнять арифметические операции.
Ссылку на объект разрешается передавать через
параметр функции. Функция не в состоянии
изменить полученную ей таким образом ссылку.
Однако пользуясь ссылкой, она может вызвать
метод объекта, изменяющий поля этого объекта.
Заметим, что передать функции ссылку на объект
базового типа невозможно - такие переменные
передаются только по значению. Соответственно,
функция не может изменить содержимое переменной,
значение которой она получила через свой
параметр.
Описание примера
В примере мы демонстрируем типичные ошибки,
связанные с неправильным использованием ссылок,
а также корректный метод передачи ссылки в
функцию через ее параметр.
Внутри метода main мы определили базовую
переменную intVar, объект integerVar замещающего класса
Integer, а также массив из пяти целых чисел iDim:
int intVar;
Integer integerVar;
int[] iDim = new int[5];
Сразу после запуска наша программа присваивает
переменным intVar и integerVar начальные значения:
intVar = 5;
integerVar = new Integer(7);
Кроме того, в самый первый элемент массива iDim мы
записываем число 9:
iDim[0] = 9;
Далее мы создаем объект mp класса MyPoint,
определенного в нашей программе:
MyPoint mp = new MyPoint(1,1);
Этот объект хранит координаты точки (x, y).
Конструктор объекта инициализирует координаты,
записывая в них единицу.
Затем программа выводит на консоль значения
переменных:
System.out.println("Before modification:");
System.out.println("intVar = " + intVar);
System.out.println("integerVar = "
+ integerVar);
System.out.println("iDim = " + iDim[0]);
mp.printPoint();
Для вывода координат точки мы применили метод
printPoint, определенный в классе MyPoint.
На следующем шаге программа выполняет попытку
изменения значений переменных, первого элемента
массива, а также координат точки. С этой целью она
вызывает несколько функций:
ClearIntVar(intVar);
ClearIntegerVar(integerVar);
ClearDim(iDim);
ClearMyPoint(mp);
Результат этой попытки выводится на консоль:
System.out.println("\nAfter modification:");
System.out.println("intVar = " + intVar);
System.out.println("integerVar = "
+ integerVar);
System.out.println("iDim = " + iDim[0]);
mp.printPoint();
Вот что мы там увидим:
Before modification:
intVar = 5
integerVar = 7
iDim = 9
Point: (1,1)
After modification:
intVar = 5
integerVar = 7
iDim = 0
Point: (0,0)
Как видите, значение переменных intVar и integerVar не
изменилось.
В чем здесь дело?
Обратимся к исходным текстам функций,
выполняющим попытку изменения значений
переменных.
Функция ClearIntVar пытается изменить значение
базовой переменной, переданной ей через
параметр:
static void ClearIntVar(int v)
{
v = 0;
}
Однако подобное не предусмотрено в языке
программирования Java. Функция не может изменить
значение ссылки, переданной ей в качестве
параметра.
Ничего не получится и при попытке изменить
ссылку на объект замещающего класса Integer:
static void ClearIntegerVar(Integer v)
{
v = new Integer(0);
}
Функция ClearMyPoint, изменяющая координаты точки
класса MyPoint, работает правильно:
static void ClearMyPoint(MyPoint p)
{
p.setPoint(0,0);
}
Изменения выполняются методом setPoint,
определенным в классе MyPoint. При этом функция
ClearMyPoint не делает никаких попыток изменить ссылку
p на объект, передаваемую ей через параметр.
Функция ClearDim также работает правильно:
static void ClearDim(int[] d)
{
d[0] = 0;
}
Эта функция изменяет самый первый элемент
массива, ссылку на который она получает через
параметр d. Здесь также не предпринимается
никаких попыток изменения самой ссылки d.
В заключение расскажем о том, как устроен класс
MyPoint, определенный в нашей программе.
Внутри этого класса есть два поля с именами m_x и
m_y:
class MyPoint
{
private int m_x=0;
private int m_y=0;
. . .
}
Эти поля хранят координаты точки по оси X и Y,
соответственно.
Помимо перечисленных выше полей в классе MyPoint
мы определили конструктор, а также два метода с
именами setPoint и printPoint.
Конструктор инициализирует поля m_x и m_y
значениями, которые передаются ему через
параметры:
MyPoint(int ix, int iy)
{
m_x = ix;
m_y = iy;
}
Метод setPoint устанавливает новые координаты
точки:
public void setPoint(int ix, int iy)
{
m_x = ix;
m_y = iy;
}
Что же касается метода printPoint, то он выводит
текущие координаты точки на консоль:
public void printPoint()
{
System.out.println("Point: ("
+ m_x + "," + m_y + ")");
}
Назад Вперед |