Вложенные классы и интерфейсы
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

Классы и интерфейсы могут быть объявлены в составе других классов и интерфейсов, как в качестве членов, так и внутри блоков кода. Такие вложенные классы и вложенные интерфейсы способны принимать различные формы, каждая из которых обладает собственными свойствами и назначением.

Возможность определять вложенные типы, предусмотренная в языке Java служит нескольким целям:

• Вложенные типы позволяют представить тип в виде логически связанных структурных групп и контекстов.

• Вложенные типы – это простой и эффективный инструмент объединения семантики соотносимых объектов. Эта возможность активно применяется при создании программных сред, управляемых событиями, примерами могут служить пакет AWT и компонентная архитектура JavaBeans .

Вложенные типы считаются частью внешнего типа, и оба типа находятся во взаимно «доверительных» отношениях – один из них обладает правом обращаться ко всем членам другого. Основные различия между вложенными типами обусловлены тем, является ли вложенный тип классом или интерфейсом, и тем, к какой категории относится внешний тип – к классам или интерфейсам.

Пример вложенного класса – пример 56.

Пример 56.

package ru.smr.ipsi.ConformingEstimation;

abstract public class ConformingEstimation {

private double[][] x;

private double[] y;

protected final int n;

protected final int m;

protected class LowerSubsystem {

public int[] code;

public double[] estimate;

private void calculateEstimate() {

estimate = solveLinearEquationSystem(x, y);

}

}

// ...

Вложенные типы могут быть объявлены как статические или нестатическаие. Статические вложенные типы более просты для восприятия и использования, поэтому с них мы и начнём.

Статические вложенные классы

Статический вложенный класс - это простейшая форма вложенного класса, в его объявлении присутствует служебное слово static. Если класс вложен в интерфейс, он получает статус статического по умолчанию, и модификатор static, в соответствии с принятым соглашением, опускается. Статический вложенный класс может наследовать другие классы, реализовывать любые интерфейсы и сам по себе служить объектом расширения для любого класса, обладающего необходимыми правами доступа. В объявлении статического вложенного класса, как и обычного класса, разрешается применять модификаторы final и abstract. Статические классы, вложенные в другой класс, являются членами последнего и допускают применение любых модификаторов доступа.

Пример 57.

abstract public class ClassA {

protected static class ClassB {

...

}

}

Вложенные интерфейсы

Вложенные интерфейсы всегда статичны, хотя соответствующий модификатор, static, в соответствии с принятым соглашением, принято опускать. Доступ определяется доступом внешнего класса или интерфейса.

Пример 58.

public class ClassA {

protected interface InterfaceB {

...

}

}

Нестатические вложенные классы

Нестатические вложенные классы называются внутренними классами. Объект внутреннего класса всегда ассоциируется с т.н. внешним объектом (с соответствующим объектом внешнего класса). Элементы внутреннего класса имеют доступ к полям и методам внешнего объекта. Внутренние классы не способны содержать статические члены, кроме полей вида final static, инициализируемых константами или постоянными выражениями. Внутренние классы, как и обычные, способны расширять любые другие классы, реализовывать интерфейсы и выступать в роли объектов наследования. Вполне допустимо использовать в объявлении внутреннего класса модификаторы final и abstract.

Пример 59.

abstract public class ClassA {

private class ClassB {

...

}

}

Локальные классы

Разрешается объявлять вложенные классы внутри блоков кода, таких как тело метода, конструктор или блок инициализации. Подобный локальный внутренний класс не является членом класса, к которому относится блок, а принадлежит самому блоку – точно так же, как обычная локальная переменная. Такие классы недоступны за пределами внешнего класса, т.к. не сущестует способов обращения к ним, но их экземпляры – это обычные объекты, которые позволяется передавать в качестве аргументов или возвращать из методов. Единственный модификатор, который допускается применять в объявлении локального класса, - это final (модификаторы доступа запрещены). Экземпляры имеют доступ не только к полям и методам внешнего объекта, но и к локальным переменным. Однако такие переменные должны быть объявлены как final.

Пример 60.

public class ClassA {

public Iterator iterator() {

class Iter implements Iterator {

...

}

...

return new Iter();

}

Анонимные классы

Анонимные классы описываются непосредственно в выражении new и служат его частью. Тип, указанный после new, является базовым для объявляемого анонимного класса. Могут расширять один класс или реализовывать один интерфейс. Явно писать implements или extends нельзя. Не могут иметь конструкторов, так как имя конструктора должно совпадать с именем класса, а в данном случае класс не имеет имени. Параметры, необходимые для создания объекта, передаются конструктору суперкласса.

Пример 61.

import java. awt.*;

import java. applet.*;

public class MyApplet extends Applet {

.. .

public void init() {

Button btn = new Button(“?”);

add(btn);

btn.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {

   ((Button)e.getSource()).setLabel(“!”);

}

});

}

}

Технология Swing

Проблемы AWT

1. Сходные элементы в различных ОС могут иметь некоторые различия (например, меню, панели прокрутки).

2. ОС часто имеют элементы GUI, отсутствующие в других ОС (некоторые графические среды программирования, например, X 11/ Motif , не имеют такого богатого набора компонентов пользовательского интерфейса, как ОС Windows или Macintosh ).

3. Использование native-методов в AWT приводит к возникновению ошибок на конкретных платформах (на разных платформах возникали разные ошибки, приходилось тестировать каждое приложение на каждой платформе).

В 1996 г. компания Netscape создала библиотеку программ для создания графического пользовательского интерфейса и назвала её IFC (Internet Foundation Classes). Эта библиотекабыла основана на совершенно других принципах. Элементы пользовательского интерфейса рисовались в пустом окне. Единственная функциональность, которая требовалась от оконной системы платформы, заключалась в отображении окна и рисовании в нём. Таким образом, элемнты графического пользовательского интерфейса, созданные с помощью библиотеки IFC , выглядели и вели одинаково, но не зависили от платформы, на которой запускалась программа. Компании Sun и Netscape объединили свои усилия и усовершенствовали этот подход, создав библиотеку под названием Swing . С тех пор слово Swing стало официальным названием набора интсрументальных средств для создания машиннонезависимого пользовательского интерфейса.

Особенности Swing

1. Элементы GUI (меню, кнопки) отрисовываются в пустых окнах.

2. «Нативные» функции используются только для вывода окна, отрисовки и получения информации о действиях пользователя.

3. Обладает свойством «легковесности» (lightweight).

4. Набор элементов GUI более широк, чем в AWT, и может быть еще расширен.

5. Сильная привязка к «нативным» методам отсутствует, что снижает вероятность возникновения ошибок.

6. Отображение на различных платформах единообразно.

 

Look And Feel

Программисты, использующие Swing, могут придать своей программе внешний вид в заданном стиле. Программе можно придать различный вид, изменив «стиль» отрисовки компонентов. Есть разработанные «стили» для базовых платформ. Существует возможность создания собственных «стилей». Sun разработала независимый от платформы стиль, названный Metal , который прозвали стилем Java . На рисунках 34-36 показано, как выглядит одна и та же программа при использовании различных стилей.

Рисунок 34. Windows

Рисунок 35. Motif

Рисунок 36. Java (Metal)

Внешний вид программы может изменяться во время исполнения. Перерисовка должна вызываться принудительно.

На рисунках 37-38 показана иерархия классов.

Рисунок 37. Иерархия классов

 

Рисунок 38. Иерархия классов

Апплеты в Swing

Используется класс JApplet. Для добавления элементов в область апплета не используется его метод add(). Содержимое аплета находится на панели, ссылку на которую можно получить вызовом метода getContentPane(). Пример апплета приведен в примере 62.

Пример 62.

import java.awt.*;

import java.awt.event.*;

import java.net.*;

import java.applet.*;

import javax.swing.*;

public class SwingApplet extends JApplet {

JButton button;

public void init() {

String laf = UIManager.getSystemLookAndFeelClassName();

try {

UIManager.setLookAndFeel(laf);

} catch (UnsupportedLookAndFeelException exc) {

System.err.println("Warning: UnsupportedLookAndFeel: " + laf);

} catch (Exception exc) {

System.err.println("Error loading " + laf + ": " + exc);

}

getContentPane().setLayout(new FlowLayout());

button = new JButton("Hello, I'm a Swing Button!");

getContentPane().add(button);

}

}

Создание оконных приложений

• Используется класс JFrame .

• Содержимое окна находится на панели, ссылку на которую можно получить вызовом метода getContentPane ().

• Параметрами окна можно управлять.

Пример 63.

import java.awt.*;

import javax.swing.*;

public class CenteredFrameTest {

public static void main(String[] args) {

CenteredFrame frame = new CenteredFrame();

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.setVisible(true);

}

}

class CenteredFrame extends JFrame {

public CenteredFrame() {

Toolkit kit = Toolkit.getDefaultToolkit();

Dimension screenSize = kit.getScreenSize();

int screenHeight = screenSize.height;

int screenWidth = screenSize.width;

setSize(screenWidth / 2, screenHeight / 2);

setLocation(screenWidth / 4, screenHeight / 4);

Image img = kit.getImage("icon.gif");

setIconImage(img); setTitle("CenteredFrame");

}

}

Комментарий к примеру 63.

Определяем, что должно произойти, если пользователь закроет фрейм. В данном случае программа должна завершить свою работу. Для этого используется строка кода

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

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

Простое создание фрейма не приводит к его автоматическому появлению на экране. В начале своего существования все фреймы невидимы. Это дает возможность добавлять к фрейму компоненты еще до того, как он впервые появится на экране. Чтобы показать фрейм на экране, вызывается метод setVisible().

Если размер не задан явно, все фреймы по умолчанию имеют размер 0х0 пикселей. В профессиональных приложениях нужно сначала проверить разрешающую способность экрана и написать код, изменяющий размер фрейма в соответствии с полученной величиной: окно, которое прекрасно смотрится на экране портативного компьютера, на экране дисплея с большой разрешающей способностью будет выглядеть как почтовая марка. Для того, чтобы определить размер экрана, надо выполнить следующие действия: сначала следует вызвать статический метод getDefaultToolkit (), класса Toolkit , который вернет объект Toolkit . Класс Toolkit содержит много методов, предназначенных для взаимодействия с оконной системой конкретной платформы. Затем надо вызвать метод getScreenSize (), который вернет размер экрана в виде объекта Dimension . Этот объект содеожит ширину и высоту в общедоступных переменных width и height . Мы также предоставим пиктограмму для фрейма. Поскольку процесс изображения рисунков на экране также зависит от ОС, для загрузки рисунка нам снова нужен объект Toolkit . Затем этот рисунок устанавливается в качестве пиктограммы.

Image img = kit.getImage("icon.gif");

setIconImage(img); setTitle("CenteredFrame");

Отрисовка компонентов

• Отрисовка производится в методе paintComponent ().

• Для перерисовки по требованию вызывается метод repaint ().

Пример 64.

class NotHelloWorldPanel extends JPanel {

public void paintComponent(Graphics g) {

super.paintComponent(g);

g.drawString("Not a Hello, World program",

MESSAGE_X, MESSAGE_Y);

}

public static final int MESSAGE_X = 75;

public static final int MESSAGE_Y = 100;

}

Комментарий к примеру 64.

Можно было расширить класс JComponent .

JPanel предназаначен служить контейнером, котрый может содержать в себе другие компоненты, но можно также рисовать непосредственно в нем. Однако следует иметь в виду, что панель непрозрачна, а это значит, что она отвечает за рисование всех пикселей в ее пределах. Простейший способ достичь того же - залить панель цветом фона, вызвав super . paintComponent (), в методе paintComponent каждого подкласса панели.

В целях экономии времени на перерисовку логично запоминать однажды нарисованный статичный объект как рисунок в памяти. При использовании Swing для этого не надо предпринимать дополнительных действий по выделению памяти и.д. Используется т.н. механизм «двойной буферизации», реализующий сохранение информации на уровне механизмов отрисовки. Для одного участка «видимой области» приложения используется не более одного изображения-буфера. Методы класса JComponent:

setDoubleBuffered( boolean aFlag ). Устанавливает, буферизует ли объект свой вывод.

boolean isDoubleBuffered(). Возвращает булевское значение, показывающее, используется ли двойная буферизация, или нет

Работа с графикой

java . awt . Graphics 2 D
Класс-наследник класса java . awt . Graphics, обеспечивающий большую функциональность

java . awt . geom .*
Содержит набор классов работы с графическими примитивами



Работа с меню

javax . swing . JMenuBar
Панель меню в верхней части окна

javax . swing . JMenu
Меню как таковое

javax . swing . JMenuItem
Единичный элемент меню

javax . swing .JCheckBoxMenuItem
Элемент меню «флажок»

javax . swing .JRadioButtonMenuItem
Элемент меню «радио-кнопка»

javax.swing.JPopup
Всплывающее меню







Некоторые замечания

• Swing предоставляет более широкие и надежные возможности, чем AWT

• Эти возможности касаются в основном отрисовки компонентов

• Модель обработки событий и другие внутренние механизмы приложения относятся к AWT, а не к Swing

• Некорректно говорить, что Swing заменил AWT

• Современные средства разработки имеют визуальные редакторы для создания пользовательских интерфейсов

Нерассмотренные возможности

• Дополнительные события javax . swing . event

• Создание своих «стилей» отображения javax . swing . plaf

• «Высокоинтеллектуальные» компоненты JTree , JTable и т.д.

• Drag&Drop java.awt.dnd

• Вывод на печать java . awt . print

Рефлексия

• Рефлексия – исследование самого себя.

• Рефлексия в Java – возможность программы анализировать саму себя, взаимодействуя с виртуальной машиной Java (JVM).

Дата: 2019-02-19, просмотров: 241.