Соблюдение требований к безопасности данных и кода, инкапсулированных в классе
В проекте 10_10 использован рекомендуемый в Java способ создания классов, по шаблону которых будут создаваться объекты: переменные экземпляра закрыты (private), доступ к ним из других классов осуществляется через тщательно спроектированный public-интерфейс (методы геттеры и сеттеры)
Сокрытие переменной экземпляра. Ключевое слово this.
Проблема: если локальная переменная метода (а формальные параметры являются локальными переменными) имеет такое же имя, как переменная экземпляра, локальная переменная скрывает переменную экземпляра. Т.е. при употреблении данного имени обращение будет происходить только к локальной переменной.
Чтобы решить эту проблему, в конструкторах класса Box и других методах можно использовать имена формальных параметров, отличающиеся от имен полей класса например,
public class Box{
//поля
private double d, w, h;
//методы-конструкторы
…
public Box(double d1, double w1, double h1 ){
d=d1; w=w1; h=h1;}
…
// методы-сеттеры
public void setD(double d1){d=d1;}
…
Проблему можно решить и другим способом (и в проекте 10_10 мы использовали именно его):
использовать одинаковые имена для формальных параметров метода (любого, не обязательно конструктора) и переменных экземпляра, а для идентификации переменных экземпяляра в методе использовать ключевое слово this.
this – это ссылка на текущий объект, т.е. объект, который вызвал метод.
Слово this можно использовать везде, где разрешается ссылка на объект текущего класса.
public class Box{
//поля
private double d, w, h;
//методы-конструкторы
…
public Box(double d, double w, double h){
this.d=d; this.w=w; this.h=h;}
…
// методы-сеттеры
public void setD(double d){this.d=d;}
…
this.d – переменная экземпляра,
d – локальная переменная метода
Какой из способов выбрать – дело вкуса программиста.
Передача объектов в методы
Параметром метода может быть объект. Это демонстрирует конструктор
public Box (Box ob) //построить клон объекта ob (параметр – объект!)
Вызов: Box box2=new Box(box1); //создан клон (копия) box1
и метод
public boolean eguals (Box box) //сравнение (параметр – объект!)
Вызов:System.out.println("box1==box2: "+box1.eguals(box2));
Назначение ссылочных переменных объекта
Копирование ссылки отличается от копирования объекта!
Проанализируйте вывод проекта 9_3. В классе Box удален метод toString()), поэтому вместо строки описания объекта выводится его адрес. По адресам можно определить какие ссылочные переменные указывают на различные объекты, какие – на один и тот же объект, какие не указывают ни на какой объект (null).
Разрушение объектов
Как уже говорилось, разрушение объектов, созданных процедурой new, на которые уже нет ссылок в программе (сборка мусора) в Java происходит периодически и автоматически (программисту не нужно ничего предпринимать для этого).
Иногда объекту нужно выполнить некоторые действия перед разрушением. Например, если объект содержит некоторый не-Java ресурс, такой как дескриптор файла или оконный шрифт, то до разрушения объекта эти ресурсы должны быть освобождены.
Для обработки таких ситуаций Java использует механизм, называемый завершением (finalization).
В классе определяется метод finalize(), определяющий действия, которые будут выполняться перед разрушением объекта (когда объект «попадет в руки» сборщика мусора).
Метод finalize() имеет следующую общую форму:
protected void finalize() {
// код завершения
}
Спецификатор доступа protected запрещает доступ к методу finalize() кодам, определенным вне этого класса или его прямых потомков.
Массивы, как объекты
Все переменные структурированных типов (в том числе массивы и строки) реализуются в Java как объекты.
Объект-массив (одномерный) после его создания содержит следующие поля:
- length – длина массива – количество элементов;
- элементы массива базового типа с номерами от 0 до length-1.
В примере создан объект-массив, в поля которого записаны значения, заданные инициализационным выражением, создана переменная A – ссылка на массив (объект). Значению ссылки A присвоен адрес объекта:
int [ ] A={20,-3,1,50,11};
Создан еще один псевдоним объекта:
int [ ] B=A; //ссылке на массив B
// присваивается значение ссылки
// на массив A
Массивы, как и другие объекты, можно создавать при помощи функции new, которая возвращает адрес созданного объекта. При создании массивов используются конструкторы, определенные в Java.
int[ ] A = new int [5]; //элементы массива инициализируются значениями
// по умолчанию, т.е. нулями.
Многомерные массивы в Java – это массивы массивов.
Двумерный массив, как и одномерный, можно инициализировать:
Объявлен и создан двумерный массив, в котором две строки и три столбца. Элементы получили начальные значения согласно списку констант.
int A [ ] [ ] = {
{1, 3, 2,},
{6, 4, 5,}
};
Ссылочная переменная A содержит адрес объекта-массива ссылочных переменных, каждая из которых содержит адрес объекта-одномерного массива соответствующей строки прямоугольного двумерного массива (матрицы).
Другой способ создания двумерного массива при помощи – процедуры new:
int [ ] [ ] A = new int[2] [3];
Это действие состоит из двух действий:
1) int [][] A; − объявляется ссылка A (ссылочная переменная) на двумерный массив, ей присваивается значение null;
2) A=new int [2][3] − процедура new возвращает адрес найденного свободного блока памяти нужного размера ((3+4+4)*4=44 байта), этот адрес записывается в ссылочную переменную A. Начальные значения элементов задаются по умолчанию (нулями).
Для перебора элементов одномерного массива (вектора) мы использовали цикл for. Для перебора элементов двумерного массива (матрицы) требуется конструкция, состоящая из двух циклов for (основного и вложенного). В основном цикле будет изменяться номер строки (первый индекс элемента матрицы), а во вложенном – номер столбца (второй индекс элемента матрицы), или наоборот.
Фрагмент программы создает объект-матрицу и инициализирует значения элементов.
int [ ] [ ] B = new int[5] [4];
for (i=0; i<B.length;i++)
for (j=0; j<B[0].length; j++) B[ i ][ j ]=i+j;