Заполнение лакун в рассказе
Инициализация
Инициализация объекта
Инициализатор – специальный блок кода, заключенный в фигурные скобки. Чтобы понять, где он может размещаться, в какой момент исполняется и как он вписывается в процесс инициализации объекта, рассмотрим пример.
class A { int x = 1; // 1.1 { // 1.2 … } int y = 2; // 1.3 { // 1.4 … } … A (…) { // 1.5 … } … }
и
class B extends A { double z = 1.0; // 2.1 { … } int Y = 2; // 2.2 { // 2.3 … } … B (…) { // 2.4 … } … }
Рассмотрим, что происходит при исполнении В начале происходит инициализация полей и выполнение
инициализаторов расширяемого класса A (1.1–1.4) в
порядке следования их в файле с исходным кодом. Далее выполняется конструктор класса А с соответствующей
сигнатурой (1.5). Затем сверху вниз выполняются инициализаторы и
инициализируются поля класса B (2.1–2.3). И, наконец, выполняется конструктор с соответствующей
сигнатурой класса B (2.4). Естественным образом эта логика распространяется и на случаи
наличия более одного предка у класса. Поля и инициализаторы, отмеченные ключевым словом static, в момент инициализации объекта игнорируются. Рассмотрим Ключевое слово final требует
обязательного и единственного изменения соответствующего поля в процессе
инициализации. То есть к концу выполнения любого конструктора поле final должно быть проинициализировано и только один раз.
Возможность иного сценария выполнения вызовет ошибку еще на стадии компиляции. Например, поле myDimension класса SquareMatrix логично проинициализировать в конструкторе: Существует момент загрузки класса (обычно до первого
использования класса). При этом происходит инициализация класса в порядке
аналогичном порядку инициализации объекта (см. пункт 1.1 данной лекции), но
только с полями (статическими) и инициализаторами (класса) отмеченными ключевым
словом static. Рассмотрим простой пример: Порядок действий при инициализации класса С: Статические поля можно использовать, например, для подсчета
количества экземпляров данного класса При именовании статических полей принято использовать префикс
«our» Инициализаторы класса в среднем используются чаще чем простые
инициализаторы Cуществуют «настоящие константы».
Например, в классе Float определено: static final поле должно быть проинициализировано при инициализации
класса один и только один раз. Возможность осуществления иного сценария вызовет
ошибку еще на стадии компиляции. Принято имя static final поля писать прописными буквами. В классе Object существует метод Его, естественно, можно перекрывать. Метод finalize будет вызван при
уничтожении объекта. Но то, что до конкретного объекта когда-нибудь дойдет
сборщик мусора, не гарантируется. Это определяется, в том числе, внутренней
логикой работы сборщика мусора. То есть может такое быть, что программа
завершится раньше, чем объект будет обработан garbage collector’ом. Обычно предполагается, что метод finalize
если и будет вызван, то только один раз. Если вызвать finalize
вручную, то повторный вызов finalize при уничтожении
объекта сборщиком мусора может привести к поломке программы. finalize изредка используется в
стандартной библиотеке. Использование final создает
ограничения на этапе компиляции. Ключевое слово final может применяться
к 4 видам сущностей языка java. К полям (см. выше) К локальным переменным. Результат аналогичен применению const в C++. Локальные final переменные обязаны инициализироваться сразу. Пример: final относится только к ссылке «n». При этом, естественно, сам объект можно менять, используя, к примеру, метод Но оператор вызовет ошибку на этапе компиляции. К методам final методы нельзя перекрывать (но можно перегружать). При компиляции выражению будет сопоставлена не сигнатура, а конкретная функция. Поэтому final методы определяют в основном только для оптимизации. К классам У final класса не может быть
наследников. final классы, так же как и final методы используются в основном только для ускорения
работы программы, так как все методы final класса -
тоже final. Рассмотрим (a == b) – false, так как, естественно, в данном случае «==» - это
сравнение непосредственно переменных a и b, то есть ссылок. А они указывают на разные объекты. Аналогично со строками и массивами – специальными объектами java. В классе Object существует
специальный, используемый, в том числе, в стандартной библиотеке, не final метод equals возвращает true,
если по сути сравниваемые объекты равны, и false – в
ином случае. Реализованный в Object метод equals сравнивает непосредственно ссылки. Часто необходимо
перекрывать его. Например, при использовании Collection Framework, так как, в том числе,
класс Set определяет эквивалентность объектов,
используя equals. В Java существует ужасная с точки
зрения ООП вещь instanceof: (<object> instanceof <Class>)
возвращает true, только если объект
является экземпляром указанного класса. Элементом хорошего стиля является как можно более редкое
использование instanceof. Пример разумного перекрытия equals в
классе Int: Для организации хранения файлов классов существует система packages. Допустим, классу Main требуется для
работы класс Matrix, лежащий в каталоге с относительным
путем «math/matrixes/». Тогда
существуют два варианта действий: Package – это каталог, со всеми и
только с ними содержащимися в нем классами. Имя package
совпадает с его относительным путем. Существуют вложенные пакеты. Чтобы использовать короткие имена для всех классов package matrixes,
можно написать «import math.matrixes.*» Пример файла Main.java: Package также используются для
избежания совпадения имен. Но даже длинные имена классов иногда совпадают.
Чтобы избегать этого, сформулировано несколько правил: Пример организации папок:new B();
Константные поля
class SquareMatrix {
…
final int myDimension;
…
}
public SquareMatrix(int dimension) {
myDimension = dimension;
…
}
Инициализация класса
class С {
static int x = 1; // 1
static { // 2
…
}
static int y = 2; // 3
static { // 4
…
}
…
}
static int ourCounter = 0;
public static final float MIN_VALUE = 1.4E-45f;
Финализация. «finalize»
public void finalize()
«final»
final Int n = new Int();
n.setValue(10);
n = n2;
Сравнение объектов
Int a = new Int();
Int b = new Int();
public boolean equals(Object o)
public boolean equals(Object o) {
if (o instanceof Int) {
return (((Int) o).myValue == myValue);
} else {
return false;
}
}
Packages
package org.borland;
import math.matrixes.*;
public class Main {
…
}
org/
borland/
Main.java («import math.matrixes.*»)
math/
matrixes/
Matrix.java
MatrixException.java