Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
GoslingJava2.doc
Скачиваний:
139
Добавлен:
23.02.2016
Размер:
2.39 Mб
Скачать

2.6.1. Значения параметров

Все параметры в Java передаются “по значению”. Другими словами, значения переменных-параметров метода являются копиями значений, указанных при его вызове. Если передать методу переменную некоторого типа, то параметр будет представлять собой копию этой переменной; ее изменение внутри метода никак не повлияет на значение переменной в коде за его пределами. Например:

class PassByValue {

public static void main(String[] args) {

double one = 1.0;

System.out.println(“before: one = ” + one);

halveIt(one);

System.out.println(“after: one = ” + one);

}

public static void halveIt(double arg) {

arg /= 2.0; //

System.out.println(“halved: arg = ” + arg);

}

}

Приведенные ниже результаты показывают, что деление на два переменной arg в методе halveIt не меняет значения переменной one в методе main:

before: one = 1

halved: arg = 0.5

after: one = 1

Однако, если параметр метода представляет собой ссылку на объект, то “по значению” передается ссылка, а не сам объект! Следовательно, вы можете изменять в методе тот объект, на который она ссылается,— значение ссылки остается прежним. Можно изменять любые поля объекта или вызывать методы, влияющие на его состояние,— произойдет изменение объекта во всех фрагментах программы, где имеется ссылка на него. Приведенный ниже пример наглядно показывает, чем данный случай отличается от предыдущего:

class PassRef {

public static void main(String[] args) {

Body sirius = new Body(“Sirius”, null);

System.out.println(“before: ” + sirius);

commonName(sirius);

System.out.println(“after: ” + sirius);

}

public static void commonName(Body bodyRef) {

bodyRef.name = “Dog Star”;

bodyRef = null;

}

}

Результат будет следующим:

before: 0 (Sirius)

after: 0 (Dog Star)

Обратите внимание на то, что название объекта изменилось, тогда как ссылка bodyRef все равно указывает на объект Body (хотя метод commonName присваивал параметру bodyRef значение null).

Приведенная выше диаграмма показывает состояние ссылок непосредственно после вызова commonName в main. Обе ссылки— sirius (в main) иbodyRef (в commonName)— указывают на один и тот же объект. Когда commonName изменяет значение поля bodyRef.name, то название изменяется в объекте, совместно используемом обоими ссылками. Однако при присвоении null ссылке bodyRef изменяется только ее значение, тогда как значение ссылки на объект sirius остается тем же самым; вспомним, что параметр bodyRef является передаваемой по значению копией sirius. Внутри метода commonNameизменяется лишь значение переменной-параметра bodyRef, подобно тому как в методе halveIt изменялось лишь значение параметра-переменной arg. Если бы изменение bodyRef относилось и к значению sirius в main, то в строке, начинающейся с “after: ”, стояло бы “null”. Тем не менее переменные bodyRef в commonName и sirius в main указывают на один и тот же объект, поэтому изменения, вносимые в commonName, отражаются и в том объекте, на который ссылается sirius.

2.6.2. Применение методов для ограничения доступа

Пользоваться классом Body с несколькими конструкторами стало значительно удобнее, чем его старым вариантом, состоявшим из одних данных; кроме того, мы обеспечили правильное автоматическое присвоение значений idNum. И все же программист может все испортить, изменяя значение поля idNum после конструирования объекта,— ведь данное поле объявлено как public и открыто для любых действий. Необходимо, чтобы поле idNum содержало данные, доступные только для чтения. Подобные данные в объектах встречаются довольно часто, но в языке Java не существует ключевого слова, которое сделало бы поле за пределами класса доступным только для чтения.

Чтобы сделать поле доступным только для чтения, мы должны скрыть его. Для этого поле idNum объявляется с ключевым словом private, а в класс добавляется новый метод, с помощью которого код за пределами класса может получить значение этого поля:

class Body {

private long idNum; // поле стало private

public String name = “”;

public Body orbits = null;

private static long nextID = 0;

Body() {

idNum = nextID++;

}

public long id() {

return idNum;

}

// ...

}

Начиная с этого момента программист, которому понадобилось узнать идентификатор небесного тела, должен вызвать метод id, возвращающий требуемое значение. У программиста не остается никакой возможности изменить идентификатор— в сущности, за пределами класса его можно рассматривать как величину, доступную только для чтения. Данное поле может быть изменено только внутренними методами класса Body.

Методы, регулирующие доступ к внутренним данным класса, иногда называются методами доступа (accessor methods). С их помощью также можно (и, наверное, нужно) защитить поля name и orbits.

Даже если интересы приложения и не требуют полей, доступных только для чтения, объявление полей класса с ключевым словом private и создание методов для присвоения/получения их значений позволяет вам определить необходимые действия над объектом в будущем. Если программист может непосредственно обращаться к полям класса, вы неизбежно теряете контроль над тем, какие значения будут принимать эти поля и что происходит в программе при их изменении. По этим причинам в дальнейших примерах этой книги поля public встречаются очень редко.

Упражнение 2.8

Объявите поля класса Vehicle с ключевым словом private и опишите соответствующие методы доступа. Для каких полей следует предусмотреть методы, изменяющие их значения, а для каких— нет?

Упражнение 2.9

Объявите поля класса LinkedList с ключевым словом private и включите в класс соответствующие методы доступа. Для каких полей следует предусмотреть методы, изменяющие их значения, а для каких— нет?

Упражнение 2.10

Включите в класс Vehicle метод changeSpeed для задания текущей скорости машины в соответствии с передаваемым значением и метод stop для обнуления скорости.

Упражнение 2.11

Включите в класс LinkedList метод для подсчета количества элементов в списке.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]