Программирование на Java

         

Аплет CDRotation


Назад Вперед

В этом разделе мы расскажем об аплете CDRotation, в окне которого вращается компакт-диск.

В левом верхнем углу каждого кадра отображается его порядковый номер (рис. 1). Этот номер не нарисован в файлах кадров, а надписывается приложением после рисования очередного кадра. Такое невозможно, если располагать в документе HTML файл AVI или многосекционный файл GIF.

Рис. 1. Изображение вращающегося компакт-диска в окне аплета CDRotation



Биты флагов для параметра infoflags метода imageUpdate


public final static int ABORT; public final static int ALLBITS; public final static int ERROR; public final static int FRAMEBITS; public final static int HEIGHT; public final static int PROPERTIES; public final static int SOMEBITS; public final static int WIDTH;



Boolean


Представляет класс-обертку для примитивного типа boolean.

Реализует интерфейс java.io.Serializable и во всем напоминает аналогичные классы-обертки.

Для получения примитивного значения используется метод booleanValue().



Character


Реализует интерфейсы Comparable и Serializable.

Из конструкторов имеет только один, принимающий char в качестве параметра.

Кроме стандартных методов equals(), hashCode(), toString(), содержит только два нестатических метода:

public char charValue() – возвращает обернутое значение char;

public int compareTo(Character anotherCharacter) – сравнивает обернутые значения char как числа, то есть возвращает значение return this.value – anotherCharacter.value.

Также для совместимости с интерфейсом Comparable метод compareTo() определен с параметром Object:



public int compareTo(Object o) – если переданный объект имеет тип Character, результат будет аналогичен вызову compareTo((Character)o), иначе будет брошено исключение ClassCastException, так как Character можно сравнивать только с Character.

Статических методов в классе Character довольно много, но все они просты и логика их работы понятна из названия. Большинство из них - это методы, принимающие char и проверяющие всевозможные свойства. Например:

public static boolean isDigit(char c) // проверяет, является ли char цифрой.

Эти методы возвращают значение истина или ложь, в соответствии с тем, выполнен ли критерий проверки.



Class


В запущенной программе Java каждому классу соответствует объект типа Class. Этот объект содержит информацию, необходимую для описания класса – поля, методы и т.д.

Класс Class не имеет открытого конструктора – объекты этого класса создаются автоматически Java-машиной по мере загрузки описания классов из class-файлов. Получить экземпляр Class для конкретного класса можно с помощью метода forName():

public static Class forName(String name, boolean initialize, ClassLoader loader) – возвращает объект Class, соответствующий классу, или интерфейсу, с названием, указанным в name (необходимо указывать полное название класса или интерфейса), используя переданный загрузчик классов. Если в качестве загрузчика классов loader передано значение null, будет взят ClassLoader, который применялся для загрузки вызывающего класса. При этом класс будет инициализирован, только если значение initialize равно true и класс не был инициализирован ранее.

Зачастую проще и удобнее воспользоваться методом forName(), передав только название класса: public static Class forName(String className),– при этом будет использоваться загрузчик вызывающего класса и класс будет инициализирован (если до этого не был).

public Object newInstance() – создает и возвращает объект класса, который представляется данным экземпляром Class. Создание будет происходить с использованием конструктора без параметров. Если такового в классе нет, будет брошено исключение InstantiationException. Это же исключение будет брошено, если объект Class соответствует абстрактному классу, интерфейсу, или какая-то другая причина помешала созданию нового объекта.

Каждому методу, полю, конструктору класса также соответствуют объекты, список которых можно получить вызовом соответствующих методов объекта Class: getMethods(), getFields(), getConstructors(), getDeclaredMethods() и т.д. В результате будут получены объекты, которые отвечают за поля, методы, конструкторы объекта. Их можно использовать для формирования динамических вызовов Java – этот механизм называется reflection. Необходимые классы содержатся в пакете java.lang.reflection.

Рассмотрим пример использования этой технологии:

Пример 13.3.

(html, txt)

Если запустить эту программу, на экран будет выведено следующее:

Пример 13.4.

(html, txt)

В этом примере делается попытка создать с помощью reflection три объекта. Имена классов, от которых они должны быть порождены, записаны в массив vehicleNames. Объект класса Automobile был успешно создан, причем, дальнейшая работа с ним велась через интерфейс Vehicle. Класс Truck был найден, но при попытке создания объекта было брошено, а затем обработано исключение java.lang.InstantiationException, поскольку конструктор без параметров отсутствует. Класс java.lang.Tank определен не был и поэтому при попытке получить соответствующий ему объект Class было выброшено исключение java.lang.ClassNotFoundException.


package demo.lang; interface Vehicle { void go(); } class Automobile implements Vehicle { public void go() { System.out.println("Automobile go!"); } } class Truck implements Vehicle { public Truck(int i) { super(); } public void go() { System.out.println("Truck go!"); } } public class VehicleStarter { public static void main(String[] args) { Vehicle vehicle; String[] vehicleNames = {"demo.lang.Automobile", "demo.lang.Truck", "demo.lang.Tank"}; for(int i=0; i<vehicleNames.length; i++) { try { String name = vehicleNames[i]; System.out.println("look for class for: " + name); Class aClass = Class.forName(name); System.out.println("creating vehicle..."); vehicle = (Vehicle)aClass.newInstance(); System.out.println("create vehicle: " + vehicle.getClass()); vehicle.go(); } catch(ClassNotFoundException e) { System.out.println("Exception: " + e); } catch(InstantiationException e) { System.out.println("Exception: " + e); } } } }

Пример 13.3.

Если запустить эту программу, на экран будет выведено следующее:

look for class for: demo.lang.Automobile creating vehicle... create vehicle: class demo.lang.Automobile Automobile go! look for class for: demo.lang.Truck creating vehicle... Instantiation exception: java.lang.InstantiationException look for class for: demo.lang.Tank Class not found: java.lang.ClassNotFoundException: demo.lang.Tank

Пример 13.4.

В этом примере делается попытка создать с помощью reflection три объекта. Имена классов, от которых они должны быть порождены, записаны в массив vehicleNames. Объект класса Automobile был успешно создан, причем, дальнейшая работа с ним велась через интерфейс Vehicle. Класс Truck был найден, но при попытке создания объекта было брошено, а затем обработано исключение java.lang.InstantiationException, поскольку конструктор без параметров отсутствует. Класс java.lang.Tank определен не был и поэтому при попытке получить соответствующий ему объект Class было выброшено исключение java.lang.ClassNotFoundException.


ClassLoader


Это абстрактный класс, ответственный за загрузку типов. По имени класса или интерфейса он находит и загружает в память данные, которые составляют определение типа. Обычно для этого используется простое правило: название типа преобразуется в название class-файла, из которого и считывается вся необходимая информация.

Каждый объект Class содержит ссылку на объект ClassLoader, с помощью которого он был загружен.

Для добавления альтернативного способа загрузки классов можно реализовать свой загрузчик, унаследовав его от ClassLoader. Например, описание класса может загружаться через сетевое соединение. Метод defineClass() преобразует массив байт в экземпляр класса Class. С помощью метода newInstance() могут быть получены экземпляры такого класса. В результате загруженный класс становится полноценной частью исполняемого Java-предложения.

Для иллюстрации приведем пример, как может выглядеть простая реализация загрузчика классов, использующего сетевое соединение:

class NetworkClassLoader extends ClassLoader { String host; int port; public NetworkClassLoader(String host, int port) { this.host = host; this.port = port; } public Class findClass(String className) { byte[] bytes = loadClassData(className); return defineClass(className, bytes, 0, bytes.length); } private byte[] loadClassData( String className) { byte[] result = null; // open connection, load the class data return result; } }

В этом примере только показано, что наследник загрузчика классов должен определить и реализовать методы findClass() и loadClassData() для загрузки описания класса. Когда описание получено, массив байт передается в метод defineClass() для создания экземпляра Class. Для простоты в примере приведен только шаблонный код, без реализации получения байт из сетевого соединения.

Для получения экземпляров классов, загруженных с помощью этого загрузчика, можно воспользоваться методом loadClass():

try { ClassLoader loader = new NetworkClassLoader(host, port); Object main = loader.loadClass( "Main").newInstance(); } catch(ClassNotFoundException e) { e.printStackTrace(); } catch(InstantiationException e) { e.printStackTrace(); } catch(IllegalAccessException e) { e.printStackTrace(); }

Если такой класс не будет найден, будет брошено исключение ClassNotFoundException, если класс будет найден, но произойдет какая-либо ошибка при создании объекта этого класса – будет брошено исключение InstantiationException, и, наконец, если у вызывающего потока не имеется соответствующих прав для создания экземпляров этого класса (что проверяется менеджером безопасности), будет брошено исключение IllegalAccessException.



Добавление изображений в объект класса MediaTracker


Далее метод init должен создать все необходимые объекты класса Image и добавить их в объект MediaTracker методом addImage. Ниже мы показали фрагмент кода, в котором выполняется добавление трех изображений:

Image img1; Image img2; Image img3; img1 = getImage(getCodeBase(), "pic1.gif"); img2 = getImage(getCodeBase(), "pic2.gif"); img3 = getImage(getCodeBase(), "pic3.gif"); mt.addImage(img1 , 0); mt.addImage(img2 , 0); mt.addImage(img3 , 0);

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



Другие методы класса MediaTracker


Какие другие полезные методы, кроме методов addImage и waitForAll есть в классе MediaTracker?

public boolean waitForAll(long ms);

Метод waitForAll с параметром ms позволяет выполнять ожидание в течение заданного времени. Время ожидания задается в миллисекундах. При этом если за указанное время все изображения были успешно загружены, метод waitForAll возвращает значение true, если нет - false.

Вариант метода checkAll с параметром load позволяет проверить, завершилась ли загрузка отслеживаемых изображений:

public boolean checkAll(boolean load);

Если значение параметра load равно true, метод инициирует загрузку изображений.

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

public boolean checkID(int id);

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

public boolean checkID(int id, boolean load);

Метод waitForID с параметрами id и ms позволяет выполнять ожидание загрузки группы изображений с заданным идентификатором в течении указанного периода времени:

public boolean waitForID(int id, long ms);

Класс MediaTracker предоставляет также возможность прослеживать сам процесс загрузки всех добавленных в него изображений или отдельных групп изображений с помощью методов statusAll и statusID:

public int statusAll(boolean load); public int statusID(int id, boolean load);

В зависимости от значения параметра load эти методы могут инициировать загрузку изображений. Если параметр равен true, загрузка изображений инициируется, если false - выполняется только проверка текущего состояния загрузки.

Методы statusAll и statusID возвращают значение, составленное из отдельных битов состояния при помощи логической операции ИЛИ. Ниже мы перечислили эти биты состояния и привели их краткое описание.

Биты состояния Описание
MediaTracker.LOADING Один или несколько отслеживаемых файлов продолжают загружаться
MediaTracker.ABORTED Загрузка одного или нескольких файлов была прервана
MediatTracker.ERRORED При загрузке одного или нескольких файлов произошла ошибка
MediaTracker.COMPLETE Загрузка всех отслеживаемых файлов произошла полностью и успешно

Еще четыре метода, определенных в классе MediaTracker, связаны с обработкой ошибок:

public boolean isErrorAny(); public boolean isErrorID(int id); public Object[] getErrorsAny(); public Object[] getErrorsID(int id);

Методы isErrorAny и isErrorID позволяют проверить, возникла ли ошибка при загрузке, соответственно, любого из отслеживаемых изображений или изображений из заданной группы. Если ошибка произошла, возвращается значение true, если нет - значение false.

Методы getErrorsAny и getErrorsID возвращают массив объектов, при ожидании загрузки которых произошла ошибка. Первый из этих методов возвращает массив для всех отслеживаемых объектов, второй - только объектов из заданной группы.



public int sideA; public int


package demo.lang; public class Rectangle { public int sideA; public int sideB; public Rectangle(int x, int y) { super(); sideA = x; sideB = y; } public boolean equals(Object obj) { if(!(obj instanceof Rectangle)) return false; Rectangle ref = (Rectangle)obj; return (((this.sideA==ref.sideA)&&(this.sideB==ref.sideB))|| (this.sideA==ref.sideB)&&(this.sideB==ref.sideA)); } public static void main(String[] args) { Rectangle r1 = new Rectangle(10,20); Rectangle r2 = new Rectangle(10,10); Rectangle r3 = new Rectangle(20,10); System.out.println("r1.equals(r1) == " + r1.equals(r1)); System.out.println("r1.equals(r2) == " + r1.equals(r2)); System.out.println("r1.equals(r3) == " + r1.equals(r3)); System.out.println("r2.equals(r3) == " + r2.equals(r3)); System.out.println("r1.equals(null) == " + r1.equals(null)); } }
Пример 13.1.
Закрыть окно


r1.equals(r1) == true r1.equals(r2) == false r1.equals(r3) == true r2.equals(r3) == false r1.equals(null) == false
Пример 13.2.
Закрыть окно


package demo.lang; interface Vehicle { void go(); } class Automobile implements Vehicle { public void go() { System.out.println("Automobile go!"); } } class Truck implements Vehicle { public Truck(int i) { super(); } public void go() { System.out.println("Truck go!"); } } public class VehicleStarter { public static void main(String[] args) { Vehicle vehicle; String[] vehicleNames = {"demo.lang.Automobile", "demo.lang.Truck", "demo.lang.Tank"}; for(int i=0; i<vehicleNames.length; i++) { try { String name = vehicleNames[i]; System.out.println("look for class for: " + name); Class aClass = Class.forName(name); System.out.println("creating vehicle..."); vehicle = (Vehicle)aClass.newInstance(); System.out.println("create vehicle: " + vehicle.getClass()); vehicle.go(); } catch(ClassNotFoundException e) { System.out.println("Exception: " + e); } catch(InstantiationException e) { System.out.println("Exception: " + e); } } } }
Пример 13.3.
Закрыть окно


look for class for: demo.lang.Automobile creating vehicle... create vehicle: class demo.lang. Automobile Automobile go! look for class for: demo.lang.Truck creating vehicle... Instantiation exception: java.lang.InstantiationException look for class for: demo.lang.Tank Class not found: java.lang.ClassNotFoundException: demo.lang.Tank
Пример 13.4.
Закрыть окно

Integer


Наиболее часто используемые статические методы:

public static int parseInt(String s) – преобразует строку, представляющую десятичную запись целого числа, в int;

public static int parseInt(String s, int radix) – преобразует строку, представляющую запись целого числа в системе счисления radix, в int.

Оба метода могут возбуждать исключение NumberFormatException, если строка, переданная на вход, содержит нецифровые символы.

Не следует путать эти методы с другой парой похожих методов:

public static Integer valueOf(String s) public static Integer valueOf(String s, int radix)

Данные методы выполняют аналогичную работу, только результат представляют в виде объекта-обертки.

Существует также два конструктора для создания экземпляров класса Integer:

Integer(String s) – конструктор, принимающий в качестве параметра строку, представляющую числовое значение.

Integer(int i) – конструктор, принимающий числовое значение.

public static String toString(int i) – используется для преобразования значения типа int в строку.

Далее перечислены методы, преобразующие int в строковое восьмеричное, двоичное и шестнадцатеричное представление:

pubic static String toOctalString(int i) – восьмеричное;

pubic static String toBinaryString(int i) – двоичное;

pubic static String toHexString(int i) – шестнадцатеричное.

Имеется также две статические константы:

Integer.MIN_VALUE – минимальное int значение;

Integer.MAX_VALUE – максимальное int значение.

Аналогичные константы, описывающие границы соответствующих типов, определены и для всех остальных классов-оберток числовых примитивных типов.

public int intValue() возвращает значение примитивного типа для данного объекта Integer. Классы-обертки остальных примитивных целочисленных типов – Byte, Short, Long – содержат аналогичные методы и константы (определенные для соответствующих типов: byte, short, long).

Рассмотрим пример:

public static void main(String[] args) { int i = 1; byte b = 1; String value = "1000"; Integer iObj = new Integer(i); Byte bObj = new Byte(b); System.out.println("while i==b is " + (i==b)); System.out.println("iObj.equals(bObj) is " + iObj.equals(bObj)); Long lObj = new Long(value); System.out.println("lObj = " + lObj.toString()); Long sum = new Long(lObj.longValue() + iObj.byteValue() + bObj.shortValue()); System.out.println("The sum = " + sum.doubleValue()); }

В данном примере произвольным образом используются различные варианты классов-оберток и их методов. В результате выполнения на экран будет выведено следующее:

while i==b is true iObj.equals(bObj) is false lObj = 1000 The sum = 1002.0

Оставшиеся классы-обертки числовых типов Float и Double, помимо описанного для целочисленных примитивных типов, дополнительно содержат определения следующих констант (они подробно разбирались в лекции 4):

NEGATIVE_INFINITY – отрицательная бесконечность;

POSITIVE_INFINITY – положительная бесконечность;

NaN – нечисловое значение.

Кроме того, другой смысл имеет значение MIN_VALUE – вместо наименьшего значения оно представляет минимальное положительное (строго > 0) значение, которое может быть представлено этим примитивным типом.

Кроме классов-оберток для примитивных числовых типов, таковые определены и для остальных примитивных типов Java.



Исходные тексты приложения


Главный файл исходных текстов приложения CDRotation представлен в листинге 1.

Листинг 1. Файл CDRotation.java

import java.applet.*; import java.awt.*;

public class CDRotation extends Applet implements Runnable { Thread m_CDRotation = null; private Graphics m_Graphics; private Image m_Images[]; private int m_nCurrImage; private int m_nImgWidth = 0; private int m_nImgHeight = 0; private boolean m_fAllLoaded = false; private final int NUM_IMAGES = 11;

public String getAppletInfo() { return "Name: CDRotation"; }

private void displayImage(Graphics g) { if (!m_fAllLoaded) return;

g.drawImage(m_Images[m_nCurrImage], (size().width - m_nImgWidth) / 2, (size().height - m_nImgHeight) / 2, null);

g.drawString( (new Integer(m_nCurrImage)).toString(), (size().width - m_nImgWidth) /2, ((size().height - m_nImgHeight)/2)+ 10); }

public void paint(Graphics g) { Dimension dimAppWndDimension = size(); g.setColor(Color.white); g.fillRect(0, 0, dimAppWndDimension.width - 1, dimAppWndDimension.height - 1); g.setColor(Color.black); g.drawRect(0, 0, dimAppWndDimension.width - 1, dimAppWndDimension.height - 1);

if (m_fAllLoaded) { displayImage(g); }

else g.drawString("Please, wait...", 10, dimAppWndDimension.height / 2); }

public void start() { if (m_CDRotation == null) { m_CDRotation = new Thread(this); m_CDRotation.start(); } }

public void stop() { if (m_CDRotation != null) { m_CDRotation.stop(); m_CDRotation = null; } }

public void run() { m_nCurrImage = 0;

if (!m_fAllLoaded) { repaint(); m_Graphics = getGraphics();

m_Images = new Image[NUM_IMAGES];

MediaTracker tracker = new MediaTracker(this);

String strImage;

for (int i = 0; i < NUM_IMAGES; i++) { strImage = "images/cdimg0" + ((i < 10) ? "0" : "") + i + ".gif";

m_Images[i] = getImage( getDocumentBase(), strImage);

tracker.addImage(m_Images[i], 0); }

try { tracker.waitForAll();

m_fAllLoaded = !tracker.isErrorAny(); } catch (InterruptedException e) { }



Исключения


Подробно механизм использования исключений описан в лекции 10. Здесь остановимся только на том, что базовым классом для всех исключений является класс Throwable. Любой класс, который планируется использовать как исключение, должен явным или неявным образом наследоваться от него. Класс Throwable, а также наиболее значимые его наследники – классы Error, Exception, RuntimeException, – содержатся именно в пакете java.lang.



Класс Image


Назад Вперед

Процесс рисования растрового изображения в окне аплета предельно прост - вам достаточно загрузить изображение методом getImage и затем нарисовать его методом drawImage.

Но не забывайте, что метод getImage в действительности только создает объект класса Image, но не загружает его. Давайте посмотрим на класс Image.

В этом классе имеется единственный конструктор без параметров:

public Image();

Вы, однако, скорее всего будете создавать объекты класса Image при помощи метода getImage.

Методы getHeight и getWidth, определенные в классе Image, позволяют определить, соответственно, высоту и ширину изображения:

public abstract int getHeight( ImageObserver observer); public abstract int getWidth( ImageObserver observer);

Так как при вызове этих методов изображение еще может быть не загружено, в качестве параметров методам передается ссылка на объект ImageObserver. Этот объект получит извещение, когда будет доступна высота или ширина изображения.

Метод getGraphics позволяет получить так называемый внеэкранный контекст отображения для рисования изображения не в окне аплета, а в оперативной памяти:

public abstract Graphics getGraphics();

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

Еще один метод класса Image, который мы рассмотрим, называется flush:

public abstract void flush();

Он освобождает ресурсы, занятые изображением.

Назад Вперед



Контакты

О компании

Новости

Вакансии

Правовые аспекты

Условия использования

Торговые марки

Copyright 1994-2005 Sun Microsystems, Inc.

printmenus();

Программные продукты

Рабочие станции и тонкие клиенты

Серверы

Системы хранения данных

Посмотреть все

»

  

Solaris 10

Java 2 Standard Edition

Developer Tools

Top Downloads

New Downloads

Патчи и обновления

Посмотреть все

»

  

Каталог решений

Истории успеха

The Sun Grid

Партнерские программы

Посмотреть все

»

  

Гарантийное обслуживание


Программы SunSpectrum

Консалтинг

Услуги инсталляции

Поддержка ПО

Посмотреть все
»

  
Описание курсов

Сертификация

Авторизованные учебные центры

Посмотреть все
»

  
Проекты

События

Lab Downloads

Посмотреть все
»

  



Классы-обертки


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

Для этих целей и предназначены так называемые классы-обертки. Для каждого примитивного типа Java существует свой класс-обертка. Такой класс является неизменяемым (если необходим объект, хранящий другое значение, его нужно создать заново), к тому же имеет атрибут final – от него нельзя наследовать класс. Все классы-обертки (кроме Void) реализуют интерфейс Serializable, поэтому объекты любого (кроме Void) класса-обертки могут быть сериализованы. Все классы-обертки содержат статическое поле TYPE, ссылающееся на объект Class, соответствующий примитивному оборачиваемому типу.

Также классы-обертки содержат статические методы для обеспечения удобного манипулирования соответствующими примитивными типами, например, преобразование к строковому виду.

В таблице 13.1 приведены примитивные типы и соответствующие им классы-обертки.

Таблица 13.1. Примитивные типы и соответствующие им классы-обертки.

Класс-оберткаПримитивный тип
Bytebyte
Shortshort
Characterchar
Integerint
Longlong
Floatfloat
Doubledouble
Booleanboolean

При этом классы-обертки числовых типов Byte, Short, Integer, Long, Float, Double наследуются от одного класса – Number. В нем объявлены методы, возвращающие числовое значение во всех числовых форматах Java (byte, short, int, long, float и double).

Все классы-обертки реализуют интерфейс Comparable. Все классы-обертки числовых типов имеют метод equals(Object), сравнивающий примитивные значения объектов.

Рассмотрим более подробно некоторые из классов-оберток.



Math


Класс Math состоит из набора статических методов, производящих наиболее популярные математические вычисления, и двух констант, имеющих особое значение в математике, – это число Пи и основание натурального логарифма. Часто этот класс еще называют классом-утилитой (Utility class). Так как все методы класса статические, нет необходимости создавать экземпляр данного класса, потому он и не имеет открытого конструктора. Нельзя также и наследоваться от этого класса, так как он объявлен с модификатором final.

Итак, константы определены следующим образом:

public static final double Math.PI – задает число ? ("пи");

public static final double Math.E – основание натурального логарифма.

В таблице 13.2 приведены все методы класса и дано их краткое описание.

Таблица 13.2. Методы класса Math и их краткое описание.

Возвращаемое значениеИмя метода и параметрыОписание

abs(… a)

абсолютное значение (модуль) для типов double, float, int, long

double

acos(double a)

арккосинус

double

asin(double a)

арксинус

double

atan(double a)

арктангенс

double

ceil(double a)

наименьшее целое число, большее a

double

floor(double a)

целое число, меньшее a

double

IEEEremainder (double a, double b)

остаток по стандарту IEEE 754 (подробно рассматривался в лекции 3)

double

sin(double a)

синус (здесь и далее: аргумент должен быть в радианах)

double

cos(double a)

косинус

double

tan(double a)

тангенс

double

exp(double a)

e в степени a

double

log(double a)

натуральный логарифм a

max(… a, … b)

большее из двух чисел (для типов double, float, long, int)

min(… a, … b)

меньшее из двух чисел (для типов double, float, long, int)

double

pow(double a, double b)

a в степени b

double

random()

случайное число от 0.0 до 1.0

double

rint(double a)

значение int, ближайшее к a

round(… a)

значение long для double (int для float), ближайшее к a

double

sqrt(double a)

квадратный корень числа a

double

toDegrees(double a)

преобразование из радианов в градусы

double

toRadians(double a)

преобразование из градусов в радианы



Метод displayImage


Метод displayImage вызывается из двух мест - из метода paint при перерисовке окна аплета и из метода run (периодически).

Если кадры видеофильма не загружены, содержимое флага m_fAllLoaded равно false и метод displayImage просто возвращает управление, ничего не делая:

if(!m_fAllLoaded) return;

Если же загрузка изображений завершена, этот метод рисует в центре окна текущий кадр видеофильма, вызывая для этого знакомый вам метод drawImage:

g.drawImage(m_Images[m_nCurrImage], (size().width - m_nImgWidth) / 2, (size().height - m_nImgHeight) / 2, null);

После того как кадр нарисован, мы надписываем на нем его порядковый номер, вызывая для этого метод drawString:

g.drawString((new Integer( m_nCurrImage)).toString(), (size().width - m_nImgWidth) / 2, ((size().height - m_nImgHeight) / 2) + 10);

Назад Вперед



Контакты

О компании

Новости

Вакансии

Правовые аспекты

Условия использования

Торговые марки

Copyright 1994-2005 Sun Microsystems, Inc.

printmenus();

Программные продукты

Рабочие станции и тонкие клиенты

Серверы

Системы хранения данных

Посмотреть все

»

  

Solaris 10

Java 2 Standard Edition

Developer Tools

Top Downloads

New Downloads

Патчи и обновления

Посмотреть все

»

  

Каталог решений

Истории успеха

The Sun Grid

Партнерские программы

Посмотреть все

»

  

Гарантийное обслуживание

Программы SunSpectrum

Консалтинг

Услуги инсталляции

Поддержка ПО

Посмотреть все

»

  

Описание курсов

Сертификация

Авторизованные учебные центры

Посмотреть все

»

  

Проекты

События

Lab Downloads

Посмотреть все

»

  



Метод imageUpdate


public abstract boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height);

Как видите, в интерфейсе ImageObserver определен единственный метод imageUpdate и набор битовых флагов для этого метода.

Класс Component, от которого происходит класс Applet, реализует интерфейс ImageObserver:

public abstract class java.awt.Component extends java.lang.Object implements java.awt.image.ImageObserver { . . . }

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

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

Процедура ожидания загрузки изображений достаточно проста.

Прежде всего, аплет должен передать в последнем параметре методу drawImage ссылку на интерфейс ImageObserver, который будет применяться для отслеживания процесса загрузки:

g.drawImage(Img, x, y, width, height, this);

Здесь в качестве ссылки на интерфейс ImageObserver мы передали значение this. При этом будет применен интерфейс нашего аплета. Соответственно, нам нужно определить в классе аплета метод imageUpdate, который будет вызываться в процессе загрузки изображений.

Ниже мы привели возможный вариант реализации этого метода:

public boolean imageUpdate( Image img, int flags, int x, int y, int w, int h) { // Проверяем, все ли // биты изображения загружены fAllLoaded = ((flags & ALLBITS) != 0);

// Если все, перерисовываем окно if(fAllLoaded) repaint();

// Если все биты загружены, // дальнейшие вызовы // метода imageUpdate не нужны return !fAllLoaded; }

Через первый параметр img методу imageUpdate передается ссылка на изображение, загрузка которого отслеживается.

Параметр flags отражает состояние процесса загрузки.

Через остальные параметры x, y, w и h передаются, соответственно, координаты и размеры изображения.


Основное, что должен делать метод imageUpdate для отслеживания процесса загрузки - это проверять флаги flags, дожидаясь установки нужных флагов.

Флаги определены следующим образом:

public final static int WIDTH; public final static int HEIGHT = 2; public final static int PROPERTIES = 4; public final static int SOMEBITS = 8; public final static int FRAMEBITS = 16; public final static int ALLBITS = 32; public final static int ERROR = 64; public final static int ABORT = 128;

Ниже мы привели краткое описание перечисленных флагов.

Флаг Описание
WIDTH Изображение загружено настолько, что стала доступна его ширина. Значение ширины изображения можно получить из параметра w метода imageUpdate
HEIGHT Аналогично предыдущему, но для высоты изображения. Высоту изображения можно получить из параметра h метода imageUpdateimageUpdate
PROPERTIES Стали доступны свойства изображения, которые можно получить методом getProperty класса Image. В нашей книге мы опустили описание этого метода
SOMEBITS Стали доступны биты изображения для рисования в масштабе. Через параметры x, y, h и w передаются координаты и размеры прямоугольной области, которая ограничивает загруженную часть изображения
FRAMEBITS Загружен очередной фрейм изображения, состоящего из нескольких фреймов. Параметры x, y, h и w следует игнорировать
ALLBITS Изображение загружено полностью. Параметры x, y, h и w следует игнорировать
ERROR При загрузке произошла ошибка
ABORT Загрузка изображения была прервана или отменена
Анализируя состояние флагов, метод imageUpdate может следить за ходом загрузки изображений, отображая, например, процент завершения процесса загрузки или выполняя какие-либо другие действия.

Если вам нужно только дождаться завершения процесса загрузки, достаточно использовать флаг ALLBITS. Для проверки ошибок воспользуйтесь флагами ERROR и ABORT.

Назад Вперед


Контакты

О компании

Новости

Вакансии

Правовые аспекты

Условия использования

Торговые марки

Copyright 1994-2005 Sun Microsystems, Inc.





printmenus();

Программные продукты

Рабочие станции и тонкие клиенты

Серверы

Системы хранения данных

Посмотреть все
»

  
Solaris 10

Java 2 Standard Edition

Developer Tools

Top Downloads

New Downloads

Патчи и обновления

Посмотреть все
»

  
Каталог решений

Истории успеха

The Sun Grid

Партнерские программы

Посмотреть все
»

  
Гарантийное обслуживание

Программы SunSpectrum

Консалтинг

Услуги инсталляции

Поддержка ПО

Посмотреть все
»

  
Описание курсов

Сертификация

Авторизованные учебные центры

Посмотреть все
»

  
Проекты

События

Lab Downloads

Посмотреть все
»

  



Метод paint


Сразу после получения управления, метод paint закрашивает окно аплета белым цветом и рисует вокруг него черную рамку.

Затем метод проверяет содержимое флага m_fAllLoaded. Этот флаг установлен в значение true, когда все кадры видеофильма загружены и сброшен в значение false, когда загрузка кадров еще не завершена. Последняя ситуация возникает всегда при первом вызове метода paint.

Если все изображения загружены, метод paint вызывает метод displayImage, определенный в нашем приложении:

if(m_fAllLoaded) { displayImage(g); }

Этот метод, о котором мы еще расскажем подробнее, отображает в окне аплета текущий кадр видеофильма.

Если же кадры видеофильма еще не загружены, в окне аплета отображается соответствующее сообщение:

else g.drawString("Please, wait...", 10, dimAppWndDimension.height / 2);



Метод run


Метод run работает в рамках отдельного потока. Он занимается последовательным рисованием кадров нашего видеофильма.

Прежде всего метод run записывает нулевое значение в поле m_nCurrImage, хранящее номер текущего отображаемого кадра:

m_nCurrImage = 0;

Далее выполняется проверка, загружены ли все кадры видеофильма, для чего анализируется содержимое флага m_fAllLoaded.

Если изображения не загружены (а в самом начале так оно и есть) метод run перерисовывает окно аплета и получает контекст отображения для этого окна. Затем создается массив объектов Image для хранения кадров видеофильма:

m_Images = new Image[NUM_IMAGES];

Метод run создает также объект класса MediaTracker для ожидания загрузки всех кадров видеофильма:

MediaTracker tracker = new MediaTracker(this);

Далее метод run в цикле загружает изображения и добавляет их в объект класса MediaTracker для того чтобы можно было дождаться загрузки всех кадров:

for (int i = 0; i < NUM_IMAGES; i++) { strImage = "images/cdimg0" + ((i < 10) ? "0" : "") + i + ".gif"; m_Images[i] = getImage( getDocumentBase(), strImage); tracker.addImage(m_Images[i], 0); }

Здесь предполагается, что файлы изображений находятся в каталоге images, который, в свою очередь, размещен там же, где и двоичный файл аплета.

Имена файлов, составляющих отдельные кадры, начинаются с префикса cdimg0, вслед за которым идет номер кадра (00, 01, 02, и так далее), и расширение имени .gif.

Ожидание загрузки кадров выполняется с помощью метода waitForAll, о котором мы вам уже рассказывали:

try { tracker.waitForAll(); m_fAllLoaded = !tracker.isErrorAny(); } catch (InterruptedException e) { }

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

Если же произошла ошибка, в окне аплета отображается соответствующее сообщение, после чего работа метода run (и, следовательно, работа созданного для него потока) заканчивается:



Метод start


В задачу метода start, который получает управление при отображении окна аплета, входит создание и запуск потока, отображающего кадры видеофильма с изображением вращающегося компакт-диска:

if (m_CDRotation == null) { m_CDRotation = new Thread(this); m_CDRotation.start(); }

Поток создается как объект класса Thread, причем конструктору передается ссылка на главный класс аплета. Поэтому при запуске потока управление получит метод run, определенный в классе аплета.



Object


Класс Object является базовым для всех остальных классов. Он определяет методы, которые поддерживаются любым классом в Java.

Метод public final native Class getClass() возвращает объект типа Class, соответствующий классу объекта. Этот метод уже рассматривался в лекции 4.

Метод public boolean equals(Object obj) определяет, являются ли объекты одинаковыми. Если оператор == проверяет равенство по ссылке (указывают на один и тот же объект), то метод equals() – равенство по значению (состояния объектов одинаковы). Поскольку класс Object не содержит полей, реализация в нем этого метода такова, что значение true будет возвращено только в случае равенства по ссылке, то есть:

public boolean equals(Object obj) { return (this == obj); }

В классах-наследниках этот метод при необходимости может быть переопределен, чтобы поддержать расширенное состояние объекта (например, если добавилось поле, характеризующее состояние). Рассмотрим сравнение объектов-оберток целых чисел (класс Integer). Оно должно по всей логике возвращать значение true, если равны значения int чисел, которые обернуты, даже если это два различных объекта.

Метод equals() может быть переопределен любым способом (например, всегда возвращать false, или, наоборот, true) – компилятор, конечно же, не будет проводить анализ реализации и давать рекомендации. Однако существуют соглашения, которые необходимо соблюдать, чтобы программа имела предсказуемое поведение, в том числе и с точки зрения других программистов:

рефлексивность: для любой объектной ссылки x, отличной от null, вызов x.equals(x) возвращает true;симметричность: для любых объектных ссылок x и y, вызов x.equals(y) возвращает true только в том случае, если вызов y.equals(x) возвращает true;транзитивность: для любых объектных ссылок x, y и z, если x.equals(y) возвращает true и y.equals(z) возвращает true, то вызов x.equals(z) должен вернуть true;непротиворечивость: для любых объектных ссылок x и y многократные последовательные вызовы x.equals(y) возвращают одно и то же значение (либо всегда true, либо всегда false);для любой не равной null объектной ссылки x вызов x.equals(null) должен вернуть значение false.


Пример:

Пример 13.1.

(html, txt)

Запуск этой программы, очевидно, приведет к выводу на экран следующего:

Пример 13.2.

(html, txt)

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

Большинство стандартных классов переопределяет этот метод, строго следуя всем соглашениям.

Метод public int hashCode() возвращает хеш-код (hash code) для объекта. Хеш-код – это целое число, которое сопоставляется с данным объектом. Оно позволяет организовать хранение набора объектов с возможностью быстрой выборки (стандартная реализация такого механизма присутствует в Java и будет описана в следующей лекции).

Для этого метода также принят ряд соглашений, которым стоит следовать при переопределении:

если два объекта идентичны, то есть вызов метода equals(Object) возвращает true, то вызов метода hashCode() у каждого из этих двух объектов должен возвращать одно и то же значение;во время одного запуска программы для одного объекта при вызове метода hashCode() должно возвращаться одно и то же значение, если между этими вызовами не были затронуты данные, используемые для проверки объектов на идентичность в методе equals(). Это число не обязательно должно быть одним и тем же при повторном запуске той же программы, даже если все данные будут идентичны.

В классе Object этот метод реализован на уровне JVM. Сама виртуальная машина генерирует хеш-код, основываясь на расположении объекта в памяти. Это позволяет для различных объектов (неравенство по ссылке) получать различные хеш-коды.

В силу первого соглашения при переопределении метода equals() необходимо переопределить также метод hashCode(). При этом нужно стремиться, во-первых, к тому, чтобы метод возвращал значение как можно быстрее, иначе основная цель – быстрая выборка – не будет достигнута. Во-вторых, желательно для различных объектов, то есть когда метод equals(Object) возвращает false, генерировать различные хеш-коды. В этом случае хеш-таблицы будут работать особенно эффективно. Однако, понятно, что это не всегда возможно. Диапазон значений int – 232, а количество различных строк, или двумерных точек, с координатами типа int – заведомо больше.

Большинство стандартных классов переопределяет этот метод, строго следуя всем соглашениям.

Метод public String toString() возвращает строковое представление объекта. В классе Object этот метод реализован следующим образом:



public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }

То есть возвращает строку, содержащую название класса объекта и его хеш-код в шестнадцатеричном формате.

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

package demo.lang; public class Book { private String title; private String author; private int pagesNumber; public Book(String title, String author, int pagesNumber) { super(); this.title = title; this.author = author; this.pagesNumber = pagesNumber; } public static void main(String[] args) { Book book = new Book("Java2","Sun",1000); System.out.println("object is: " + book); } public String toString(){ return "Book: " + title + " ( " + author + ", " + pagesNumber + " pages )"; } }

При запуске этой программы на экран будет выведено следующее:

object is: Book: Java2 ( Sun, 1000 pages )

Большинство стандартных классов переопределяет этот метод. Экземпляры класса String возвращают ссылку на самих себя (this).

Метод wait(), notify(), notifyAll() используются для поддержки многопоточности и были подробно рассмотрены в лекции 12. Они определены с атрибутом final и не могут быть переопределены в классах-наследниках.

Метод protected void finalize() throws Throwable вызывается Java-машиной перед тем, как garbage collector (сборщик мусора) освободит память, занимаемую объектом. Этот метод уже подробно рассматривался в лекции 4.

Метод protected native Object clone() throws CloneNotSupportedException создает копию объекта. Механизм клонирования подробно рассматривался в лекции 9.


Описание исходных текстов


Рассмотрим наиболее важные методы нашего аплета.



Ожидание загрузки добавленных изображений


Для того чтобы убедиться, что все изображения загружены, вы можете воспользоваться методом waitForAll. Этот метод инициирует загрузку изображений, а также задержит выполнение вызвавшего потока до момента полной загрузки всех изображений, добавленных в объект класса MediaTracker:

try { mt.waitForAll(); } catch (InterruptedException ex) { }

Обратите внимание, что метод waitForAll может создавать исключение InterruptedException. Это исключение возникает, если по какой-либо причине процесс ожидания прерывается.

Чаще всего рисование выполняется в отдельном потоке, поэтому метод waitForAll должен вызываться в начале соответствующего метода run. Ниже мы привели исходные тексты приложения ImageDrawWait, в котором такое ожидание выполняется в методе paint, что приводит, однако, к блокировке работы аплета до момента загрузки всех изображений. В данном случае это не критично, так как кроме рисования изображений наш аплет ничего не делает, однако более предпочтительным является выполнение длительных процессов в отдельном потоке.



Ожидание загрузки изображений


Назад Вперед

Как мы уже говорили в наших предыдущих статьях, загрузка изображений из сети Internet - длительный процесс, который в среднем идет со скоростью 1 Кбайт в секунду. Поэтому изображения загружаются навигатором в отдельной задаче. При этом метод getImage только создает объект класса Image, а метод drawImage инициирует загрузку изображения и рисует его. Причем если файл изображения имеет большую длину, он будет появляться в окне аплета постепенно по мере загрузки.

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

Есть ли способ определить, когда изображение будет загружено полностью?

Есть, и причем целых два. Один из них связан с использованием класса MediaTracker, специально предназначенного для этой цели и достаточно удобного в использовании, другой основан на переопределении одного из методов интерфейса ImageObserver.



Потоки исполнения


Многопоточная архитектура в Java была подробно рассмотрена в лекции 12. Остановимся более подробно на методах применяемых классов.



Применение интерфейса ImageObserver


Второй способ ожидания завершения процесса загрузки изображений связан с интерфейсом ImageObserver:



Применение класса MediaTracker


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

Как это сделать?

Обычно метод init аплета создает объект класса MediaTracker с помощью конструктора и добавляет в него все изображения, загрузки которых необходимо дождаться.



Process


Объекты этого класса получаются вызовом метода exec() у объекта Runtime, запускающего отдельный процесс. Объект класса Process может использоваться для управления процессом и получения информации о нем.

Process – абстрактный класс, определяющий, какие методы должны присутствовать в реализациях для конкретных платформ. Объекты класса Process:

public InputStream getInputStream() – дает возможность получать поток ввода процесса;

getErrorStream(), getOutputStream() – методы, аналогичные getInputStream(), но получающие, соответственно, стандартные потоки сообщений об ошибках и вывода;

public void destroy() – уничтожает процесс; все подпроцессы, запущенные из него, также будут уничтожены;

public int exitValue() – возвращает код завершения процесса; по соглашению, код завершения, равный 0, означает нормальное завершение;

public int waitFor() – вынуждает текущий поток выполнения приостановиться до тех пор, пока не будет завершен процесс, представленный этим экземпляром Process; возвращает значение кода завершения процесса.

Даже если в приложении Java не будет ни одной ссылки на объект Process, процесс не будет уничтожен и будет продолжать асинхронно выполняться до своего завершения. Спецификацией не оговаривается механизм, с помощью которого будет выделяться процессорное время на выполнение процессов Process и потоков Java. Поэтому при проектировании программ не стоит полагаться ни на какой из них, так как различные Java-машины могут демонстрировать различное поведение.



Растровые изображения и анимация


Назад Вперед

Одно из наиболее распространенный применений аплетов связано с рисованием простых или анимированных растровых изображений. На серверах Web изображения обычно хранятся в форматах GIF или JPEG. Оба эти формата обеспечивают сжатие изображения, что весьма актуально из-за невысокой скорости передачи данных в сети Internet.

Рисование растровых изображений в приложениях для операционной системы Windows, составленных на языке программирования С - непростая задача. В классическом программном интерфейсе этой операционной системы отсутствуют функции, с помощью которых можно было бы непосредственно рисовать содержимое файлов с растровыми изображениями. Программист вынужден работать с заголовками таких файлов, выделять таблицу цветов и биты изображений, создавать и реализовывать палитру, заниматься восстановлением сжатых данных и так далее.

Разработчик приложений Java находится в намного лучшем положении, так как библиотеки классов Java содержат простые в использовании и мощные средства, предназначенные для работы с растровыми изображениями. В этой статье мы научим вас рисовать в окне аплета содержимое файлов GIF и JPEG, выполняя при необходимости масштабирование, а также создавать на базе таких файлов анимационные изображения, показывая по очереди отдельные кадры небольшого видеофильма.

Назад Вперед



Контакты

О компании

Новости

Вакансии

Правовые аспекты

Условия использования

Торговые марки

Copyright 1994-2005 Sun Microsystems, Inc.

printmenus();

Программные продукты

Рабочие станции и тонкие клиенты

Серверы

Системы хранения данных

Посмотреть все

»

  

Solaris 10

Java 2 Standard Edition

Developer Tools

Top Downloads

New Downloads

Патчи и обновления

Посмотреть все

»

  

Каталог решений

Истории успеха

The Sun Grid

Партнерские программы

Посмотреть все

»

  

Гарантийное обслуживание

Программы SunSpectrum

Консалтинг

Услуги инсталляции

Поддержка ПО

Посмотреть все

»

  

Описание курсов


Сертификация

Авторизованные учебные центры

Посмотреть все
»

  
Проекты

События

Lab Downloads

Посмотреть все
»

  



Runnable


Runnable – это интерфейс, содержащий один-единственный метод без параметров: run().



Runtime


Во время исполнения приложению Java сопоставляется экземпляр класса Runtime. Этот объект позволяет взаимодействовать с окружением, в котором запущена Java-программа. Получить его можно с помощью статического метода Runtime.getRuntime().

Объект этого класса:

public void exit(int status) – осуществляет завершение программы с кодом завершения status (при использовании этого метода особое внимание нужно уделить обработке исключений – выход будет осуществлен моментально и в конструкциях try-catch-finally управление в finally передано не будет);

public native void gc() – сигнализирует сборщику мусора о необходимости запуска;

public void runFinalization() – производит запуск выполнения методов finalize() у всех объектов, этого ожидающих;

public native long freeMemory() – возвращает количество свободной памяти, доступной приложению JVM. В некоторых случаях это количество может быть увеличено, если вызвать у объекта Runtime метод gc();

public native long totalMemory() – возвращает суммарное количество памяти, выделенное Java-машине. Это количество может изменяться даже в течение одного запуска, что зависит от реализации платформы, на которой запущена Java-машина. Также не стоит закладываться на объем памяти, занимаемой одним определенным объектом, – эта величина тоже зависит от реализации Java-машины;

public void loadLibrary(String libname) – загружает библиотеку с указанным именем.

Обычно загрузка библиотек производится следующим образом: в классе, использующем native реализации методов, добавляется статический инициализатор, например:

static { System.loadLibrary("LibFile"); }

Таким образом, когда класс будет загружен и инициализирован, необходимый код для реализации native методов также будет загружен. Если будет произведено несколько вызовов загрузки библиотеки с одним и тем же именем, произведен будет только первый, а все остальные будут проигнорированы.

public void load(String filename) – подгружает файл с указанным названием в качестве библиотеки. В принципе, этот метод работает так же, как и метод loadLibrary(), только принимает в качестве параметра именно название файла, а не библиотеки, тем самым позволяя загрузить любой файл с native кодом;

public Process exec(String command) – в отдельном процессе запускает команду, представленную переданной строкой. Возвращаемый объект Process может быть использован для взаимодействия с этим процессом.



SecurityManager – менеджер безопасности


С помощью методов этого класса приложения перед выполнением потенциально опасных операций проверяют, является ли операция допустимой в данном контексте.

Класс SecurityManager содержит много методов с именами, начинающимися с приставки check ("проверить"). Эти методы вызываются из стандартных классов библиотек Java перед тем, как в них будут выполнены потенциально опасные операции. Типичный вызов выглядит примерно следующим образом:

SecurityManager security = System.getSecurityManager(); if(security != null){ security.checkX(…); }

где X – название потенциально опасной операции: Access, Read, Write, Connect, Delete, Exec, Listen и т.д.

Предотвращение вызова производится путем бросания исключения – SecurityException, если вызов операции не разрешен (кроме метода checkTopLevelWindow, который возвращает boolean значение).

Для установки менеджера безопасности в качестве текущего вызывается метод setSecurityManager() в классе System. Соответственно, для его получения нужно вызвать метод getSecurityManager().

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



Системные классы


Следующие классы, которые будут рассмотрены, обеспечивают взаимодействие с внутренними механизмами JVM и средой исполнения приложения:

ClassLoader – загрузчик классов; отвечает за загрузку описания классов в память JVM;

SecurityManager – менеджер безопасности; содержит различные методы проверки допустимости запрашиваемой операции;

System – содержит набор полезных статических полей и методов;

Runtime – позволяет приложению взаимодействовать со средой исполнения;

Process – представляет интерфейс для взаимодействия с внешней программой, запущенной при помощи Runtime.



Создание объекта класса MediaTracker


Объект класса MediaTracker создается следующим образом:

MediaTracker mt; mt = new MediaTracker(this);

Конструктору класса MediaTracker передается ссылка на компонент, для которого необходимо отслеживать загрузку изображений. В данном случае это наш аплет, поэтому мы передаем конструктору значение this.



String


Этот класс используется в Java для представления строк. Он обладает свойством неизменяемости. После того как создан экземпляр этого класса, его содержимое уже не может быть модифицировано.

Существует много способов создать объект String. Наиболее простой, если содержимое строки известно на этапе компиляции, – написать текст в кавычках:

String abc = "abc";

Можно использовать и различные варианты конструктора. Наиболее простой из них – конструктор, получающий на входе строковый литерал.

String s = new String("immutable");

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

public class Test { public Test() { }

public static void main(String[] args) { Test t = new Test(); String s1 = "Hello world !!!"; String s2 = "Hello world !!!"; System.out.println("String`s equally = " + (s1.equals(s2))); System.out.println( "Strings are the same = " + (s1==s2)); } }

В результате на консоль будет выведено:

String`s equally = true Strings are the same = true

Теперь несколько модифицируем код:

public class Test { public Test() { } public static void main(String[] args) { Test t = new Test(); String s1 = "Hello world !!!"; String s2 = new String("Hello world !!!"); System.out.println("String`s equally = " + (s1.equals(s2))); System.out.println( "Strings are the same = " + (s1==s2)); } }

В результате на консоль будет выведено:

String`s equally = true Strings are the same = false

Почему результат изменился? Дело в том, что создание нового объекта – это одна из самых трудоемких процедур в Java. Поэтому компилятор стремится уменьшить их количество, если это не приводит к непредсказуемому поведению программы.

В примере объявляются две переменных, которые инициализируются одинаковым значением. Поскольку класс String неизменяемый, их значения всегда будут одинаковыми. Это позволяет компилятору завести скрытую вспомогательную текстовую переменную, которая будет хранить такое значение, а все остальные переменные будут ссылаться на него же, а не порождать новые объекты. В результате в первом варианте программы создается лишь один объект String. Для большинства операций это несущественная разница. Исключение составляют действия, которые привязаны к конкретному объекту, а не к его значению. Это метод equals, методы wait/notify.

Во втором варианте указано динамическое обращение к конструктору. В этом случае компилятор уже не имеет возможности заниматься оптимизацией и JVM во время исполнения программы действительно создаст второй объект с точно таким же значением. Что мы и видим по результату выполнения примера.

В Java для строк определен оператор +. При использовании этого оператора производится конкатенация строк. В классе String также определен метод:


public String concat(String s);

Он возвращает новый объект-строку, дополненный справа строкой s.

Рассмотрим другой пример.

public class Test { public static void main(String[] args) { Test t = new Test(); String s = " prefix !"; System.out.println(s); s = s.trim(); System.out.println(s); s = s.concat(" suffix"); System.out.println(s); } }

prefix ! prefix ! prefix ! suffix

В данном случае может сложиться впечатление, что строку (объект String, на который ссылается переменная s), можно изменять. В действительности это не так. В результате выполнения методов trim (отсечение пробелов в начале и конце строки) и concat создаются новые объекты-строки и ссылка s начинает указывать на новый объект-строку. Таким образом, меняется значение ссылки, объекты же неизменяемы.

Как уже отмечалось, строка состоит из двухбайтных Unicode-символов. Однако во многих случаях требуется работать со строкой как с набором байт (ввод/вывод, работа с базой данных и т.д.). Преобразование строки в последовательность байтов производится следующими методами:



byte[] getBytes() – возвращает последовательность байтов в кодировке, принятой по умолчанию (как правило, зависит от настроек операционной системы);

byte[] getBytes(String encoding) – возвращает последовательность байтов в указанной кодировке encoding.

Для выполнения обратной операции (преобразования байтов в строку) необходимо сконструировать новый объект-строку с помощью следующих методов:



String(byte[] bytes) – создает строку из последовательности байтов в кодировке, принятой по умолчанию;

String(byte[] bytes, String enc) – создает строку из последовательности байтов в указанной кодировке.


StringBuffer


Этот класс используется для создания и модификации строковых выражений, которые после можно превратить в String. Он реализован на основе массива char[], что позволяет, в отличие от String, модифицировать его значение после создания объекта.

Рассмотрим наиболее часто используемые конструкторы класса StringBuffer:

StringBuffer() – создает пустой StringBuffer;

StringBuffer(String s) – буфер заполняется указанным значением s;

StringBuffer(int capacity) – создает экземпляр класса StringBuffer с указанным размером (длина char[]). Задание размера не означает, что нельзя будет оперировать строками с большей длинной, чем указано в конструкторе. На самом деле этим гарантируется, что при работе со строками меньшей длины дополнительное выделение памяти не потребуется.

Разница между String и StringBuffer может быть продемонстрирована на следующем примере:

public class Test { public static void main(String[] args) { Test t = new Test(); String s = new String("ssssss"); StringBuffer sb = new StringBuffer("bbbbbb"); s.concat("-aaa"); sb.append("-aaa"); System.out.println(s); System.out.println(sb); } }

В результате на экран будет выведено следующее:

ssssss bbbbbb-aaa

В данном примере можно заметить, что объект String остался неизменным, а объект StringBuffer изменился.

Основные методы, используемые для модификации StringBuffer, это:

public StringBuffer append(String str) – добавляет переданную строку str в буфер;

public StringBuffer insert(int offset, String str) – вставка строки, начиная с позиции offset (пропустив offset символов).

Стоит обратить внимание, что оба метода имеют варианты, принимающие в качестве параметров различные примитивные типы Java вместо String. При использовании этих методов аргумент предварительно приводится к строке (с помощью String.valueOf()).

Еще один важный момент, связанный с этими методами, – они возвращают сам объект, у которого вызываются. Благодаря этому, возможно их использование в цепочке. Например:


public static void main(String[] args) { StringBuffer sb = new StringBuffer("abc"); String str = sb.append("e").insert(4, "f").insert(3,"d").toString(); System.out.println(str); }

В результате на экран будет выведено:

abcdef

При передаче экземпляра класса StringBuffer в качестве параметра метода следует помнить, что этот класс изменяемый:

public class Test { public static void main(String[] args) { Test t = new Test(); StringBuffer sb = new StringBuffer("aaa"); System.out.println("Before = " + sb); t.doTest(sb); System.out.println("After = " + sb); } void doTest(StringBuffer theSb){ theSb.append("-bbb"); } }

В результате на экран будет выведено следующее:

Before = aaa After = aaa-bbb

Поскольку все объекты передаются по ссылке, в методе doTest, при выполнении операций с theSB, будет модифицирован объект, на который ссылается sb.


System


Класс System содержит набор полезных статических методов и полей. Экземпляр этого класса не может быть создан или получен.

Пожалуй, наиболее широко используемой возможностью, предоставляемой System, является стандартный вывод, доступный через переменную System.out. Ее тип – PrintStream (потоки данных будут подробно рассматриваться в лекции 15). Стандартный вывод можно перенаправить в другой поток (файл, массив байт и т.д., главное, чтобы это был объект PrintStream):

public static void main(String[] args) { System.out.println("Study Java"); try { PrintStream print = new PrintStream(new FileOutputStream("d:\\file2.txt")); System.setOut(print); System.out.println("Study well"); } catch(FileNotFoundException e) { e.printStackTrace(); } }

При запуске этого кода на экран будет выведено только

Study Java

И в файл "d:\file2.txt" будет записано

Study well

Аналогично могут быть перенаправлены стандартный ввод System.in – вызовом System.setIn(InputStream) и поток вывода сообщений об ошибках System.err – вызовом System.setErr(PrintStream) (по умолчанию все потоки – in, out, err – работают с консолью приложения).

Следующие методы класса System позволяют работать с некоторыми параметрами системы:

public static void runFinalizersOnExit(boolean value) – определяет, будет ли производиться вызов метода finalize() у всех объектов (у кого еще не вызывался), когда выполнение программы будет окончено (по умолчанию выставлено значение false);

public static native long currentTimeMillis() – возвращает текущее время; это время представляется как количество миллисекунд, прошедших с 1 января 1970 года;

public static String getProperty(String key) – возвращает значение свойства с именем key.

Чтобы получить все свойства, определенные в системе, можно воспользоваться следующим методом:

public static java.util.Properties getProperties() – возвращает объект java.util.Properties, в котором содержатся значения всех определенных системных свойств.

Метод arrayCopy(Object source, int srcPos, Object target, int trgPos, int length) предоставляет возможность быстрого копирования содержимого одного массива в другой. Первый параметр задает исходный массив, второй – номер позиции, начиная с которого брать элементы для копирования. Третий параметр – массив-"получатель", четвертый – номер позиции в нем, начиная с которого будут записываться скопированные элементы. Наконец, последний параметр задает количество элементов, которые надо скопировать. Оба массива должны быть созданы, иметь совместимые типы и достаточную длину, иначе будут сгенерированы соответствующие исключения.



Thread


Объекты этого класса представляют возможность запускать и управлять потоками исполнения.

Итак, для управления потоками в классе Thread предусмотрены следующие методы:

public void start() – производит запуск нового потока;

public final void join() – если поток A вызывает этот метод у объекта Thread, представляющего поток B (threadB.join()), то выполнение потока A приостанавливается до тех пор, пока не закончит выполнение поток B;

public static void yield() – поток, из которого вызван этот метод, временно приостанавливается, чтобы дать возможность выполняться другим потокам;

public static void sleep(long millis) – поток, из которого вызван этот метод, перейдет в состояние "сна" на указанное количество миллисекунд, после чего сможет продолжить выполнение. При этом нужно учесть, что через время millis миллисекунд этому потоку может быть выделено процессорное время, а может, ему придется и подождать немного дольше. Можно сказать, что поток продолжит выполнение не раньше, чем через время millis миллисекунд.

Существует еще несколько методов, которые объявлены deprecated и рекомендуется их избегать. Это: suspend() – временно прекратить выполнение, resume() – продолжить выполнение (приостановленное вызовом suspend()), stop() – остановить выполнение потока.

При вызове метода stop() в потоке, который представляет этот объект Thread, будет брошена ошибка ThreadDeath. Этот класс унаследован от Error. Если ошибка не будет обработана в программе и, соответственно, произойдет прекращение работы потока, сообщение о ненормальном завершении выведено не будет, так как такое завершение рассматривается как нормальное. Если же в программе эта ошибка обрабатывается (например, для проведения каких-то дополнительных действий перед закрытием потока), то очень важно позаботиться о том, чтобы эта же ошибка была брошена дальше, чтобы поток действительно закончил свое выполнение. Класс ThreadDeath специально унаследован от Error, а не от Exception, так как очень часто используется перехват всех исключений класса Exception, что не позволит корректно остановить поток.

Также Thread позволяет выставлять такие свойства потока, как:

Name – значение типа String, которое можно использовать для более наглядного обращения с потоками в группе;

Daemon – выполнение программы не будет прекращено до тех пор, пока выполняется хотя бы один не daemon поток;

Priority – определяет приоритет потока. В классе Thread определены константы, задающие минимальное и максимальное значения для приоритетов потока,– MIN_PRIORITY и MAX_PRIORITY, а также значение приоритета по умолчанию – NORM_PRIORITY.

Эти свойства могут быть изменены только до того момента, когда поток будет запущен, то есть вызван метод start() объекта Thread.

Получить эти значения можно, конечно же, в любой момент жизни потока – и после его запуска, и после прекращения выполнения. Также можно узнать, в каком состоянии сейчас находится поток: вызовом методов isAlive() – выполняется ли еще, isInterrupted() – прерван ли.



ThreadGroup


Для того, чтобы отдельный поток не мог начать останавливать и прерывать все потоки подряд, введено понятие группы. Поток может оказывать влияние только на потоки, которые находятся в одной с ним группе. Группу потоков представляет класс ThreadGroup. Такая организация позволяет защитить потоки от нежелательного внешнего воздействия. Группа потоков может содержать другие группы, что позволяет организовать все потоки и группы в иерархическое дерево, в котором каждый объект ThreadGroup, за исключением корневого, имеет родителя.

Класс ThreadGroup обладает методами для изменения свойств всех входящих в него потоков, таких, как приоритет, daemon и т.д. Метод list() позволяет получить список потоков.



Видео в окне аплета


Назад Вперед

Наиболее динамичные страницы сервера Web содержат анимационные изображения в виде небольших видеофильмов. Вы можете подготовить видеофильм как файл AVI или как многосекционный файл GIF.

Файл AVI представляет собой многопоточный файл, содержащий видео и звук. Файлы AVI можно создавать при помощи специального видеоадаптера, который способен оцифровывать сигнал с видеокамеры или видеомагнитофона, а также из отдельных изображений, составляющих кадры видеофильма.

Заметим, однако, что озвученный видеофильм в формате AVI продолжительностью в 1 минуту занимает мегабайты дискового пространства. При существующих на сегодняшний день скоростях передачи данных через Internet не имеет никакого смысла размещать на страницах сервера Web файлы такого размера.

Многосекционные файлы GIF не содержат звуковой информации и состоят обычно из одного-двух десятков кадров. Для каждого такого кадра вы можете задавать время отображения и координаты, где этот кадр будет отображаться. Можно также добиться зацикленного отображения видеофильма, созданного как многосекционный файл GIF.

Аплеты Java предоставляют вам еще одну возможность отображения небольших видеофильмов на страницах сервера Web.

Для реализации этой возможности вы должны подготовить и разместить в одном из каталогов сервера Web файлы отдельных кадров видеофильма в формате GIF или JPEG.

Аплет Java должен загрузить эти изображения, дождавшись окончания процесса загрузки, что можно сделать либо при помощи рассмотренного в этой главе класса MediaTracker либо при помощи интерфейса ImageObserver.

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

Так как аплет полностью контролирует отображение кадров фильма, он может реализовывать эффекты, недостижимые при использовании файлов AVI или многосекционных файлов GIF. Например, аплет может накладывать или смешивать кадры различных фильмов, рисовать поверх кадров произвольные изображения или делать надписи, масштабировать отдельные фрагменты кадров или весь кадр и так далее. Здесь все ограничивается главным образом вашей фантазией.


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

Назад Вперед


Контакты

О компании

Новости

Вакансии

Правовые аспекты

Условия использования

Торговые марки

Copyright 1994-2005 Sun Microsystems, Inc.



printmenus();

Программные продукты

Рабочие станции и тонкие клиенты

Серверы

Системы хранения данных

Посмотреть все
»

  
Solaris 10

Java 2 Standard Edition

Developer Tools

Top Downloads

New Downloads

Патчи и обновления

Посмотреть все
»

  
Каталог решений

Истории успеха

The Sun Grid

Партнерские программы

Посмотреть все
»

  
Гарантийное обслуживание

Программы SunSpectrum

Консалтинг

Услуги инсталляции

Поддержка ПО

Посмотреть все
»

  
Описание курсов

Сертификация

Авторизованные учебные центры

Посмотреть все
»

  
Проекты

События

Lab Downloads

Посмотреть все
»

  



Void


Этот класс-обертка, в отличие от остальных, не реализует интерфейс java.io.Serializable. Он не имеет открытого конструктора. Более того, экземпляр этого класса вообще не может быть получен. Он нужен только для получения ссылки на объект Class, соответствующий void. Эта ссылка представлена статической константой TYPE.

Делая краткое заключение по классам-оберткам, можно сказать, что:

каждый примитивный тип имеет соответствующий класс-обертку;все классы-обертки могут быть сконструированы как с использованием примитивных типов, так и с использованием String, за исключением Character, который может быть сконструирован только по char;

классы-обертки могут сравниваться с использованием метода equals();примитивные типы могут быть извлечены из классов-оберток с помощью соответствующего метода xxxxValue() (например intValue());

классы-обертки также являются классами-утилитами, т.е. предоставляют набор статических методов для работы с примитивными типами;

классы-обертки являются неизменяемыми.



lang входят классы, составляющие основу


В состав пакета java. lang входят классы, составляющие основу для всех других, и поэтому он является наиболее важным из всех, входящих в Java API. Поскольку без него не может обойтись ни один класс, каждый модуль компиляции содержит неявное импортирование этого пакета (import java.lang.*;).
Перечислим классы, составляющие основу пакета.
Object – является корневым в иерархии классов.
Class – экземпляры этого класса являются описаниями объектных типов в памяти JVM.
String – представляет собой символьную строку, содержит средства работы с нею.
StringBuffer – используется для работы (создания) строк.
Number – абстрактный класс, являющийся суперклассом для классов-объектных оберток числовых примитивных типов Java.
Character – объектная обертка для типа char.
Boolean – объектная обертка для типа boolean.
Math – реализует набор базовых математических функций.
Throwable – базовый класс для объектов, представляющих исключения. Любое исключение, которое может быть брошено и, соответственно, перехвачено блоком catch, должно быть унаследовано от Throwable.
Thread – позволяет запускать и работать с потоками выполнения в Java. Runnable – может использоваться в сочетании с классом Thread для описания потоков выполнения.
ThreadGroup – позволяет объединять потоки в группу и производить действия сразу над всеми потоками в ней. Существуют ограничения по безопасности на манипуляции с потоками из других групп.
System – содержит полезные поля и методы для работы системного уровня.
Runtime – позволяет приложению взаимодействовать с окружением, в котором оно запущено.
Process – представляет интерфейс к внешней программе, запущенной при помощи Runtime.
ClassLoader – отвечает за загрузку описания классов в память JVM.
SecurityManager – для обеспечения безопасности накладывает ограничения на данную среду выполнения программ.
Compiler – используется для поддержки Just-in-Time компиляторов.
Интерфейсы:
Cloneable – должен быть реализован объектами, которые планируется клонировать с помощью средств JVM;
Comparable – позволяет упорядочивать (сортировать, сравнивать) объекты каждого класса, реализующего этот интерфейс.

Загрузка и рисование растрового изображения


Назад Вперед

Загрузка растрового изображения из файла выполняется очень просто - с помощью метода getImage, определенного в классе Applet:

public Image getImage(URL url); public Image getImage(URL url, String name);

Первый вариант метода предполагает использование только одного параметра - адреса URL файла графического изображения. Второй позволяет дополнительно указать относительное расположение файла изображения относительно адреса URL, например:

Image img; img = getImage( "http://www.glasnet.ru/~frolov/pic","cd.gif");

Если аплет желает загрузить изображение, расположенное в том же каталоге, что и он сам, это можно сделать следующим образом:

img = getImage(getCodeBase(), "cd.gif");

Метод getCodeBase, определенный в классе Applet, возвращает адрес URL аплета. Вместо него можно использовать метод getDocumentBase, который также определен в классе Applet и возвращает адрес URL документа HTML, содержащего аплет:

img = getImage(getDocumentBase(), "cd.gif");

В любом случае метод getImage создает объект класса Image.

Заметим, что на самом деле метод getImage вовсе не загружает изображение через сеть, как это можно было бы подумать. Он только создает объект класса Image. Реальная загрузка файла растрового изображения будет выполняться методом рисования drawImage, который определен в классе Graphics:

public abstract boolean drawImage(Image img, int x, int y, ImageObserver observer); public abstract boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer); public abstract boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer); public abstract boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer);

Как видите, существует четыре варианта этого метода.

В качестве первого параметра любому варианту метода передается ссылка на объект класса Image, полученный ранее с помощью метода getImage.

Параметры x и y задают координаты верхнего левого угла прямоугольной области, внутри которой будет нарисовано изображение. Эти параметры также задаются для любого варианта метода drawImage.


Авторизованные учебные центры

Посмотреть все
»

  
Проекты

События

Lab Downloads

Посмотреть все
»

  



В этой лекции мы рассказали


В этой лекции мы рассказали о назначении и возможностях классов, представленных в пакете java.lang. Как Вы теперь знаете, пакет java.lang автоматически импортируется во все Java программы и содержит фундаментальные классы и интерфейсы, которые составляют основу для других пакетов Java.
Были рассмотрены все наиболее важные классы пакета java.lang:

Object, Class – основные классы, представляющие объект и класс объектов;
классы-обертки (Wrapper классы) – служат для представления примитивных значений в виде объектов, так как многие классы работают именно с объектами;
Math – класс, предоставляющий набор статических методов, реализующих базовые математические функции;
String и StringBuffer – классы для работы со строками;
System, Runtime, Process, ClassLoader, SecurityManager – системные классы, помогающие взаимодействовать с программным окружением (System, Runtime, Process), загружать классы в JVM (ClassLoader) и управлять безопасностью (SecurityManager);
Thread, ThreadGroup, Runnable – типы, обеспечивающие работу с потоками исполнения в Java;
Throwable, Error, Exception, RuntimeException – базовые классы для всех исключений.