Программирование на Java
Шрифт:
// Объявляем новый класс и наследуем
// его от класса Child
class ChildOfChild extends Child { }
Теперь заведем переменную нового типа:
Parent p = new ChildOfChild;
print(p instanceof Child);
В первой строке объявляется переменная типа Parent, которая инициализируется ссылкой на объект, порожденный от ChildOfChild. Во второй строке оператор instanceof анализирует совместимость ссылки типа Parent с классом Child, причем задействованный объект не порожден
Добавим еще один класс:
class Child2 extends Parent {
}
И снова объявим переменную типа Parent:
Parent p=new Child;
print(p instanceof Child);
print(p instanceof Child2);
Переменная p имеет тип Parent, а значит, может ссылаться на объекты типа Child или Child2. Оператор instanceof помогает разобраться в ситуации:
true
false
Для ссылки, равной null, оператор instanceof всегда вернет значение false.
С изучением свойств объектной модели Java мы будем возвращаться к алгоритму работы оператора instanceof.
Операторы сравнения == и != проверяют равенство (или неравенство) объектных величин именно по ссылке. Однако часто требуется альтернативное сравнение – по значению. Сравнение по значению имеет дело с понятием состояние объекта. Сам смысл этого выражения рассматривается в ООП, что же касается реализации в Java, то состояние объекта хранится в его полях. При сравнении по ссылке ни тип объекта, ни значения его полей не учитываются, true возвращается только в том случае, если обе ссылки указывают на один и тот же объект.
Point p1=new Point(2,3);
Point p2=p1;
Point p3=new Point(2,3);
print(p1==p2);
print(p1==p3);
Результатом будет:
true
false
Первое сравнение оказалось истинным, так как переменная p2 ссылается на тот же объект, что и p1. Второе же сравнение ложно, несмотря на то, что переменная p3 ссылается на объект-точку с точно такими же координатами. Однако это другой объект, который был порожден другим выражением new.
Если один из аргументов оператора == равен null, а другой – нет, то значение такого выражения будет false. Если же оба операнда null, то результат будет true.
Для корректного сравнения по значению существует специальный метод equals, который будет рассмотрен позже. Например, строки надо сравнивать следующим образом:
String s = "abc";
s=s+1;
print(s.equals("abc1"));
Операция с условием ?: работает как обычно и может принимать второй и третий аргументы, если они оба одновременно ссылочного типа. Результат такого оператора также будет иметь объектный тип.
Как и простые типы, ссылочные величины можно складывать со строкой. Если ссылка равна null, то к строке добавляется текст "null". Если же ссылка указывает на объект, то у него вызывается специальный метод (он будет рассмотрен ниже, его имя toString )
Класс Object
В Java множественное наследование отсутствует. Каждый класс может иметь только одного родителя. Таким образом, мы можем проследить цепочку наследования от любого класса, поднимаясь все выше. Существует класс, на котором такая цепочка всегда заканчивается, это класс Object. Именно от него наследуются все классы, в объявлении которых явно не указан другой родительский класс. А значит, любой класс напрямую, или через своих родителей, является наследником Object. Отсюда следует, что методы этого класса есть у любого объекта (поля в Object отсутствуют), а потому они представляют особенный интерес.
Рассмотрим основные из них.
getClass
Этот метод возвращает объект класса Class, который описывает класс, от которого был порожден этот объект. Класс Class будет рассмотрен ниже. У него есть метод getName, возвращающий имя класса:
String s = "abc";
Class cl=s.getClass;
System.out.println(cl.getName);
Результатом будет строка:
java.lang.String
В отличие от оператора instanceof, метод getClass всегда возвращает точно тот класс, от которого был порожден объект.
equals
Этот метод имеет один аргумент типа Object и возвращает boolean. Как уже говорилось, equals служит для сравнения объектов по значению, а не по ссылке. Сравнивается состояние объекта, у которого вызывается этот метод, с передаваемым аргументом.
Point p1=new Point(2,3);
Point p2=new Point(2,3);
print(p1.equals(p2));
Результатом будет false.
Поскольку сам Object не имеет полей, а значит, и состояния, в этом классе метод equals возвращает результат сравнения по ссылке. Однако при написании нового класса можно переопределить этот метод и описать правильный алгоритм сравнения по значению (что и сделано в большинстве стандартных классов). Соответственно, в класс Point также необходимо добавить переопределенный метод сравнения:
public boolean equals(Object o) {
// Сначала необходимо убедиться, что
// переданный объект совместим с типом
// Point
if (o instanceof Point) {
// Типы совместимы, можно провести
// преобразование
Point p = (Point)o;
// Возвращаем результат сравнения
// координат
return p.x==x && p.y==y;
}
// Если объект не совместим с Point,
// возвращаем false
return false;
}
hashCode
Данный метод возвращает значение int. Цель hashCode – представить любой объект целым числом. Особенно эффективно это используется в хэш-таблицах (в Java есть стандартная реализация такого хранения данных, она будет рассмотрена позже). Конечно, нельзя потребовать, чтобы различные объекты возвращали различные хэш-коды, но, по крайней мере, необходимо, чтобы объекты, равные по значению (метод equals возвращает true ), возвращали одинаковые хэш-коды.