Программирование на языке Java

         

А дорога дальше вьется



А дорога дальше вьется

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



Abstract



abstract

Бывают ситуации, когда нужно определить класс, в котором задана структура какой-либо абстракции, но полная реализация всех методов отсутствует. В таких случаях вы можете с помощью модификатора типа abstract объявить, что некоторые из методов обязательно должны быть замещены в подклассах. Любой класс, содержащий методы abstract, также должен быть объявлен, как abstract. Поскольку у таких классов отсутствует полная реализация, их представителей нельзя создавать с помощью оператора new. Кроме того, нельзя объявлять абстрактными конструкторы и статические методы. Любой подкласс абстрактного класса либо обязан предоставить реализацию всех абстрактных методов своего суперкласса, либо сам должен быть объявлен абстрактным. abstract class A { abstract void callme(); void metoo() { System.out.println("Inside A's metoo method"); } } class B extends A { void callme() { System.out.println("Inside B's callme method"); } } class Abstract { public static void main(String args[]) { A a = new B(): a.callme(): a.metoo(): } }

В нашем примере для вызова реализованного в под-классе класса А метода callme и реализованного в классе А метода metoo используется динамическое назначение методов, которое мы обсуждали раньше. С:\> Java Abstract Inside B's callrne method Inside A's metoo method



ALIGN = alignment



ALIGN = alignment

ALIGN - необязательный атрибут, задающий стиль выравнивания апплета. Этот атрибут трактуется так же, как в теге IMG, возможные его значения - LEFT, RIGHT, TOP, TEXTTOP, MIDDLE, ABSMIDDLE, BASELINE, BOTTOM, ABSBOTTOM.



ALT = alternateAppletText



ALT = alternateAppletText

Признак ALT - необязательный атрибут, задающий короткое текстовое сообщение, которое должно быть выведено в том случае, если используемый браузер распознает синтаксис тега <applet>, но выполнять апплеты не умеет. Это не то же самое, что HTML-текст, который можно вставлять между <applet> и </applet> для браузеров, вообще не поддерживающих апплетов.





Append



append

Метод append класса StringBuffer обычно вызывается неявно при ис-пользовании оператора + в выражениях со строками. Для каждого параметра вызывается метод String.valueOf и его результат до-бавляется к текущему объекту StringBuffer. К тому же при каждом вы-зове метод append возвращает ссылку на объект StringBuffer, с которым он был вызван. Это позволяет выстраивать в цепочку последовательные вызовы метода, как это показано в очередном примере. class appendDemo { public static void main(String args[]) { String s; int a = 42; StringBuffer sb = new StringBuffer(40); s = sb.append("a = ").append(a).append("!").toString(); System.out.println(s); } }

Вот вывод этого примера: С:\> Java appendDemo а = 42!



AppletContext и showDocument



AppletContext и showDocument

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



Апплеты



Апплеты

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



Апплеты Java



Апплеты Java

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

Именно броские Web-страницы с анимацией привлекли большинство ранних приверженцев языка Java. Поскольку пользователи не сразу смогли полностью освоить наиболее революционные аспекты Java, этот язык часто сравнивался с другими технологиями для загрузки динамических изображений и простого взаимодействия с Web-клиентами. Компании, традиционно занимающиеся разработкой мультимедиа-технологий, например, Adobe или MacroMedia, утверждали, что их продукты предоставляют те же возможности, что и Java. По мнению Kaleida, Taligent и NeXT, их собственные объектно-ориентированные среды разработки были не менее революционны. Microsoft заявлял о победе технологии десятилетней давности. На самом деле ничто не может сравниться с тем, что вы откроете для себя, ощутив мощь программирования на языке Java.

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



ARCHIVE = jarFiles



ARCHIVE = jarFiles

Задает список jar-файлов (разделяется запятыми), которые предварительно загружаются в Web-броузер. В этих архивных файлах могут содержаться файлы классов, изображения, звуки и любые другие ресурсы, необходимые апплету. Для создания архивов используется утилита JAR, синтаксис вызова которой напоминает вызов команды TAR Unix: c:\> jar cf soundmap.jar *.class image.gif sound.wav

Очевидно, что передача сжатых jar-файлов повышает эффективность работы. Поэтому многие средства разработки (Lotus JavaBeans, Borland JBuilder) уже имеют средства для публикации апплетов в виде jar-файлов.



Арифметические операторы Арифметические



Арифметические операторы

Арифметические операторы используются для вычислений так же как в алгебре (см. таблицу со сводкой арифметических операторов ниже). Допустимые операнды должны иметь числовые типы. Например, использовать эти операторы для работы с логическими типами нельзя, а для работы с типом char можно, поскольку в Java тип char - это подмножество типа int.

ОператорРезультатОператорРезультат
+Сложение+ =сложение с присваиванием
-вычитание (также унарный минус)-=вычитание с присваиванием
*Умножение*=умножение с присваиванием
/Деление/=деление с присваиванием
%деление по модулю%=деление по модулю с присваиванием
++Инкремент--декремент



Арифметические операторы присваивания



Арифметические операторы присваивания

Для каждого из арифметических операторов есть форма, в которой одновременно с заданной операцией выполняется присваивание. Ниже приведен пример, который иллюстрирует использование подобной разновидности операторов. class OpEquals { public static void main(String args[]) { int a = 1; int b = 2; int с = 3; a += 5; b *= 4; c += a * b; с %= 6; System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("c = " + c); } }

А вот и результат, полученный при запуске этой программы: С:> Java OpEquals а = 6 b = 8 с = 3

Инкремент и декремент

В С существует 2 оператора, называемых операторами инкремента и декремента (++ и --) и являющихся сокращенным вариантом записи для сложения или вычитания из операнда единицы. Эти операторы уникальны в том плане, что могут использоваться как в префиксной, так и в постфиксной форме. Следующий пример иллюстрирует использование операторов инкремента и декремента. class IncDec { public static void main(String args[]) { int a = 1; int b = 2; int c = ++b; int d = a++; c++; System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("c = " + c); System.out.println("d = " + d); } }

Результат выполнения данной программы будет таким: C:\ java IncDec a = 2 b = 3 c = 4 d = 1



Автоматическое преобразование типов в выражениях



Автоматическое преобразование типов в выражениях

Когда вы вычисляете значение выражения, точность, требуемая для хранения промежуточных результатов, зачастую должна быть выше, чем требуется для представления окончательного результата. byte a = 40; byte b = 50; byte с = 100; int d = a* b / с;

Результат промежуточного выражения (а* b) вполне может выйти за диапазон допустимых для типа byte значений. Именно поэтому Java автоматически повышает тип каждой части выражения до типа int, так что для промежуточного результата (а* b) хватает места.

Автоматическое преобразование типа иногда может оказаться причиной неожиданных сообщений транслятора об ошибках. Например, показанный ниже код, хотя и выглядит вполне корректным, приводит к сообщению об ошибке на фазе трансляции. В нем мы пытаемся записать значение 50* 2, которое должно прекрасно уместиться в тип byte, в байтовую переменную. Но из-за автоматического преобразования типа результата в int мы получаем сообщение об ошибке от транслятора - ведь при занесении int в byte может произойти потеря точности. byte b = 50; b = b* 2; ^ Incompatible type for =. Explicit cast needed to convert int to byte.

(Несовместимый тип для =. Необходимо явное преобразование int в byte)

Исправленный текст : byte b = 50; b = (byte) (b* 2);

что приводит к занесению в b правильного значения 100.

Если в выражении используются переменные типов byte, short и int, то во избежание переполнения тип всего выражения автоматически повышается до int. Если же в выражении тип хотя бы одной переменной - long, то и тип всего выражения тоже повышается до long. He забывайте, что все целые литералы, в конце которых не стоит символ L (или 1), имеют тип int.

Если выражение содержит операнды типа float, то и тип всего выражения автоматически повышается до float. Если же хотя бы один из операндов имеет тип double, то тип всего выражения повышается до double. По умолчанию Java рассматривает все литералы с плавающей точкой, как имеющие тип double. Приведенная ниже программа показывает, как повышается тип каждой величины в выражении для достижения соответствия со вторым операндом каждого бинарного оператора. class Promote { public static void main (String args []) { byte b = 42; char с = 'a'; short s = 1024; int i = 50000; float f = 5.67f; double d =.1234; double result = (f* b) + (i/ c) - (d* s); System. out. println ((f* b)+ "+ "+ (i / с)+ " - " + (d* s)); System. out. println ("result = "+ result); } }

Подвыражение f* b - это число типа float, умноженное на число типа byte. Поэтому его тип автоматически повышается до float. Тип следующего подвыражения i / с ( int, деленный на char) повышается до int. Аналогично этому тип подвыражения d* s (double, умноженный на short) повышается до double. На следующем шаге вычислений мы имеем дело с тремя промежуточными результатами типов float, int и double. Сначала при сложении первых двух тип int повышается до float и получается результат типа float. При вычитании из него значения типа double тип результата повышается до double. Окончательный результат всего выражения - значение типа double.



AWT при свете дня



AWT при свете дня

AWT в своем нынешнем виде делает прекрасную работу, являясь общим знаменателем - библиотекой, единой для всех платформ. Некоторый недостаток AWT в том, что, поскольку каждый из AWT-компонентов реализован на основе соответствующего компонента базовой операционной системы, их поведение и внешний вид может меняться при смене платформы. Хорошо известны расширения и аналоги AWT - Swing, Java Foundation Classes (Netscape), Application Foundation Classes (Microsoft).



Бесконечность и NaN



Бесконечность и NaN

В спецификации IEEE для чисел с вещественной точкой есть два значения типа double, которые трактуются специальным образом: бесконечность и NaN (Not a Number - неопределенность). В классе Double есть тесты для проверки обоих этих условий, причем в двух формах - в виде методов (статических), которым значение double передается в качестве параметра, и в виде методов, проверяющих число, хранящееся в объекте класса Double. islnfinite(d) возвращает true, если абсолютное значение указанного числа типа double бесконечно велико. islnfinite() возвращает true, если абсолютное значение числа, хранящегося в данном объекте Double, бесконечно велико. isNaN(d) возвращает true, если значение указанного числа типа double неопределено. isNaN() возвращает true, если значение числа, хранящегося в данном объекте Double, неопределено.

Очередной наш пример создает два объекта Double, один с бесконечным, другой с неопределенным значением. class InfNaN { public static void main(String args[]) { Double d1 = new Double(1/0.); Double d2 = new Double(0/0.); System.out.println(d1+":"+d1.isInfinite()+","+d1.isNaN()); System.out.println(d2+":"+d2.isInfinite()+","+d2.isNaN()); } }

Ниже приведен результат работы этой программы: С:\> java InfNaN Infinity: true, false NaN: false, true



Безопасность



Безопасность

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



Безопасность



Безопасность

В Java 1.1 включены новые пакеты, которые обеспечивают поддержку цифровых подписей, обработку сообщений, обработку ключей и списков управления доступом.



Беззнаковый сдвиг вправо



Беззнаковый сдвиг вправо

Часто требуется, чтобы при сдвиге вправо расширение знакового раз-ряда не происходило, а освобождающиеся левые разряды просто запол-нялись бы нулями. class ByteUShift { static public void main(String args[]) { char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'а', 'b', 'с', 'd', 'e', 'f' }; byte b = (byte) 0xf1; byte c = (byte) (b >> 4); byte d = (byte) (b >> 4); byte e = (byte) ((b & 0xff) >> 4); System.out.println(" b = 0x" + hex(b >> 4) & 0x0f] + hex[b & 0x0f]); System.out.println(" b >> 4 = 0x" + hex[(c >> 4) & 0x0f] + hex[c & 0x0f]); System.out.println("b >>> 4 = 0x" + hex[(d >> 4) & 0x0f] + hex[d & 0x0f]); System.out.println("(b & 0xff) >> 4 = 0x" + hex[(e >> 4) & 0x0f] + hex[e & 0x0f]); } }

Для этого примера переменную b можно было бы инициализировать произвольным отрицательным числом, мы использовали число с шест-надцатиричным представлением 0xf1. Переменной с присваивается ре-зультат знакового сдвига b вправо на 4 разряда. Как и ожидалось, рас-ширение знакового разряда приводит к тому, что 0xf1 превращается в 0xff. Затем в переменную d заносится результат беззнакового сдвига b вправо на 4 разряда. Можно было бы ожидать, что в результате d со-держит 0x0f, однако на деле мы снова получаем 0xff. Это - результат расширения знакового разряда, выполненного при автоматическом по-вышении типа переменной b до int перед операцией сдвига вправо. На-конец, в выражении для переменной е нам удается добиться желаемого результата - значения 0x0f. Для этого нам пришлось перед сдвигом вправо логически умножить значение переменной b на маску 0xff, очис-тив таким образом старшие разряды, заполненные при автоматическом повышении типа. Обратите внимание, что при этом уже нет необходи-мости использовать беззнаковый сдвиг вправо, поскольку мы знаем со-стояние знакового бита после операции AND. С: \> java ByteUShift b = 0xf1 b >> 4 = 0xff b >>> 4 = 0xff b & 0xff) >> 4 = 0x0f



Битовые операторы присваивания



Битовые операторы присваивания

Так же, как и в случае арифметических операторов, у всех бинарных битовых операторов есть родственная форма, позволяющая автоматичес-ки присваивать результат операции левому операнду. В следующем примере создаются несколько целых переменных, с ко-торыми с помощью операторов, указанных выше, выполняются различ-ные операции. class OpBitEquals { public static void main(String args[]) { int a = 1; int b = 2; int с = 3; a |= 4; b >>= 1; с

Результаты исполнения программы таковы: С:\> Java OpBitEquals а = 3 b = 1 с = 6



Богатая объектная среда



Богатая объектная среда

Среда Java — это нечто гораздо большее, чем просто язык программирования. В нее встроен набор ключевых классов, содержащих основные абстракции реального мира, с которым придется иметь дело вашим программам. Основой популярности Java являются встроенные классы-абстракции, сделавшие его языком, действительно независимым от платформы. Библиотеки, подобные MFC/COM, OWL, VCL, NeXTStep, Motif и OpenDoc прекрасно работают на своих платформах, однако сегодня главной платформой становится Internet.

В реализации Java 1.1.6 находится 23 пакета (в Java 1.0.2 их было 8), а количество классов – 503 (211). Сейчас проходит завершающую стадию бета-тестирования JDK 1.2. Для тех, кто собирается поддерживать Java 1.0 наряду с 1.1 (актуальность этой поддержки подтверждает Borland JBuilder 2.0 и другие продукты), специально выделены новшества 1.1 в Приложение 2.



Boolean



Boolean

Класс Boolean - это очень тонкая оболочка вокруг логических значений, она бывает полезна лишь в тех случаях, когда тип boolean требуется передавать по ссылке, а не по значению.



BorderLayout



BorderLayout

Класс BorderLayout реализует обычный стиль размещения для окон верхнего уровня, в котором предусмотрено четыре узких компонента фиксированной ширины по краям, и одна большая область в центре, которая может расширяться и сужаться в двух направлениях, занимая все свободное пространство окна. У каждой из этих областей есть строки-имена: String.North, String.South, String.East и String.West соответствуют четырем краям, a Center - центральной области. Ниже приведен пример BorderLayout с компонентом в каждой из названных областей. /* <applet code = "BorderLayoutDemo" width=300 height=200> </applet> */ import java.awt.*; import java.applet.*; import java.util.*; public class BorderLayoutDemo extends Applet { public void init() { setLayout(new BorderLayout()); int width = Integer.parseInt(getParameter("width")); int height = Integer.parseInt(getParameter("height")); add("North", new Button("This is across the top")); add("South", new Label("The footer message might go here")); add("East", new Button("Left")); add("West", new Button("Right")); String msg = "The reasonable man adapts " + "himself to the world;\n" + "the unreasonable one persists in " + "trying to adapt the world to himself.\n" + "Therefore all progress depends " + "on the unreasonable rnan.\n\n" + "George Bernard Shaw\n\n"; add("Center", new TextArea(msg)); } }

Опять читаем фразу со смыслом (спасибо Бернарду Шоу) - BorderLayoutDemo.html.



Break



break

В языке Java отсутствует оператор goto. Для того, чтобы в некоторых случаях заменять goto, в Java предусмотрен оператор break. Этот оператор сообщает исполняющей среде, что следует прекратить выполнение именованного блока и передать управление оператору, следующему за данным блоком. Для именования блоков в языке Java используются метки. Оператор break при работе с циклами и в операторах switch может использоваться без метки. В таком случае подразумевается выход из текущего блока.

Например, в следующей программе имеется три вложенных блока, и у каждого своя уникальная метка. Оператор break, стоящий во внутреннем блоке, вызывает переход на оператор, следующий за блоком b. При этом пропускаются два оператора println. class Break { public static void main(String args[]) { boolean t = true; a: { b: { c: { System.out.println("Before the break"); // Перед break if (t) break b; System.out.println("This won't execute"); // He будет выполнено } System.out.println("This won't execute"); // He будет выполнено } System.out.println("This is after b"); //После b } } }

В результате исполнения программы вы получите следующий результат: С:\> Java Break Before the break This is after b



Булевы логические операторы



Булевы логические операторы

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

ОператорРезультатОператорРезультат
&логическое И (AND)&=И (AND) с присваиванием
|логическое ИЛИ (OR)=ИЛИ (OR) с присваиванием
^логическое исключающее ИЛИ (XOR)^=исключающее ИЛИ (XOR) с присваиванием
||оператор OR быстрой оценки выражений (short circuit OR)==равно
&&оператор AND быстрой оценки выражений (short circuit AND)!=не равно
!логическое унарное отрицание (NOT)?:тернарный оператор if-then-else

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

АВORANDXORNOT A
falsefalsefalsefalsefalsetrue
truefalsetruefalsetruefalse
falsetruetruefalsetruetrue
truetruetruetruefalsefalse

Программа, приведенная ниже, практически полностью повторяет уже знакомый вам пример BitLogic. Только но на этот раз мы работаем с булевыми логическими значениями. class BoolLogic { public static void main(String args[]) { boolean a = true; boolean b = false; boolean с = a | b; boolean d = a & b; boolean e = a ^ b; boolean f = (!a & b) | (a & !b); boolean g = !a; System.out.println(" a = " + a); System.out.println(" b = " + b); System.out.println(" a|b = " + c); System.out.println(" a&b = " + d); System.out.println(" a^b = " + e); System.out.println("!a&b|a&!b = " + f); System.out.println(" !a = " + g); } } С: \> Java BoolLogic а = true b = false a|b = true a&b = false a^b = true !a&b|a&!b = true !a = false

Операторы быстрой оценки логических выражений (short circuit logical operators)

Существуют два интересных дополнения к набору логических опера-торов. Это - альтернативные версии операторов AND и OR, служащие для быстрой оценки логических выражений. Вы знаете, что если первый операнд оператора OR имеет значение true, то независимо от значения второго операнда результатом операции будет величина true. Аналогично в случае оператора AND, если первый операнд - false, то значение вто-рого операнда на результат не влияет - он всегда будет равен false. Если вы в используете операторы && и || вместо обычных форм & и |, то Java не производит оценку правого операнда логического выражения, если ответ ясен из значения левого операнда. Общепринятой практикой является использование операторов && и || практически во всех случаях оценки булевых логических выражений. Версии этих операторов & и | применяются только в битовой арифметике.



Button



Button

Объекты-кнопки помечаются строками, причем эти строки нельзя выравнивать подобно строкам объектов Label (они всегда центрируются внутри кнопки). Позднее в данной главе речь пойдет о том, как нужно обрабатывать события, возникающие при нажатии и отпускании пользователем кнопки. Ниже приведен пример, в котором создаются три расположенные по вертикали кнопки. /* <applet code = "ButtonDemo" width=100 height=100> </applet> */ import java.awt.*; import java.applet.*; public class ButtonDemo extends Applet { public void init() { setLayout(null); int width = Integer.parseInt(getParameter("width")); int height = Integer.parseInt(getParameter("height")); Button yes = new Button("Yes"); Button no = new Button("No"); Button maybe = new Button("Undecided"); add(yes); add(no); add(maybe); yes.reshape(0, 0, width, height / 3); no.reshape(0, height / 3, width, height / 3); maybe.reshape(0, 2 * height / 3, width, height / 3); } }



Byte



byte

Тип byte - это знаковый 8-битовый тип. Его диапазон - от -128 до 127. Он лучше всего подходит для хранения произвольного потока байтов, загружаемого из сети или из файла. byte b; byte с = 0х55;

Если речь не идет о манипуляциях с битами, использования типа byte, как правило, следует избегать. Для нормальных целых чисел, используемых в качестве счетчиков и в арифметических выражениях, гораздо лучше подходит тип int.



BytesWidth, charsWidth



bytesWidth, charsWidth

Эти методы возвращают ширину указанного массива байтов для текущего шрифта.



Canvas



Canvas

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

Произведем от Canvas подкласс GrayCanvas, который будет просто закрашивать себя серым цветом определенной насыщенности. Наш апплет будет создавать несколько таких объектов, каждый со своей интенсивностью серого цвета. /* <applet code = "PanelDemo" width=300 height=300> </applet> */ import java.awt.*; import java.applet.*; class GrayCanvas extends Canvas { Color gray; public GrayCanvas(float g) { gray = new Color(g, g, g); } public void paint(Graphics g) { Dimension size = size(); g.setColor(gray); g.fillRect(0, 0, size.width, size.height); g.setColor(Color.black); g.drawRect(0, 0, size.width-1, size.height-1); } } public class PanelDemo extends Applet { static final int n = 4; public void init() { setLayout(null); int width = Integer.parseInt(getParameter("width")); int height = Integer.parseInt(getParameter("height")); for (int i=0;i



CardLayout



CardLayout

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



Целочисленные битовые операторы



Целочисленные битовые операторы

Для целых числовых типов данных - long, int, short, char и byte, определен дополнительный набор операторов, с помощью которых можно проверять и модифицировать состояние отдельных битов соответствующих значений. В таблице приведена сводка таких операторов. Операторы битовой арифметики работают с каждым битом как с самостоятельной величиной.

ОператорРезультатОператорРезультат
~побитовое унарное отрицание (NOT) 
&побитовое И (AND)&=побитовое И (AND) с присваиванием
|побитовое ИЛИ (OR)|=побитовое ИЛИ (OR) с присваиванием
^побитовое исключающее ИЛИ (XOR)^=побитовое исключающее ИЛИ (XOR) с присваиванием
>>сдвиг вправо>> =сдвиг вправо с присваиванием
>>>сдвиг вправо с заполнением нулями>>>=сдвиг вправо с заполнением нулями с присваиванием
<<сдвиг влево<<=сдвиг влево с присваиванием


Целые числа



Целые числа

В языке Java понятие беззнаковых чисел отсутствует. Все числовые типы этого языка - знаковые. Например, если значение переменной типа byte равно в шестнадцатиричном виде 0х80, то это - число -1. Замечание
ЗАМЕЧАНИЕ

Единственная реальная причина использования беззнаковых чисел - это использование иных, по сравнению со знаковыми числами, правил манипуляций с битами при выполнении операций сдвига. Пусть, например, требуется сдвинуть вправо битовый массив mask, хранящийся в целой переменной и избежать при этом расширения знакового разряда, заполняющего старшие биты единицами. Стандартный способ выполнения этой задачи в С - ((unsigned) mask) >> 2. В Java для этой цели введен новый оператор беззнакового сдвига вправо. Приведенная выше операция записывается с его помощью в виде mask>>>2. Детально мы обсудим все операторы в следующей главе.

Отсутствие в Java беззнаковых чисел вдвое сокращает количество целых типов. В языке имеется 4 целых типа, занимающих 1, 2, 4 и 8 байтов в памяти. Для каждого типа - byte, short, int и long, есть свои естественные области применения.



Целые литералы



Целые литералы

Целые числа - это тип, используемый в обычных программах наиболее часто. Любое целочисленное значение, например, 1, 2, 3, 42 - это целый литерал. В данном примере приведены десятичные числа, то есть числа с основанием 10 - именно те, которые мы повседневно используем вне мира компьютеров. Кроме десятичных, в качестве целых литералов могут использоваться также числа с основанием 8 и 16 - восьмеричные и шестнадцатиричные. Java распознает восьмеричные числа по стоящему впереди нулю. Нормальные десятичные числа не могут начинаться с нуля, так что использование в программе внешне допустимого числа 09 приведет к сообщению об ошибке при трансляции, поскольку 9 не входит в диапазон 0.. 7, допустимый для знаков восьмеричного числа. Шестнадцатиричная константа различается по стоящим впереди символам нуль-х (0х или 0Х). Диапазон значений шестнадцатиричной цифры - 0.. 15, причем в качестве цифр для значений 10.. 15 используются буквы от А до F (или от а до f). С помощью шестнадцатиричных чисел вы можете в краткой и ясной форме представить значения, ориентированные на использование в компьютере, например, написав Oxffff вместо 65535.

Целые литералы являются значениями типа int, которое в Java хранится в 32-битовом слове. Если вам требуется значение, которое по модулю больше, чем приблизительно 2 миллиарда, необходимо воспользоваться константой типа long. При этом число будет храниться в 64-битовом слове. К числам с любым из названных выше оснований вы можете приписать справа строчную или прописную букву L, указав таким образом, что данное число относится к типу long. Например, Ox7ffffffffffffffL или 9223372036854775807L - это значение, наибольшее для числа типа long.



Центрирование текста



Центрирование текста

Давайте теперь воспользуемся методами объекта FontMetrics для получения подъема, снижения и длины строки, которую требуется нарисовать, и с помощью полученных значений отцентрируем ее в нашем апплете. /* * <applet code="HelloWorld" width=200 height=100> * </applet> * */ import java.applet.*; import java.awt.*; public class HelloWorld extends Applet { final Font f = new Font("Helvetica", Font.BOLD, 18); public void paint(Graphics g) { Dimension d = this.size(); g.setColor(Color.white); g.fillRect(0,0,d.width,d.height); g.setColor(Color.black); g.setFont(f); drawCenteredString("Hello World!", d.width, d.height, g); g.drawRect(0,0,d.width-1,d.height-1); } public void drawCenteredString(String s, int w, int h, Graphics g) { FontMetrics fm = g.getFontMetrics(); int x=(w-fm.stringWidth(s))/2; int y=(fm.getAscent()+(h- (fm.getAscent()+fm.getDescent()))/2); g.drawString(s, x, y); } }



Character



Character

Character - простой класс-оболочка типа char. У него есть несколько полезных статических методов, с помощью которых можно выполнять над символом различные проверки и преобразования. isLowerCase(char ch) возвращает true, если символ-параметр принадлежит нижнему регистру (имеется в виду не просто диапазон a-z, но и символы нижнего регистра в кодировках, отличных от ISO-Latin-1). isUpperCase(char ch) делает то же самое в случае символов верхнего регистра. isDigit(char ch) и isSpace(char ch) возвращают true для цифр и пробелов, соответственно. toLowerCase(char ch) и toupperCase(char ch) выполняют преобразования символов из верхнего в нижний регистр и обратно.



CharAt и setCharAt



charAt и setCharAt

Одиночный символ может быть извлечен из объекта StringBuffer с помощью метода charAt. Другой метод setCharAt позволяет записать в заданную позицию строки нужный символ. Использование обоих этих методов проиллюстрировано в примере: class setCharAtDemo { public static void main(String args[]) { StringBuffer sb = new StringBuffer("Hello"); System.out.println("buffer before = " + sb); System.out.println("charAt(1) before = " + sb.charAt(1)); sb.setCharAt(1, 'i'); sb.setLength(2); System.out.println("buffer after = " + sb); System.out.println("charAt(1) after = " + sb.charAt(1)); } }

Вот вывод, полученный при запуске этой программы. C:\> java setCharAtDemo buffer before = Hello charAt(1) before = e buffer after = Hi charAt(1) after = i



Checkbox



Checkbox

Класс Checkbox часто используется для выбора одной из двух возможностей. При создании объекта Checkbox ему передается текст метки и логическое значение, чтобы задать исходное состояние окошка с отметкой. Программно можно получать и устанавливать состояние окошка с отметкой с помощью методов getState и setState. Ниже приведен пример с тремя объектами Checkbox, задаваемое в этом примере исходное состояние соответствует отметке в первом объекте. /* <applet code = "CheckBoxDemo" width=120 height=100> </applet> */ import java.awt.*; import java.applet.*; public class CheckboxDemo extends Applet { public void init() { setLayout(null); int width = Integer.parseInt(getParameter("width")); int height = Integer.parseInt(getParameter("height")); Checkbox win95 = new Checkbox("Windows 95/98", null, true); Checkbox Solaris = new Checkbox("Solaris 2.5"); Checkbox mac = new Checkbox("MacOS 7.5"); add(win95); add(solaris); add(mac); win95.reshape(0, 0, width, height / 3); Solaris.reshape(0, height / 3, width, height / 3); mac.reshape(0, 2 * height / 3, width, height / 3); } }

Ниже приведен внешний вид работающего апплета - CheckBoxDemo.html.



CheckboxGroup



CheckboxGroup

Второй параметр конструктора Checkbox (в предыдущем примере мы ставили там null) используется для группирования нескольких объектов Checkbox. Для этого сначала создается объект CheckboxGroup, затем он передается в качестве параметра любому количеству конструкторов Checkbox, при этом предоставляемые этой группой варианты выбора становятся взаимоисключающими (только один может быть задействован). Предусмотрены и методы, которые позволяют получить и установить группу, к которой принадлежит конкретный объект Checkbox - getCheckboxGroup и setCheckboxGroup. Вы можете пользоваться методами getCurrent и setCurrent для получения и установки состояния выбранного в данный момент объекта Checkbox. Ниже приведен пример, отличающийся от предыдущего тем, что теперь различные варианты выбора в нем взаимно исключают друг друга. /* <applet code = "CheckboxGroupDemo" width=120 height=100> </applet> */ import java.awt.*; import java.applet.*; public class CheckboxGroupDemo extends Applet { public void init() { setLayout(null); int width = Integer.parseInt(getParameter("width")); int height = Integer.parseInt(getParameter("height")); CheckboxGroup g = new CheckboxGroup(); Checkbox win95 = new Checkbox("Windows 95/98", g, true); Checkbox solaris = new Checkbox("Solaris 2.5", g, false); Checkbox mac = new Checkbox("MacOS 7.5", g, false); add(win95); add(solaris); add(mac); win95.reshape(0, 0, width, height / 3); solaris. reshape(0, height / 3, width, height / 3); mac.reshape(0, 2 * height / 3, width, height / 3); } }

Обратите внимание - окошки изменили свою форму, теперь они не квадратные, а круглые - CheckboxGroupDemo.html.



Четыре арифметических действия



Четыре арифметических действия

Ниже, в качестве примера, приведена простая программа, демонстрирующая использование операторов. Обратите внимание на то, что операторы работают как с целыми литералами, так и с переменными. class BasicMath { public static void int a = 1 + 1; int b = a * 3; main(String args[]) { int c = b / 4; int d = b - а; int e = -d; System.out.println("a = " + а); System.out.println("b = " + b); System.out.println("c = " + c); System.out.println("d = " + d); System.out.println("e = " + e); } }

Исполнив эту программу, вы должны получить приведенный ниже результат: C: \> java BasicMath a = 2 b = 6 c = 1 d = 4 e = -4



Числа с плавающей точкой



Числа с плавающей точкой

Числа с плавающей точкой, часто называемые в других языках вещественными числами, используются при вычислениях, в которых требуется использование дробной части. В Java реализован стандартный (IEEE-754) набор типов для чисел с плавающей точкой - float и double и операторов для работы с ними. Характеристики этих типов приведены в таблице.

ИмяРазрядностьДиапазон
double64 1.7е-308.. 1. 7е+ 308
float323.4е-038.. 3. 4е+ 038


Choice



Choice

Класс Choice (выбор) используется при создании раскрывающихся списочных меню (выпадающих списков типа ComboBox в Windows). Компонент Choice занимает ровно столько места, сколько требуется для отображения выбранного в данный момент элемента, когда пользователь щелкает мышью на нем, раскрывается меню со всеми элементами, в котором можно сделать выбор. Каждый элемент меню - это строка, которая выводится, выровненная по левой границе. Элементы меню выводятся в том порядке, в котором они были добавлены в объект Choice. Метод countItems возвращает количество пунктов в меню выбора. Вы можете задать пункт, который выбран в данный момент, с помощью метода select, передав ему либо целый индекс (пункты меню перечисляются с нуля), либо строку, которая совпадает с меткой нужного пункта меню. Аналогично, с помощью методов getSelectedItem и getSelectedIndex можно получить, соответственно, строку-метку и индекс выбранного в данный момент пункта меню. Вот очередной простой пример, в котором создается два объекта Choice. /* <applet code = "ChoiceDemo" width=200 height=100> </applet> */ import java.awt.*; import java.applet.*; public class ChoiceDemo extends Applet { public void init() { setLayout(null); int width = Integer.parseInt(getParameter("width")); int height = Integer.parseInt(getParameter("height")); Choice os = new Choice(); Choice browser = new Choice(); os.addItem("Windows 95/98"); os.addItem("Solaris 2.5"); os.addItem("MacOS 7.5"); browser.addItem("Netscape Navigator 3.0"); browser.addItem("Netscape Communicator 4.5"); browser.addItem("Internet Explorer 3.0"); browser.addItem("Mosaic 3.0"); browser.addItem("Lynx 2.4"); browser.select("Netscape Communicator 4.5"); add(os); add(browser); os.reshape(0, 0, width, height / 2); browser.reshape(0, height / 2, width, height / 2); } }

А вот как выглядят эти выпадающие списки - ChoiceDemo.html.



Что дальше?



Что дальше?

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



Цикл обработки событий в случае единственного подпроцесса



Цикл обработки событий в случае единственного подпроцесса

В системах без параллельных подпроцессов используется подход, называемый циклом обработки событий. В этой модели единственный подпроцесс выполняет бесконечный цикл, проверяя и обрабатывая возникающие события. Синхронизация между различными частями программы происходит в единственном цикле обработки событий. Такие среды называют синхронными управляемыми событиями системами. Apple Macintosh, Microsoft Windows, X11/Motif — все эти среды построены на модели с циклом обработки событий.

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



Циклы



Циклы

Любой цикл можно разделить на 4 части - инициализацию, тело, итерацию и условие завершения. В Java есть три циклические конструкции: while (с предусловием), do-while (с постусловием) и for (с параметровм).



CODE = appletClassFile



CODE = appletClassFile

CODE - обязательный атрибут, задающий имя файла, в котором содержится оттранслированный код апплета. Имя файла задается относительно codebase, то есть либо от текущего каталога, либо от каталога, указанного в атрибуте CODEBASE. В Java 1.1 вместо этого атрибута может использоваться атрибут OBJECT.



CODEBASE = codebaseURL



CODEBASE = codebaseURL

CODEBASE - необязательный атрибут, задающий базовый URL кода апплета, являющийся каталогом, в котором будет выполняться поиск исполняемого файла апплета (задаваемого в признаке CODE). Если этот атрибут не задан, по умолчанию используется каталог данного HTML-документа. CODEBASE не обязательно должен указывать на тот же узел, с которого был загружен HTML-документ.



Container



Container

Container - это абстрактный подкласс класса Component, определяющий дополнительные методы, которые дают возможность помещать в него другие компоненты, что дает возможность построения иерархической системы визуальных объектов. Container отвечает за расположение содержащихся в нем компонентов с помощью интерфейса LayoutManager, описание которого будет позднее в этой главе.



Continue



continue

В некоторых ситуациях возникает потребность досрочно перейти к выполнению следующей итерации, проигнорировав часть операторов тела цикла, еще не выполненных в текущей итерации. Для этой цели в Java предусмотрен оператор continue. Ниже приведен пример, в котором оператор continue используется для того, чтобы в каждой строке печатались два числа. class ContinueDemo { public static void main(String args[]) { for (int i=0; i < 10; i++) { System.out.print(i + " "); if (i % 2 == 0) continue; System.out.println(""); } }}

Если индекс четный, цикл продолжается без вывода символа новой строки. Результат выполнения этой программы таков: С: \> java ContinueDemo 0 1 2 3 4 5 5 7 8 9

Как и в случае оператора break, в операторе continue можно задавать метку, указывающую, в каком из вложенных циклов вы хотите досрочно прекратить выполнение текущей итерации. Для иллюстрации служит программа, использующая оператор continue с меткой для вывода треугольной таблицы умножения для чисел от 0 до 9: class ContinueLabel { public static void main(String args[]) { outer: for (int i=0; i < 10; i++) { for (int j = 0; j < 10; j++) { if (j > i) { System.out.println(""); continue outer; } System.out.print(" " + (i * j)); } } }}

Оператор continue в этой программе приводит к завершению внутреннего цикла со счетчиком j и переходу к очередной итерации внешнего цикла со счетчиком i. В процессе работы эта программа выводит следующие строки: С:\> Java ContinueLabel 0 0 1 0 2 4 0 3 6 9 0 4 8 12 16 0 5 10 15 20 25 0 6 12 18 24 30 36 0 7 14 21 28 35 42 49 0 8 16 24 32 40 48 56 64 0 9 18 27 36 45 54 63 72 81



CropImageFilter



CropImageFilter

CropImageFilter создает новое изображение из фрагмента существующего. Использование этого фильтра полезно тогда, когда вы хотите использовать несколько маленьких изображений в одном апплете. Загрузка по сети двадцати изображений по 2 Кбайта происходит намного медленнее, чем загрузка одного файла размером 40 Кбайт. Если ваши изображения - одинакового размера, вы можете собрать их в единый блок и использовать CropImageFilter для разделения блока на отдельные изображения в Java-клиенте.



CurrentThread



currentThread

Статический метод currentThread возвращает объект Thread, выполняющийся в данный момент.



Цвет



Цвет

Цветовая система AWT разрабатывалась так, чтобы была возможность работы со всеми цветами. После того, как цвет задан, Java отыскивает в диапазоне цветов дисплея тот, который ему больше всего соответствует. Вы можете запрашивать цвета в той семантике, к которой привыкли - как смесь красного, зеленого и голубого, либо как комбинацию оттенка, насыщенности и яркости. Вы можете использовать статические переменные класса Color.black для задания какого-либо из общеупотребительных цветов - black, white, red, green, blue, cyan, yellow, magenta, orange, pink, gray, darkGray и lightGray.

Для создания нового цвета используется один из трех описанных ниже конструкторов. Color(int, int, int)

Параметрами для этого конструктора являются три целых числа в диапазоне от 0 до 255 для красного, зеленого и голубого компонентов цвета. Color(int)

У этого конструктора - один целочисленный аргумент, в котором в упакованном виде заданы красный, зеленый и голубой компоненты цвета. Красный занимает биты 16-23, зеленый - 8-15, голубой - 0-7. Color(float, float, float)

Последний из конструкторов цвета, Color(float, float, float), принимает в качестве параметров три значения типа float (в диапазоне от 0.0 до 1.0) для красного, зеленого и голубого базовых цветов.



Date



Date

Класс Date используется для операций с датой и временем. Через него вы можете получить доступ к дате, месяцу, году, дню недели, часам, минутам, секундам. У объектов этого класса - несколько конструкторов. Самый простой - Date() - инициализирует объект текущими датой и временем. Три остальных конструктора предлагают дополнительные возможности задавать начальные значения для нового объекта. Date(year, month, date) - устанавливает указанную дату, при этом время устанавливается в 00:00:00 (полночь). Date(year, month, date, hours, minutes) - устанавливает указанные дату и время, секунды устанавливаются в 0. Date(year, month, date, hours, minutes, seconds) - наиболее полное задание времени, в объекте устанавливаются указанные дата и время, в том числе и секунды.