Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Абстрактные классы интерфейсы внутренние классы...doc
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
204.29 Кб
Скачать

Внутренние классы (Хорстманн стр. 282-new)

Внутренним (inner) называется класс, определенный внутри другого класса. Внутренние классы удобно использовать в следующих случаях:

  • необходимо обеспечить доступ к реализации объекта, который создал данный объект, включая закрытые данные;

  • необходимо скрыть данный класс от других классов того же пакета

  • при создании событийно-управляемых программ (анонимные внутренние классы ) .

Рассмотрим пример. (InnerClassTest.java)

/* version 1.10 2004-02-27 author Cay Horstmann */

import java.awt.*;

import java.awt.event.*;

import java.util.*;

import javax.swing.*;

import javax.swing.Timer;

public class InnerClassTest

{

public static void main(String[] args)

{

TalkingClock clock = new TalkingClock(1000, true);

clock.start();

JOptionPane.showMessageDialog(null, "Quit program?");

System.exit(0);

}

}

class TalkingClock

{

private int interval;

private boolean beep;

public TalkingClock(int interval, boolean beep)

{

this.interval = interval;

this.beep = beep;

}

public void start()

{

ActionListener listener = new TimePrinter();

Timer t = new Timer(interval, listener);

t.start();

}

private class TimePrinter implements ActionListener

{

public void actionPerformed(ActionEvent event)

{

Date now = new Date();

System.out.println("At the tone, the time is " + now);

if (beep) Toolkit.getDefaultToolkit().beep();

}

}

}

Класс TimePrinter расположен в классе TalkingClock. Объекты TimePrinter создаются с методами класса TalkingClock.

TimePrinter представляет собой закрытый внутренний класс в составе TalkingClock. В результате создавать объекты TimePrinter могут только методы класса TalkingClock. Если бы TimePrinter был обычным классом, он должен был бы получить доступ к флагу beep посредством общедоступного метода. Наличие внутреннего класса делает это не обязательным при том же уровне безопасности.

Для определения анонимного внутреннего класса характерно следующее:

  • класс определяется локально в отдельном методе внешнего класса;

  • при объявлении класса не используются модификаторы доступа (public, protected). Их область видимости ограничена блоком в котором они объявлены;

  • методы анонимного класса могут ссылаться на локальные переменные объявленные как final;

  • в общем случае синтаксис определения анонимного класса выглядит следующим образом:

new СуперТип (параметры, необходимые для создания объекта)

{

Методы внутреннего класса и данные.

}

СуперТип – это или интерфейс (если внутренний класс реализует интерфейс), или класс (тогда внутренний класс расширяет данный суперкласс)

  • анонимный класс не может иметь конструкторов.

Анонимные внутренние классы довольно часто используются при создании событийно-управляемых программ. Это касается программного кода, который генерируется оболочкой языка (например NetBeans) при макетировании панели диалога и обработки событий от элементов управления.

Пример AnonymousInnerClassTest.java демонстрирует использование анонимного внутреннего класса.

/* version 1.10 2004-02-27 author Cay Horstmann */

import java.awt.*;

import java.awt.event.*;

import java.util.*;

import javax.swing.*;

import javax.swing.Timer;

public class AnonymousInnerClassTest

{

public static void main(String[] args)

{

TalkingClock clock = new TalkingClock();

clock.start(1000, true);

JOptionPane.showMessageDialog(null, "Quit program?");

System.exit(0);

}

}

class TalkingClock

{

public void start(int interval, final boolean beep)

{

ActionListener listener = new ActionListener()

{

public void actionPerformed(ActionEvent event)

{

Date now = new Date();

System.out.println("At the tone, the time is " + now);

if (beep) Toolkit.getDefaultToolkit().beep();

}

};

Timer t = new Timer(interval, listener);

t.start();

}

}

Рассмотрим некоторые детали.

  1. Вызывается метод clock.start(1000, true);

  2. Инициализируется объектная переменная listener

  3. Ссылка listener передается конструктору класса Timer, таймер запускается и метод start() прекращает свою работу. В этот момент параметр beep метода start() больше не существует.

  4. Впоследствии (по истечении интервала таймера) вызывается метод actionPerformed() он выполняет оператор if (beep) . . . и . . .???

Чтобы метод actionPerformed() выполнялся успешно анонимный класс должен создать копию поля beep до того как оно перестанет существовать в качестве локальной переменной метода start(). Это и происходит.

15