Эккель Брюс
Шрифт:
а = 4
но нельзя присвоить что-либо константе — она не может использоваться в качестве именующего выражения (например, запись 4 = а недопустима).
Для примитивов присвоение выполняется тривиально. Так как примитивный тип хранит данные, а не ссылку на объект, то присвоение сводится к простому копированию данных из одного места в другое. Например, если команда а = b выполняется для примитивных типов, то содержимое b просто копируется в а. Естественно, последующие изменения а никак не отражаются на Ь. Для программиста именно такое поведение выглядит наиболее логично.
При присвоении объектов все меняется. При выполнении операций с объектом вы в действительности работаете со ссылкой, поэтому присвоение «одного объекта другому» на самом деле означает копирование ссылки из одного места в другое. Это значит, что при выполнении команды с = d для объектов в конечном итоге end указывают на один объект, которому изначально соответствовала только ссылка d. Сказанное демонстрирует следующий пример:
//: operators/Assignment java // Присвоение объектов имеет ряд хитростей import static net.mindview.util Print.*,
class Tank {
int level,
}
public class Assignment {
public static void main(String[] args) { Tank tl = new TankO. Tank t2 = new TankO, tl level = 9; t2 level = 47,
printC'l tl level " + tl level + \ t2 level " + t2 level);
tl = t2;
print("2- tl level- " + tl level +
t2.level• " + t2 level), tl.level = 27.
print("3 tl.level- " + tl level + t2.level. " + t2 level).
}
} /* Output
1 tl level. 9. t2.level. 47
2 tl level- 47. t2 level. 47
3: tl.level. 27. t2 level: 27
*/// ~
Класс Tank предельно прост, и два его экземпляра (tl и t2) создаются внутри метода main. Переменной level для каждого экземпляра придаются различные значения, а затем ссылка t2 присваивается tl, в результате чего tl изменяется. Во многих языках программирования можно было ожидать, что tl и t2 будут независимы все время, но из-за присвоения ссылок изменение объекта tl отражается на объекте t2! Это происходит из-за того, что tl и t2 содержат одинаковые ссылки, указывающие на один объект. (Исходная ссылка, которая содержалась в tl и указывала на объект со значением 9, была перезаписана во время присвоения и фактически потеряна; ее объект будет вскоре удален сборщиком мусора.)
Этот феномен совмещения имен часто называют синонимией (aliasing), и именно она является основным способом работы с объектами в Java. Но что делать, если совмещение имен нежелательно? Тогда можно пропустить присвоение и записать
tl.level = t2 level;
При этом программа сохранит два разных объекта, а не «выбросит» один из них, «привязав» ссылки tl и t2 к единственному объекту. Вскоре вы поймете, что прямая работа с полями данных внутри объектов противоречит принципам объектно-ориентированной разработки. Впрочем, это непростой вопрос, так что пока вам достаточно запомнить, что присвоение объектов может таить в себе немало сюрпризов.
Совмещение имен во время вызова методов
Совмещение имен также может происходить при передаче объекта методу:
// operators/PassObject java
// Передача объектов методам может работать
// не так. как вы привыкли.
import static net.mindview.util.Print.*;
class Letter { char c;
}
public class PassObject {
static void f(Letter y) { y.c = 'z';
}
public static void main(String[] args) { Letter x = new LetterO; x.c = 'a';
printCl; x.c; " + x.c); f(x);
print("2: x.c: " + x.c);
}
} /* Output 1: x.c: a 2: x.c: z */ ///
Во многих языках программирования метод f создал бы копию своего параметра Letter у внутри своей области действия. Но из-за передачи ссылки строка
у.с = 'z';
на самом деле изменяет объект за пределами метода f.
Совмещение имен и решение этой проблемы — сложные темы. Будьте очень внимательными в таких случаях во избежание ловушек.
Арифметические операторы
Основные математические операторы остаются неизменными почти во всех языках программирования: сложение (+), вычитание (-), деление (/), умножение (*) и остаток от деления нацело (%). Деление нацело обрезает, а не округляет результат.
В Java также используется укороченная форма записи для того, чтобы одновременно произвести операцию и присвоение. Она обозначается оператором с последующим знаком равенства и работает одинаково для всех операторов языка (когда в этом есть смысл). Например, чтобы прибавить 4 к переменной х и присвоить результат х, используйте команду х += 4.