Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых
[Назад]

Библиотека примеров приложений Java

Оглавление
Базовые типы

Замещающие типы
Без указателей
Массивы
Структурное программи-
рование

Обработка исключений
Возбуждение исключений
Классы обработки исключений
Блок finally
Строки String
Класс Math
Класс Vector
Класс Stack
Словарь на базе Hashtable
Словарь на базе Properties
Цифровые часы
Собственный класс
Наследование классов

Интерфейсы

Назад Вперед

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 + ")");
}

Назад Вперед

[Назад]