38

38


//: initialization/Apricot.java public class Apricot {

void pickO { /* .. */ } void pit() { pickO; /*..*/} } ///:-

Внутри метода pit() можно использовать запись this.pick(), но в этом нет не¬обходимости . Компилятор сделает это автоматически. Ключевое слово this употребляется только в особых случаях, когда вам необходимо явно сослаться на текущий объект. Например, оно часто применяется для возврата ссылки на текущий объект в команде return:

//: initialization/Leaf.java // Simple use of the "this" keyword.

public class Leaf { int i = 0; Leaf increment О { i++;

return this;

}

void printO {

System, out. printlnC'i = " + i).

}

public static void main(String[] args) { Leaf x = new LeafO;

x.i ncrement().i ncrement() i ncrement().pri nt О;

}

} /* Output: i = 3 *///:-

Так как метод increment() возвращает ссылку на текущий объект посредст¬вом ключевого слова this, над одним и тем же объектом легко можно провести множество операций.

Ключевое слово this также может пригодиться для передачи текущего объек¬та другому методу:

//. initialization/PassingThis java

class Person {

public void eat(Apple apple) {

Apple peeled = apple.getPeeledО; System.out.println("Yummy");

}

}

class Peeler {

static Apple peel(Apple apple) {

продолжение &

// .. Снимаем кожуру

return apple; // Очищенное яблоко

}

}

class Apple {

Apple getPeeledO { return Peeler.peel(this); }

}

public class PassingThis {

public static void main(String[] args) { new Person О eat (new AppleO);

}

} /* Output: Yummy *///.-

Класс Apple вызывает Peeler.peel() — вспомогательный метод, который по ка¬кой-то причине должен быть оформлен как внешний по отношению к Apple (мо¬жет быть, он должен обслуживать несколько разных классов, и вы хотите избе¬жать дублирования кода). Для передачи текущего объекта внешнему методу используется ключевое слово this.

Вызов конструкторов из конструкторов

Если вы пишете для класса несколько конструкторов, иногда бывает удобно вызвать один конструктор из другого, чтобы избежать дублирования кода. Та¬кая операция проводится с использованием ключевого слова this.

Обычно при употреблении this подразумевается «этот объект» или «теку¬щий объект», и само слово является ссылкой на текущий объект. В конструкто¬ре ключевое слово this имеет другой смысл: при использовании его со списком аргументов вызывается конструктор, соответствующий данному списку. Таким образом, появляется возможность прямого вызова других конструкторов:

// initialization/Flower.java // Calling constructors with "this" import static net.mindview.util.Print.*;

public class Flower { int petal Count = 0; String s = "initial value"; Flower(int petals) {

petal Count = petals;

print("Конструктор с параметром int, petalCount= " + petal Count),

}

Flower(String ss) {

print("Конструктор с параметром String, s = " + ss); s = ss;

}

Flower(String s, int petals) { this(petals),

//! this(s); // Вызов другого конструктора запрещен! this.s = s; // Другое использование "this" print("Аргументы String и int");

}

FlowerО { thisC'hi". 47).

printC'KOHCTpyKTop по умолчанию (без аргументов)"),

}

void printPetalCountO { //! this(11), // Разрешается только в конструкторах! print("petal Count = " + petal Count + " s = "+ s);

}

public static void main(String[] args) { Flower x = new Flower(); x printPetalCountO,

}

} /* Output-

Конструктор с параметром int, petalCount= 47 Аргументы String и int Конструктор по умолчанию (без аргументов) petal Count = 47 s = hi */// ~

Конструктор Flower(String s, int petals) показывает, что при вызове одного конструктора через this вызывать второй запрещается. Вдобавок вызов другого конструктора должен быть первой выполняемой операцией, иначе компилятор выдаст сообщение об ошибке.

Пример демонстрирует еще один способ использования this. Так как имена аргумента s и поля данных класса s совпадают, возникает неоднозначность. Раз¬решить это затруднение можно при помощи конструкции this.s, однозначно оп¬ределяющей поле данных класса. Вы еще не раз встретите такой подход в раз¬личных Java-nporpaMMax, да и в этой книге он практикуется довольно часто.

Метод printPetalCountO показывает, что компилятор не разрешает вызывать конструктор из обычного метода; это разрешено только в конструкторах.

Значение ключевого слова static

Ключевое слово this поможет лучше понять, что же фактически означает объяв¬ление статического (static) метода. У таких методов не существует ссылки this. Вы не в состоянии вызывать нестатические методы из статических  (хотя об¬ратное позволено), и статические методы можно вызывать для имени класса, без каких-либо объектов. Статические методы отчасти напоминают глобальные функции языка С, но с некоторыми исключениями: глобальные функции не разрешены в Java, и создание статического метода внутри класса дает ему право на доступ к другим статическим методам и полям.

Некоторые люди утверждают, что статические методы со своей семантикой глобальной функции противоречат объектно-ориентированной парадигме; в слу¬чае использования статического метода вы не посылаете сообщение объекту, поскольку отсутствует ссылка this. Возможно, что это справедливый упрек, и если вы обнаружите, что используете слишком много статических методов, то стоит пересмотреть вашу стратегию разработки программ. Однако ключевое слово static полезно на практике, и в некоторых ситуациях они определенно не¬обходимы. Споры же о «чистоте ООП» лучше оставить теоретикам.

Очистка: финализация и сборка мусора

Программисты помнят и знают о важности инициализации, но часто забывают о значимости «приборки». Да и зачем, например, «прибирать» после использо¬вания обычной переменной int? Но при использовании программных библио¬тек «просто забыть» об объекте после завершения его работы не всегда безопасно. Конечно, в Java существует сборщик мусора, освобождающий память от не¬нужных объектов. Но представим себе необычную ситуацию. Предположим, что объект выделяет «специальную» память без использования оператора new. Сборщик мусора умеет освобождать память, выделенную new, но ему неизвестно, как следует очищать специфическую память объекта. Для таких ситуаций в Java предусмотрен метод finalize(), который вы можете определить в вашем классе. Вот как он должен работать: когда сборщик мусора готов освободить па¬мять, использованную вашим объектом, он для начала вызывает метод finali- ze(),H только после этого освобождает занимаемую объектом память. Таким об¬разом, метод finalize() позволяет выполнять завершающие действия во время работы сборщика мусора.