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


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 приводит к тому, что заданный его параметром документ отображается в главном окне браузера или фрейме.


Апплеты Java



Апплеты Java

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


Апплеты



Апплеты

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


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 с компонентом в каждой из названных областей. /* */ 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 (они всегда центрируются внутри кнопки). Позднее в данной главе речь пойдет о том, как нужно обрабатывать события, возникающие при нажатии и отпускании пользователем кнопки. Ниже приведен пример, в котором создаются три расположенные по вертикали кнопки. /* */ 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, который будет просто закрашивать себя серым цветом определенной насыщенности. Наш апплет будет создавать несколько таких объектов, каждый со своей интенсивностью серого цвета. /* */ 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 для получения подъема, снижения и длины строки, которую требуется нарисовать, и с помощью полученных значений отцентрируем ее в нашем апплете. /* * * * */ 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, задаваемое в этом примере исходное состояние соответствует отметке в первом объекте. /* */ 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. Ниже приведен пример, отличающийся от предыдущего тем, что теперь различные варианты выбора в нем взаимно исключают друг друга. /* */ 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. /* */ 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) - наиболее полное задание времени, в объекте устанавливаются указанные дата и время, в том числе и секунды.



  • Дейтаграммы



    Дейтаграммы

    Дейтаграммы, или пакеты протокола UDP (User Datagram Protocol) - это пакеты информации, пересылаемые в сети по принципу "fire-and-forget" (выстрелил и забыл). Если вам надо добиться оптимальной производительности, и вы в состоянии минимизировать затраты на проверку целостности
    UDP не предусматривает проверок и подтверждений при передаче информации. При передаче пакета UDP по какому-либо адресу нет никакой гарантии того, что он будет принят, и даже того, что по этому адресу вообще есть кому принимать такие пакеты. Аналогично, когда вы получаете дейтаграмму, у вас нет никаких гарантий, что она не была повреждена в пути или что ее отправитель все еще ждет от вас подтверждения ее получения.
    Java реализует дейтаграммы на базе протокола UDP, используя для этого два класса. Объекты класса DatagramPacket представляют собой контейнеры с данными, a DatagramSocket - это механизм, получении объектов DatagramPacket.


    Destroy



    destroy

    Метод destroy вызывается тогда, когда среда (например, браузер Netscape) решает, что апплет нужно полностью удалить из памяти. В этом методе нужно освободить все ресурсы, которые использовал апплет.


    Dictionary



    Dictionary

    Dictionary (словарь) - абстрактный класс, представляющий собой хранилище информации типа "ключ-значение". Ключ - это имя, по которому осуществляется доступ к значению. Имея ключ и значение, вы можете записать их в словарь методом put(key, value). Для получения значения по заданному ключу служит метод get(key). И ключи, и значения можно получить в форме перечисления (объект Enumeration) методами keys и elements. Метод size возвращает количество пар "ключ-значение", записанных в словаре, метод isEmpty возвращает true, если словарь пуст. Для удаления ключа и связанного с ним значения предусмотрен метод remove(key).


    Динамическое назначение методов



    Динамическое назначение методов

    Давайте в качестве примера рассмотрим два класса, у которых имеют простое родство подкласс / суперкласс, причем единственный метод суперкласса замещен в подклассе. class A { void callme() { System.out.println("Inside A's callrne method"); }} class В extends A { void callme() { System.out.println("Inside B's callme method"); }} class Dispatch { public static void main(String args[]) { A a = new B(); a.callme(); } }
    Обратите внимание - внутри метода main мы объявили переменную а класса А, а проинициализировали ее ссылкой на объект класса В. В следующей строке мы вызвали метод callme. При этом транслятор проверил наличие метода callme у класса А, а исполняющая система, увидев, что на самом деле в переменной хранится представитель класса В, вызвала не метод класса А, а callme класса В. Ниже приведен результат работы этой программы: С:\> Java Dispatch Inside B's calime method Совет
    Совет


    Программистам Delphi / C++ следует отметить, что все Java по умолчанию являются виртуальными функциями (ключевое слово virtual).
    Рассмотренная форма динамического полиморфизма времени выполнения представляет собой один из наиболее мощных механизмов объектно-ориентированного программирования, позволяющих писать надежный, многократно используемый код.


    Do-while



    do-while

    Иногда возникает потребность выполнить тело цикла по крайней мере один раз - даже в том случае, когда логическое выражение с самого начала принимает значение false. Для таких случаев в Java используется циклическая конструкция do-while. Ее общая форма записи такова: [ инициализация; ] do { тело; [итерация;] } while ( завершение );
    В следующем примере тело цикла выполняется до первой проверки условия завершения. Это позволяет совместить код итерации с условием завершения: class DoWhile { public static void main(String args[]) { int n = 10; do { System.out.println("tick " + n); } while (--n > 0); } }


    Double



    double

    В случае двойной точности, задаваемой с помощью ключевого слова double, для хранения значений используется 64 бита. Все трансцендентные математические функции, такие, как sin, cos, sqrt, возвращают результат типа double. double d; double pi = 3. 14159265358979323846;


    DrawArc и fillArc



    drawArc и fillArc

    Форма методов drawArc и fillArc следующая: drawArc(int x, int у, int width, int height, int startAngle, int sweepAngle)
    Эти методы вычерчивают (fillArc заполняет) дугу, ограниченную прямоугольником (x,y,width, height), начинающуюся с угла startAngle и имеющую угловой размер sweepAngle. Ноль градусов соответствует положению часовой стрелки на 3 часа, угол отсчитывается против часовой стрелки (например, 90 градусов соответствуют 12 часам, 180 - 9 часам, и так далее).


    DrawLine



    drawLine

    drawline(int x1, int у1, int х2, int у2) Этот метод вычерчивает отрезок прямой между точками с координатами (х1,у1) и (х2,у2). Эти линии представляют собой простые прямые толщиной в 1 пиксель. Поддержка разных перьев и разных толщин линий не предусмотрена.


    DrawPolyson и fillPolyson



    drawPolyson и fillPolyson

    Прототипы для этих методов: drawPolygon(int[], int[], int) fillPolygon(int[], int[], int)
    Метод drawPolygon рисует контур многоугольника (ломаную линию), задаваемого двумя массивами, содержащими х и у координаты вершин, третий параметр метода - число пар координат. Метод drawPolygon не замыкает автоматически вычерчиваемый контур. Для того, чтобы прямоугольник получился замкнутым, координаты первой и последней точек должны совпадать.


    DrawString



    drawString

    В предыдущих примерах использовался метод drawString(String, x, у). Этот метод выводит строку с использованием текущих шрифта и цвета. Точка с координатами (х,у) соответствует левой границе базовой линии символов, а не левому верхнему углу, как это принято в других методах рисования. Для того, чтобы понять, как при этом располагается описывающий строку прямоугольник, прочтите раздел о метрике шрифта в конце этой главы.


    Другие новые особенности A WT



    Другие новые особенности A WT

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


    EnsureCapacity



    ensureCapacity

    Если вы после создания объекта StringBuffer захотите зарезервировать в нем место для определенного количества символов, вы можете для установки размера буфера воспользоваться методом ensureCapacity. Это бывает полезно, когда вы заранее знаете, что вам придется добавлять к буферу много небольших строк.


    Фабричные методы



    Фабричные методы

    В классе InetAddress нет доступных пользователю конструкторов. Для создания объектов этого класса нужно воспользоваться одним из его фабричных методов. Фабричные методы - это обычные статические методы, которые возвращают ссылку на объект класса, которому они принадлежат. В данном случае, у класса InetAddress есть три метода, которые можно использовать для создания представителей. Это методы getLocalHost, getByName и
    В приведенном ниже примере выводятся адреса и имена локальной машины, локального почтового узла и WWW-узла компании, в которой работает автор. InetAddress Address = InetAddress.getLocalHost(); System.out.println(Address); Address = InetAddress.getByName("mailhost"); System.out.println(Address); InetAddress SW[] = InetAddress.getAllByNarne ("www.starwave.com"); System.out.println(SW);
    У класса InetAddress также есть несколько нестатических методов, которые можно использовать с объектами, возвращаемыми только что названными фабричными методами:
  • getHostName() возвращает строку, содержащую символическое имя узла, соответствующее хранящемуся в данном объекте адресу Internet.
  • getAddress() возвращает байтовый массив из четырех элементов, в котором в порядке, используемом в сети, записан адрес Internet, хранящийся в данном объекте.
  • toString() возвращает строку, в которой записано имя узла и его адрес.



  • Final



    final

    Все методы и переменные объектов могут быть замещены по умолчанию. Если же вы хотите объявить, что подклассы не имеют права замещать какие-либо переменные и методы вашего класса, вам нужно объявить их как final (в Delphi / C++ не писать слово virtual). final int FILE_NEW = 1;
    По общепринятому соглашению при выборе имен переменных типа final - используются только символы верхнего регистра (т.е. используются как аналог препроцерных констант C++). Использование final-методов порой приводит к выигрышу в скорости выполнения кода - поскольку они не могут быть замещены, транслятору ничто не мешает заменять их вызовы встроенным (in-line) кодом (байт-код копируется непосредственно в код вызывающего метода).


    Finalize



    finalize

    В Java существует возможность объявлять методы с именем finalize. Методы finalize аналогичны деструкторам в C++ (ключевой знак ~) и Delphi (ключевое слово destructor). Исполняющая среда Java будет вызывать его каждый раз, когда сборщик мусора соберется уничтожить объект этого класса.


    Finally



    finally

    Иногда требуется гарантировать, что определенный участок кода будет выпол-няться независимо от того, какие исключения были возбуждены и пере-хвачены. Для создания такого участка кода используется ключевое слово finally. Даже в тех случаях, когда в методе нет соответствующего воз-бужденному исключению раздела catch, блок finally будет выполнен до того, как управление перейдет к операторам, следующим за разделом try. У каждого раздела try должен быть по крайней мере или один раз-дел catch или блок finally. Блок finally очень удобен для закрытия файлов и освобождения любых других ресурсов, захваченных для времен-ного использования в начале выполнения метода. Ниже приведен пример класса с двумя методами, завершение которых происходит по разным причинам, но в обоих перед выходом выполняется код раздела finally. class FinallyDemo { static void procA() { try { System.out.println("inside procA"); throw new RuntimeException("demo"); } finally { System.out.println("procA's finally"); } } static void procB() { try { System.out.println("inside procB"); return; } finally { System.out.println("procB's finally"); } } public static void main(String args[]) { try { procA(); } catch (Exception e) {} procB(); } }
    В этом примере в методе procA из-за возбуждения исключения про-исходит преждевременный выход из блока try, но по пути вы-полняется раздел finally. Другой метод procB завершает работу выпол-нением стоящего в try-блоке оператора return, но и при этом перед выходом из метода выполняется программный код блока finally. Ниже приведен результат, полученный при выполнении этой программы. С:\> java FinallyDemo inside procA procA's finally inside procB procB's finally


    Float



    float

    В переменных с обычной, или одинарной точностью, объявляемых с помощью ключевого слова float, для хранения вещественного значения используется 32 бита. float f; float f2 = 3. 14F; // обратите внимание на F, //т.к. по умолчанию все литералы double


    FlowLayout



    FlowLayout

    Класс FlowLayout реализует простой стиль размещения, при котором компоненты располагаются, начиная с левого верхнего угла, слева направо и сверху вниз. Если в данную строку не помещается очередной компонент, он располагается в левой позиции новой строки. Справа, слева, сверху и снизу компоненты отделяются друг от друга небольшими промежутками. Ширину этого промежутка можно задать в конструкторе FlowLayout. Каждая строка с компонентами выравнивается по левому или правому краю, либо центрируется в зависимости от того, какая из констант LEFT, RIGHT или CENTER была передана конструктору. Режим выравнивания по умолчанию - CENTER, используемая по умолчанию ширина промежутка - 5 пикселей.
    Ниже приведен пример, в котором в Panel включается несколько компонентов Label. Объект Panel использует FlowLayout с выравниванием RIGHT. /* */ import java.awt.*; import java.applet.*; import java.util.*; public class FlowLayoutDemo extends Applet { public void init() { setLayout(new FlowLayout(FlowLayout.RIGHT, 10, 3)); int width = Integer.parseInt(getParameter("width")); int height = Integer.parseInt(getParameter("height")); String val = "Data is not information " + "is not knowledge is not wisdom."; StringTokenizer st = new StringTokenizer(val); while (st.hasMoreTokens()) { add(new Button(st.nextToken())); } } }
    Необходимо вызвать пример для двух различных размеров - FlowLayoutDemo1.html, FlowLayoutDemo2.html для того, чтобы проиллюстрировать, как объекты Label перетекают из строки в строку, и при этом строки выравниваются по правому краю (или Вы можете изменять размеры окнa appletViewer).


    For



    for

    В этом операторе предусмотрены места для всех четырех частей цикла. Ниже приведена общая форма оператора записи for. for ( инициализация; завершение; итерация ) тело;
    Любой цикл, записанный с помощью оператора for, можно записать в виде цикла while, и наоборот. Если начальные условия таковы, что при входе в цикл условие завершения не выполнено, то операторы тела и итерации не выполняются ни одного раза. В каноническая форме цикла for происходит увеличение целого значения счетчика с минимального значения до определенного предела. class ForDemo { public static void main(String args[]) { for (int i = 1; i
    Следующий пример - вариант программы, ведущей обратный отсчет. class ForTick { public static void main(String args[]) { for (int n = 10; n > 0; n--) System.out.println("tick " + n); } }
    Обратите внимание - переменные можно объявлять внутри раздела инициализации оператора for. Переменная, объявленная внутри оператора for, действует в пределах этого оператора.
    А вот - новая версия примера с временами года, в которой используется оператор for. class Months { static String months[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; static int monthdays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; static String spring = "spring"; static String summer = "summer"; static String autumn = "autumn"; static String winter = "winter"; static String seasons[] = { winter, winter, spring, spring, spring, summer, summer, summer, autumn, autumn, autumn, winter }; public static void main(String args[]) { for (int month = 0; month < 12; month++) { System.out.println(months[month] + " is a " + seasons[month] + " month with " + monthdays[month] + " days."); } } }
    При выполнении эта программа выводит следующие строки: С:\> Java Months January is a winter month with 31 days. February is a winter month with 28 days. March is a spring month with 31 days. April is a spring month with 30 days. May is a spring month with 31 days. June is a summer month with 30 days. July is a summer month with 31 days. August is a summer month with 31 days. September is a autumn month with 30 days. October is a autumn month with 31 days. November is a autumn month with 30 days. December a winter month with 31 days.


    Frame



    Frame

    Frame - это как раз то, что обычно и считают окном на рабочей поверхности экрана. У объекта Frame есть строка с заголовком, управляющие элементы для изменения размера и линейка меню. Для того, чтобы вывести/спрятать изображение объекта Frame, нужно использовать методы show и hide. Ниже приведен пример апплета, который показывает объект Frame с содержащимся в нем компонентом TextArea. /* */ import java.awt.*; import java.applet.*; public class FrameDemo extends Applet { public void init() { int width = Integer.parseInt(getParameter("width")); int height = Integer.parseInt(getParameter("height")); String val = "There are two ways of constructing " + "a software design.\n" + "One way is to make it so simple\n" + "that there are obviously no deficiencies.\n" + "And the other way is to make it so complicated" + "that there are no obvious deficiencies.\n\n" + "C.A.R. Hoare\n\n"; TextArea text = new TextArea(val, 80, 40); Frame f = new Frame("Demo Frame"); f.setSize(width, height); f.add("Center", text); f.show(); } }


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



    get и set

    Класс Date включает в себя набор методов для получения и установки отдельных атрибутов, хранящихся в объекте. Каждая из функций семейства get - getYear, getMonth, getDate, getDay, getHours, getMi-nutes и getSeconds - возвращает целое значение. Каждой из функций семейства set - setYear, setMonth, setDate, setHours, setMinutes и setSeconds - в качестве параметра передается целое значение. Вы также можете получить представление объекта Date в виде значения типа long с помощью метода getTime. Возвращаемое этим методом значение представляет собой число миллисекунд, прошедших после 1 января 1970 года.


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



    getAscent, getDescent, getHeight

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


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



    getDocumentBase и getCodeBase

    Возможно, Вы будете писать апплеты, которым понадобится явно загружать данные и текст. Java позволяет апплету загружать данные из каталога, в котором располагается HTML-документ, запустивший апплет (база документа - getDocumentBase), и из каталога, из которого был загружен class-файл с кодом апплета (база кода - getCodeBase).


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



    getFamily и getName

    Метод getFamily возвращает строку с именем семейства шрифтов. С помощью метода getName можно получить логическое имя шрифта.


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



    getMaxAscent и getMaxDescent

    Эти методы служат для получения максимальных подъема и снижения всех символов в шрифте.


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



    getSize

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


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



    getStyle

    Этот метод возвращает целое число, соответствующее стилю шрифта. Полученный результат можно побитово сравнить со статическими переменными класса Font: - PLAIN, BOLD и ITALIC.


    Обработка исключений



    Глава 10 - Обработка исключений

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


    Легковесные процессы и синхронизация.



    Глава 11 - Легковесные процессы и синхронизация.

    Параллельное программирование, связанное с использованием легковесных процессов, или подпроцессов (multithreading, light-weight processes) — концептуальная парадигма, в которой вы разделяете свою программу на два или несколько процессов, которые могут исполняться одновременно. Замечание
    Замечание


    Во многих средах параллельное выполнение заданий представлено в том виде, который в операционных системах называется многозадачностью. Это совсем не то же самое, что параллельное выполнение подпроцессов. В многозадачных операционных системах вы имеете дело с полновесными процессами, в системах с параллельным выполнением подпроцессов отдельные задания называются легковесными процессами (light-weight processes, threads).


    Утилиты



    Глава 12 - Утилиты

    Библиотека классов языка включает в себя набор вспомогательных классов, широко используемых в других встроенных пакетах Java. Эти классы расположены в пакетах java.lang и java.util. Они используются для работы с наборов объектов, взаимодействия с системными функциями низкого уровня, для работы с математическими функциями, генерации случайных чисел и манипуляций с датами и временем.


    Сетевые средства



    Глава 14 - Сетевые средства

    Эта глава посвящена описанию пакета java.net. Java поддерживает протокол TCP/IP, во-первых, расширяя свой интерфейс потоков ввода-вывода, описанного в предыдущей главе, и во вторых, добавляя возможности, необходимые для построения объектов ввода-вывода при работе в сети.


    Апплеты



    Глава 15 - Апплеты

    Апплеты - это маленькие приложения, которые размещаются на серверах Internet, транспортируются клиенту по сети, автоматически устанавливаются и запускаются на месте, как часть документа HTML. Когда апплет прибывает к клиенту, его доступ к ресурсам ограничен.
    Ниже приведен исходный код канонической программы HelloWorld, оформленной в виде апплета: import java.awt.*; import java.applet.*; public class HelloWorldApplet extends Applet { public void paint(Graphics g) { g.drawString("Hello World!", 20, 20); } }
    Этот апплет начинается двумя строками, которые импортируют все пакеты иерархий java.applet и java.awt. Дальше в нашем примере присутствует метод paint, замещающий одноименный метод класса Applet. При вызове этого метода ему передается аргумент, содержащий ссылку на объект класса Graphics. Последний используется для прорисовки нашего апплета. С помощью метода drawString, вызываемого с этим объектом типа Graphics, в позиции экрана (20,20) выводится строка "Hello World".
    Для того, чтобы с помощью браузера запустить этот апплет, нам придется написать несколько строк html-текста.
    Вы можете поместить эти строки в отдельный html-файл (HelloWorldApplet.html), либо вставить их в текст этой программы в виде комментария и запустить программу appletviewer с его исходным текстом в качестве аргумента.


    Набор абстракций для работы с окнами



    Глава 16 - Набор абстракций для работы с окнами

    Трудность при создании независимой от платформы библиотеки заключается в том, что ее разработчикам либо приходится требовать, чтобы все приложения на всех платформах вели себя и выглядели одинаково, либо для поддержки, скажем, трех различных разновидностей интерфейса приходится писать в три раза больше кода. Существуют два взгляда на эту проблему. Один подход заключается в том, что упор делается на графику низкого уровня - рисование пикселей, при этом разработчики библиотеки сами заботятся о внешнем виде каждого компонента. При другом подходе создаются абстракции, подходящие для библиотек каждой из операционных систем, и именно "родные" пакеты данной операционной системы служат подъемной силой для архитектурно-нейтральной библиотеки на каждой из платформ. В Java при создании библиотеки Abstraction Window Toolkit (AWT) выбран второй подход.
    Классы Graphics и Fonts мы уже обсуждали в главе 15. В главе 18 будут обсуждаться различные возможности работы с изображениями. В данной главе мы пройдемся по базовой архитектуре AWT, касающейся интерфейсных объектов.


    Модели обработки событий.



    Глава 17 - Модели обработки событий.

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


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



    Глава 18 - Работа с изображениями

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


    Введение в язык Java



    Глава 3 - Введение в язык Java

    Исходный файл на языке Java - это текстовый файл, содержащий в себе одно или несколько описаний классов. Транслятор Java предполагает, что исходный текст программ хранится в файлах с расширениями Java. Получаемый в процессе трансляции код для каждого класса записывается в отдельном выходном файле, с именем совпадающем с именем класса, и расширением class.
    Прежде всего, в этой главе мы напишем, оттранслируем, и запустим каноническую программу "Hello World". После этого мы рассмотрим все существенные лексические элементы, воспринимаемые Java-транслятором: пробелы, комментарии, ключевые слова, идентификаторы, литералы, операторы и разделители. К концу главы вы получите достаточно информации для того чтобы самостоятельно ориентироваться в хорошей Java-программе.


    Типы



    Глава 4 - Типы

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


    Операторы



    Глава 5 - Операторы

    Операторы в языке Java - это специальные символы, которые сообщают транслятору о том, что вы хотите выполнить операцию с некоторыми операндами. Некоторые операторы требуют одного операнда, их называют унарными. Одни операторы ставятся перед операндами и называются префиксными, другие - после, их называют постфиксными операторами. Большинство же операторов ставят между двумя операндами, такие операторы называются инфиксными бинарными операторами. Существует тернарный оператор, работающий с тремя операндами.
    В Java имеется 44 встроенных оператора. Их можно разбить на 4 класса - арифметические, битовые, операторы сравнения и логические.


    Управление выполнением программы



    Глава 6 - Управление выполнением программы

    Управление в Java почти идентично средствам, используемым в С и C++.


    Классы



    Глава 7 - Классы

    Базовым элементом объектно-ориентированного программирования в языке Java является класс. В этой главе Вы научитесь создавать и расширять свои собственные классы, работать с экземплярами этих классов и начнете использовать мощь объектно-ориентированного подхода. Напомним, что классы в Java не обязательно должны содержать метод main. Единственное назначение этого метода - указать интерпретатору Java, откуда надо начинать выполнение программы. Для того, чтобы создать класс, достаточно иметь исходный файл, в котором будет присутствовать ключевое слово class, и вслед за ним - допустимый идентификатор и пара фигурных скобок для его тела. class Point { } Замечание
    Замечание


    Имя исходного файла Java должно соответствовать имени хранящегося в нем класса. Регистр букв важен и в имени класса, и в имени файла.
    Как вы помните из главы 2, класс - это шаблон для создания объекта. Класс определяет структуру объекта и его методы, образующие функциональный интерфейс. В процессе выполнения Java-программы система использует определения классов для создания представителей классов. Представители являются реальными объектами. Термины , и взаимозаменяемы. Ниже приведена общая форма определения класса. class имя_класса extends имя_суперкласса { type переменная1_объекта: type переменная2_объекта: type переменнаяN_объекта: type имяметода1(список_параметров) { тело метода; } type имяметода2(список_параметров) { тело метода; } type имя методаМ(список_параметров) { тело метода; } }
    Ключевое слово extends указывает на то, что - это подкласс класса . Во главе классовой иерархии Java стоит единственный ее встроенный класс - Object. Если вы хотите создать подкласс непосредственно этого класса, ключевое слово extends и следующее за ним имя суперкласса можно опустить - транслятор включит их в ваше определение автоматически. Примером может служить класс Point, приведенный ранее.


    Пакеты и интерфейсы



    Глава 8 - Пакеты и интерфейсы

    Пакет (package) - это некий контейнер, который используется для того, чтобы изолировать имена классов. Например, вы можете создать класс List, заключить его в пакет и не думать после этого о возможных конфликтах, которые могли бы возникнуть если бы кто-нибудь еще создал класс с именем List.
    Интерфейс - это явно указанная спецификация набора методов, которые должны быть представлены в классе, который реализует эту спецификацию. Реализация же этих методов в интерфейсе отсутствует. Подобно абстрактным классам интерфейсы обладают замечательным дополнительным свойством - их можно многократно наследовать. Конкретный класс может быть наследником лишь одного суперкласса, но зато в нем может быть реализовано неограниченное число интерфейсов.


    Работа со строками



    Глава 9 - Работа со строками

    В этой главе обсуждаются средства языка Java для работы со строками. В язы-ках С и C++ отсутствует встроенная поддержка такого объекта, как строка. В них при необхо-димости передается адрес последовательности байтов, содержимое которых трактуется как символы до тех пор, пока не будет встречен нулевой байт, отмечающий конец строки. В пакет java.lang встроен класс, инкапсулирующий структуру данных, соответ-ствующую строке. Этот класс, называемый String, не что иное, как объ-ектное представление неизменяемого символьного массива. В этом классе есть методы, которые позволяют сравнивать строки, осуществлять в них поиск и извлекать определенные символы и подстроки. Класс StringBuffer используется тогда, когда строку после создания требу-ется изменять.


    Глобальные переменные



    Глобальные переменные

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


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



    Goto

    Другая не слишком хорошая конструкция традиционных языков программирования - оператор goto, предназначенный для передачи управления. Всем нам на первых занятиях по программированию говорили, что можно обойтись без этого оператора, ухудшающего структуру программы и делающего ее неудобочитаемой. До того, как в C++ появился механизм работы с исключениями, goto активно использовался для выхода из циклов в исключительных ситуациях.
    В Java оператора goto нет. В ней есть зарезервированное ключевое слово goto, но это сделано лишь во избежание возможной путаницы - для того, чтобы удержать программистов от его использования. Зато в Java есть операторы continue и break с меткой, восполняющие отсутствие goto в тех единственных случаях, когда использование последнего было бы оправдано. А мощный хорошо определенный встроенный в Java механизм исключений делает ненужным использование goto во всех остальных ситуациях.


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



    GridLayout

    Класс GridLayout размещает компоненты в простой равномерной сетке. Конструктор этого класса позволяет задавать количество строк и столбцов. Ниже приведен пример, в котором GridLayout используется для создания сетки 4х4, 15 квадратов из 16 заполняются кнопками, помеченными соответствующими индексами. Как вы уже, наверное, поняли, это - панель для игры в "пятнашки". /* */ import java.awt.*; import java.applet.*; public class GridLayoutDemo extends Applet { static final int n = 4; public void init() { setLayout(new GridLayout(n, n)); setFont(new Font("Helvetica", Font.BOLD, 24)); int width = Integer.parseInt(getParameter("width")); int height = Integer.parseInt(getParameter("height")); for (int i=0;i0) add(new Button(""+k)); } } } }


    HashTable



    HashTable

    HashTable - это подкласс Dictionary, являющийся конкретной реализацией словаря. Представителя класса HashTable можно использовать для хранения произвольных объектов, причем для индексации в этой коллекции также годятся любые объекты. Наиболее часто HashTable используется для хранения значений объектов, ключами которых служат строки (то есть объекты типа String). В очередном нашем примере в HashTable хранится информация об этой книге. import java.util.Dictionary; import java.util.Hashtable; class HTDemo { public static void main(String args[]) { Hashtable ht = new Hashtable(); ht.put("title", "The Java Handbook"); ht.put("author", "Patrick Naugnton"); ht.put("email", "naughton@starwave.com"); ht.put("age", new Integer(30)); show(ht); } static void show(Dictionary d) { System.out.println("Title: " + d.get("title")); System.out.println("Author: " + d.get("author")); System.out.println("Email: " + d.get("email")); System.out.println("Age: " + d.get("age")); } }
    Результат работы этого примера иллюстрирует тот факт, что метод show, параметром которого является абстрактный тип Dictionary, может извлечь все значения, которые мы занесли в ht внутри метода main. С:\> java HTDemo Title: The Java Handbook Author: Patrick Naughton Email: naughton@starwave.com Age: 30


    HEIGHT = pixels



    HEIGHT = pixels

    WIDTH и HEIGHT - обязательные атрибуты, задающие начальный размер видимой области апплета.


    Hello World



    Hello World

    Итак, вот ваша первая Java-программа: class HelloWorld { public static void main (String args []) { System. out. println ("Hello World"); } }
    Для того, чтобы поработать с приведенными в книге примерами вам нужно получить по сети из Sun Microsystems и установить Java Developers Kit - пакет для разработки Java-приложений (http://java.sun.com/products/jdk).
    Язык Java требует, чтобы весь программный код был заключен внутри поименованных классов. Приведенный выше текст примера надо записать в файл HelloWorld.java. Обязательно проверьте соответствие прописных букв в имени файла тому же в названии содержащегося в нем класса. Для того, чтобы оттранслировать этот пример необходимо запустить транслятор Java - javac, указав в качестве параметра имя файла с исходным текстом: С: \> javac HelloWorld.Java
    Транслятор создаст файл HelloWorld.class с независимым от процессора байт-кодом нашего примера. Для того, чтобы исполнить полученный код, необходимо иметь среду времени выполнения языка Java (в нашем случае это программа java), в которую надо загрузить новый класс для исполнения. Подчеркнем, что указывается имя класса, а не имя файла, в котором этот класс содержится. С: > java HelloWorld Hello World
    Полезного сделано мало, однако мы убедились, что установленный Java-транслятор и среда времени выполнения работают.


    Хрупкие типы данных



    Хрупкие типы данных

    C++ получил в наследство от С все обычные типы данных последнего. Эти типы служат для представления целых и вещественных чисел различных размеров и точности. К несчастью, реальный диапазон и точность этих типов колеблется в зависимости от конкретной реализации транслятора. Поведение кода, который прекрасно транслируется и выполняется на одной машине, может радикально отличаться при смене платформы. Различные трансляторы C++ могут резервировать под целый тип 16, 32 или 64 бита в зависимости от разрядности машинного слова.
    В Java эта проблема решена, поскольку, как вы увидите в главе 4, в ней для всех базовых числовых типов независимо используются определенные соглашения, не зависящие от конкретной реализации среды. Не исключено, что на некоторых архитектурах реализовать работу с числами таких размеров в интерпретаторе Java окажется трудно, либо реализация будет неэффективна, однако это единственный способ гарантировать воспроизводимые результаты на широком спектре платформ.


    Идентификаторы



    Идентификаторы

    Идентификаторы используются для именования классов, методов и переменных. В качестве идентификатора может использоваться любая последовательность строчных и прописных букв, цифр и символов _ (подчеркивание) и $ (доллар). Идентификаторы не должны начинаться с цифры, чтобы транслятор не перепутал их с числовыми литеральными константами, которые будут описаны ниже. Java - язык, чувствительный к регистру букв. Это означает, что, к примеру, Value и VALUE - различные идентификаторы.


    ImageFilter и ImageFilterSource



    ImageFilter и ImageFilterSource

    Подклассы классов ImageFilter и ImageFilterSource используются совместно для создания новых изображений фильтрованием уже существующих. С двумя такими подклассами из пакета java.awt.image вы сейчас познакомитесь.


    ImageObserver



    ImageObserver

    ImageObserver - это абстрактный интерфейс, используемый для получения сообщения о создании изображения, Метод imageUpdate из ImageObserver - это все, что вы должны реализовать в своем апплете для его использования. В то время, как вы получаете информацию о загрузке, вы можете показывать любую понравившуюся вам мультипликацию, индикатор степени завершения загрузки или любую другую заставку. Для использования ImageObserver в своем подклассе Applet вы должны добавить в него строку implement ImageObserver, как показано в этом фрагменте программы: public class MyApplet extends Applet implement ImageObserver {
    Затем вам придется вставить в свой класс метод imageUpdate для интерфейса ImageObserver, как показано в следующем фрагменте : public boolean imageUpdate(Image img, int status, int x, int у int width, int height) { if((status & ALLBITS) != 1) { System.out.println("Still processing the image"); return true; } else { System.out.println("Done processing the image"); return false; } }
    Метод imageUpdate вызывается с изображением Image, которое находится в процессе изменения, целым параметром status, отражающим состояние изменения, и с координатами прямоугольника (x, у, width, height), которые соответствуют различным величинам в зависимости от информационных флагов, перечисленных ниже. ImageUpdate должен возвращать false по окончании загрузки изображения и true - если изображение еще обрабатывается.
    Целая переменная status поразрядно проверяется на наличие одного или нескольких флагов. Возможные флаги и информация, которую они несут, перечислены ниже:
    WIDTH Ширина изображения доступна и может быть взята из аргумента width.
    HEIGHT Высота изображения доступна и может быть взята из аргумента height.
    PROPERTIES Свойства изображения теперь доступны. Вы можете получить их посредством art.properties.
    SOMEBITS Доступны пиксели, необходимые для рисования масштабированного варианта изображения. Область, содержащая новые пиксели, задается параметрами x, у, width и height.
    FRAMEBITS Еще один кадр ранее нарисованного изображения с несколькими кадрами, готов для перерисовки. Параметры x, у, width, height не содержат информации.
    ALLBITS Обработка перерисовываемого изображения окончена, и оно может быть отрисовано в конечном виде. Значения аргументов x, у, width и height не содержат значимой информации.
    ERROR При пересылке изображения возникла ошибка. Поступление дальнейшей информации стало невозможным и рисование прервано. Для удобства выставляется и флаг ABORT для индикации прерывания загрузки изображения.
    ABORT Пересылка изображения была прервана до полного его получения. Поступление новой информации стало невозможным без дополнительных действий по повторному запуску операций по получению изображения. Если флаг ERROR не был выставлен, то приход любых данных изображения снова запустит процесс его получения.
    Теперь давайте рассмотрим программный пример, который использует ImageObserver для показа количества обработанных строк изображения и выводит эту информацию (переменная progress) на консоль: /* ObservedImageLoad * * * */ import java.applet.*; import java.awt.*; import java.awt.image.*; public class ObservedImageLoad extends Applet implements Runnable, ImageObserver { Image art; Dimension d; int progress; Thread motor; boolean loaded; public void init() { art = getImage(getDocumentBase(), getParameter("img")); loaded = false; progress = 0; } public void paint(Graphics g) { d = this.getSize(); loaded = g.drawImage(art, 0, 0, this); } public boolean imageUpdate(Image img, int info, int x, int y, int width, int height) { if((info & ALLBITS) != 1) { if(progress Метод imageUpdate обрабатывает статус загрузки изображения. Информация о статусе передается через переменную info, с которой сравнивается статическая переменная ALLBITS. Если еще не получено все изображение, то мы добавляем величину heihgt к общему числу обработанных строк изображения. Для проверки этой концепции мы выводим количество обработанных строк изображения на консоль. Метод run перерисовывает апплет пять раз в секунду (каждые 200 миллисекунд) до тех пор, пока изображение art не загрузится. То, как долго монитор статуса загрузки будет работать, зависит от скорости передачи данных изображения по сети - ObservedImageLoad.html.


    ImageProducer



    ImageProducer

    ImageProducer - это абстрактный интерфейс для объектов, которые готовят данные для Image. Объект, который реализует интерфейс ImageProducer, должен предоставлять массивы целых или байтовых переменных, представляющих собой данные изображений. Давайте познакомимся с очень полезным классом MemoryImageSource, реализующий ImageProducer. Мы создадим новый объект Image из данных, которые сгенерировал ImageProducer.


    IndexOf и lastIndexOf



    indexOf и lastIndexOf

    В класс String включена поддержка поиска определенного символа или подстроки, для этого в нем имеются два метода - indexOf и lastIndexOf. Каждый из этих методов возвращает индекс того символа, который вы хотели найти, либо индекс начала ис-комой подстроки. В любом случае, если поиск оказался неудачным ме-тоды возвращают значение -1. В очередном примере показано, как пользоваться различными вариантами этих методов поиска. class indexOfDemo { public static void main(String args[]) { String s = "Now is the time for all good men " + "to come to the aid of their country " + "and pay their due taxes."; System.out.println(s); System.out.println("indexOf(t) = " + s.indexOf('f')); System.out.println("lastlndexOf(t) = " + s.lastlndexOf('f')); System.out.println("indexOf(the) = " + s.indexOf("the")); System.out.println("lastlndexOf(the) = " + s.lastlndexOf("the")); System.out.println("indexOf(t, 10) = " + s.indexOf('f' , 10)); System.out.println("lastlndexOf(t, 50) = " + s.lastlndexOf('f' , 50)); System.out.println("indexOf(the, 10) = " + s.indexOf("the", 10)); System.out.println("lastlndexOf(the, 50) = " + s.lastlndexOf("the", 50)); } }
    Ниже приведен результат работы этой программы. Обратите внимание на то, что индексы в строках начинаются с нуля. С:> java indexOfDemo Now is the time for all good men to come to the aid of their country and pay their due taxes. indexOf(t) = 7 lastlndexOf(t) = 87 indexOf(the) = 7 lastlndexOf(the) = 77 index0f(t, 10) = 11 lastlndex0f(t, 50) = 44 index0f(the, 10) = 44 lastlndex0f(the, 50) = 44


    InetAddress



    InetAddress

    Java поддерживает адреса абонентов, принятые в Internet, с помощью класса InetAddress. Для адресации в Internet используются служебные функции, работающие с обычными, легко запоминающимися символическими именами, эти функции преобразуют символические имена в 32-битные адреса.


    Init



    init

    Метод init вызывается первым. В нем вы должны инициализировать свои переменные.


    Insert



    insert

    Метод insert идентичен методу append в том смысле, что для каждого возможного типа данных существует своя совмещенная версия этого ме-тода. Правда, в отличие от append, он не добавляет символы, возвра-щаемые методом String.valueOf, в конец объекта StringBuffer, а встав-ляет их в определенное место в буфере, задаваемое первым его параметром. В очередном нашем примере строка "there" вставляется между "hello" и "world!". class insertDemo { public static void main(String args[]) { StringBuffer sb = new StringBuffer("hello world !"); sb.insert(6,"there "); System.out.println(sb); } }
    При запуске эта программа выводит следующую строку: С:\> java insertDemo hello there world!
    Без строк не обойдешься
    Почти любой аспект программирования в Java на каком либо этапе подразумевает использование классов String и StringBuffer. Они понадо-бятся и при отладке, и при работе с текстом, и при указании имен фай-лов и адресов URL в качестве параметров методам. Каждый второй байт большинства строк в Java - нулевой (Unicode пока используется редко). То, что строки в Java требуют вдвое больше памяти, чем обыч-ные ASCII, не очень пугает, пока вам для эффективной работы с текстом в редакторах и других подобных приложениях не придется напрямую работать с огромным массивом типа char.


    Insets



    Insets

    Класс Insets используется для того, чтобы вставлять в объект Panel границы, напоминающие горизонтальные и вертикальные промежутки между объектами, которые делает диспетчер размещения. Для того, чтобы добиться вставки границ в объект Panel, нужно заместить метод Insets реализацией, возвращающей новый объект Insets с четырьмя целыми значениями, соответствующими ширине верхнего, нижнего, левого и правого краев. public Insets insets() { return new Insets(10, 10, 10, 10); }


    Int



    int

    Тип int служит для представления 32-битных целых чисел со знаком. Диапазон допустимых для этого типа значений - от -2147483648 до 2147483647. Чаще всего этот тип данных используется для хранения обычных целых чисел со значениями, достигающими двух миллиардов. Этот тип прекрасно подходит для использования при обработке массивов и для счетчиков. В ближайшие годы этот тип будет прекрасно соответствовать машинным словам не только 32-битовых процессоров, но и 64-битовых с поддержкой быстрой конвейеризации для выполнения 32-битного кода в режиме совместимости. Всякий раз, когда в одном выражении фигурируют переменные типов byte, short, int и целые литералы, тип всего выражения перед завершением вычислений приводится к int. int i; int j = 0x55aa0000;


    Integer и Long



    Integer и Long

    Класс Integer - класс-оболочка для чисел типов int, short и byte, a класс Long - соответственно для типа long. Помимо наследуемых методов своего суперкласса Number, классы Integer и Long содержат методы для разбора текстового представления чисел, и наоборот, для представления чисел в виде текстовых строк. Различные варианты этих методов позволяют указывать основание (систему счисления), используемую при преобразовании. Обычно используются двоичная, восьмеричная, десятичная и шестнадцатиричная системы счисления.
  • parseInt(String) преобразует текстовое представление целого числа, содержащееся в переменной String, в значение типа int. Если строка не содержит представления целого числа, записанного в допустимом формате, вы получите исключение NumberFormatException.
  • parseInt(String, radix) выполняет ту же работу, что и предыдущий метод, но в отличие от него с помощью второго параметра вы можете указывать основание, отличное от 10.
  • toString(int) преобразует переданное в качестве параметра целое число в текстовое представление в десятичной системе.
  • toString(int, radix) преобразует переданное в качестве первого параметра целое число в текстовое представление в задаваемой вторым параметром системе счисления.



  • Интерактивность



    Интерактивность

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


    Интерфейс Enumeration



    Интерфейс Enumeration

    Enumeration - простой интерфейс, позволяющий вам обрабатывать элементы любой коллекции объектов. В нем задается два метода. Первый из них - метод hasMoreElements, возвращающий значение типа boolean. Он возвращает значение true, если в перечислении еще остались элементы, и false, если у данного элемента нет следующего. Второй метод - nextElement - возвращает обобщенную ссылку на объект класса Object, которую, прежде чем использовать, нужно преобразовать к реальному типу содержащихся в коллекции объектов.
    Ниже приведен пример, в котором используется класс Enum, реализующий перечисление объектов класса Integer, и класс EnumerateDemo, создающий объект типа Enum, выводящий все значения перечисления. Обратите внимание на то, что в объекте Enum не содержится реальных данных, он просто возвращает последовательность создаваемых им объектов Integer. import java.util.Enumeration; class Enum implements Enumeration { private int count = 0; private boolean more = true; public boolean hasMoreElements() { return more; } public Object nextElement() { count++; if (count > 4) more = false; return new Integer(count); } } class EnumerateDemo { public static void main(String args[]) { Enumeration enum = new Enum(); while (enum.hasMoreElements()) { System.out.println(enum.nextElement()); } } }
    Вот результат работы этой программы: С:\> java EnumerateDemo 1 2 3 4 5 Vector
    Vector - это способный увеличивать число своих элементов массив ссылок на объекты. Внутри себя Vector реализует стратегию динамического расширения, позволяющую минимизировать неиспользуемую память и количество операций по выделению памяти. Объекты можно либо записывать в конец объекта Vector с помощью метода addElement, либо вставлять в указанную индексом позицию методом insertElementAt. Вы можете также записать в Vector массив объектов, для этого нужно воспользоваться методом copyInto. После того, как в Vector записана коллекция объектов, можно найти в ней индивидуальные элементы с помощью методов Contains, indexOf и lastIndexOf. Кроме того методы еlеmentAt, firstElement и lastElement позволяют извлекать объекты из нужного положения в объекте Vector.


    Интерфейсы



    Интерфейсы

    Интерфейсы Java созданы для поддержки динамического выбора (resolution) методов во время выполнения программы. Интерфейсы похожи на классы, но в отличие от последних у интерфейсов нет переменных представителей, а в объявлениях методов отсутствует реализация. Класс может иметь любое количество интерфейсов. Все, что нужно сделать - это реализовать в классе полный набор методов всех интерфейсов. Сигнатуры таких методов класса должны точно совпадать с сигнатурами методов реализуемого в этом классе интерфейса. Интерфейсы обладают своей собственной иерархией, не пересекающейся с классовой иерархией наследования. Это дает возможность реализовать один и тот же интерфейс в различных классах, никак не связанных по линии иерархии классового наследования. Именно в этом и проявляется главная сила интерфейсов. Интерфейсы являются аналогом механизма множественного наследования в C++, но использовать их намного легче.


    Интерпретация плюс высокая производительность



    Интерпретация плюс высокая производительность Необычайная способность Java исполнять свой код на любой из поддерживаемых платформ достигается тем, что ее программы транслируются в некое промежуточное представление, называемое байт-кодом (bytecode). Байт-код, в свою очередь, может интерпретироваться в любой системе, в которой есть среда времени выполнения Java. Большинство ранних систем, в которых пытались обеспечить независимость от платформы, обладало огромным недостатком — потерей производительности (Basic, Perl). Несмотря на то, что в Java используется интерпретатор, байт-код легко переводится непосредственно в “родные” машинные коды (Just In Time compilers) “на лету”. При этом достигается очень высокая производительность (Symantec JIT встроен в Netscape Navigator).
    Простота изучения


    Язык Java, хотя и более сложный чем языки командных интерпретаторов, все же неизмеримо проще для изучения, чем другие другие языки программирования, например C++. Черты языка станут казаться вам естественным путем для решения тех или иных задач и будут способствовать отработке хорошего стиля программирования. Поскольку объектная модель в Java одновременно проста и выразительна, вы скоро освоитесь с объектно-ориентированным стилем создания программ.


    IsBold, isItalic, isPlain



    isBold, isItalic, isPlain

    Эти методы возвращают true в том случае, если стиль шрифта - полужирный (bold), курсив (italic) или обычный (plain), соответственно.


    Исключения



    Исключения

    Последний способ вызвать передачу управления при выполнении кода - использование встроенного в Java механизма обработки исключительных ситуаций. Для этой цели в языке предусмотрены операторы try, catch, throw и finally. Глава 10 целиком посвящена изучению механизма обработки исключительных ситуаций.


    Использование пакетов



    Использование пакетов

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


    Использование шрифтов



    Использование шрифтов

    Конструктор класса Font создает новый шрифт с указанным именем, стилем и размером в пунктах: Font StrongFont = new Font("Helvetica", Font.BOLD|Font.ITALIC, 24);
    В настоящее время доступны следующие имена шрифтов: Dialog, Helvetica, TimesRoman, Courier и Symbol. Для указания стиля шрифта внутри данного семейства предусмотрены три статические переменные. - Font.PLAIN, Font.BOLD и Font.ITALIC, что соответствует обычному стилю, курсиву и полужирному.
    Теперь давайте посмотрим на несколько дополнительных методов.


    История создания



    История создания

    Язык Java зародился как часть проекта создания передового программного обеспечения (ПО) для различных бытовых приборов. Реализация проекта была начата на языке С++, но вскоре возник ряд проблем, наилучшим средством борьбы с которыми было изменение самого инструмента - языка программирования. Стало очевидным, что необходим платформо-независимый язык программирования, позволяющий создавать программы, которые не приходилось бы компилировать отдельно для каждой архитектуры и можно было бы использовать на различных процессорах под различными операционными системами.
    Рождению языка Java предшествовала довольно интересная история. В 1990 году разработчик ПО компании Sun Microsystems Патрик Нотон (Patrick Naughton) понял, что ему надоело поддерживать сотни различных интерфейсов программ, используемых в компании, и сообщил исполнительному директору Sun Microsystems и своему другу Скотту МакНили (Scott McNealy) о своем намерении перейти работать в компанию NeXT. МакНили, в свою очередь, попросил Нотона составить список причин своего недовольства и выдвинуть такое решение проблем, как если бы он был Богом и мог исполнить все, что угодно.
    Нотон, хотя и не рассчитывал на то, что кто-то обратит внимание на его письмо, все же изложил свои претензии, беспощадно раскритиковав недостатки Sun Microsystems, в частности, разрабатываемую в тот момент архитектуру ПО NeWS. К удивлению Нотона, его письмо возымело успех: оно было разослано всем ведущим инженерам Sun Microsystems, которые не замедлили откликнуться и высказать горячую поддержку своему коллеге и одобрение его взглядов на ситуацию в Sun Microsystems. Обращение вызвало одобрение и у высшего руководства компании, а именно, у Билла Джоя (Bill Joy), основателя Sun Microsystems, и Джеймса Гослинга (James Gosling), начальника Нотона.
    В тот день, когда Нотон должен был уйти из компании, было принято решение о создании команды ведущих разработчиков с тем, чтобы они делали что угодно, но создали нечто необыкновенное. Команда из шести человек приступила к разработке нового объектно-ориентированного языка программирования, который был назван Oak (дуб), в честь дерева, росшего под окном Гослинга.
    Вскоре компания Sun Microsystems преобразовала команду Green в компанию First Person. Новая компания обладала интереснейшей концепцией, но не могла найти ей подходящего применения. После ряда неудач неожиданно ситуация для компании резко изменилась: был анонсирован броузер Mosaic - так родился World Wide Web, с которого началось бурное развитие Internet. Нотон предложил использовать Oak в создании Internet-приложений. Так Oak стал самостоятельным продуктом, вскоре был написан Oak-компилятор и Oak-браузер "WebRunner". В 1995 году компания Sun Microsystems приняла решение объявить о новом продукте, переименовав его в Java (единственное разумное объяснение названию - любовь программистов к кофе). Когда Java оказалась в руках Internet, стало необходимым запускать Java-аплеты - небольшие программы, загружаемые через Internet. WebRunner был переименован в HotJava и компания Netscape встала на поддержку Java-продуктов.


    Извлечение символов



    Извлечение символов

    Для того, чтобы извлечь одиночный символ из строки, вы можете со-слаться непосредственно на индекс символа в строке с помощью метода charAt. Если вы хотите в один прием извлечь несколько символов, можете воспользоваться методом getChars. В приведенном ниже фрагменте показано, как следует извлекать массив символов из объекта типа String. class getCharsDemo { public static void main(String args[]) { String s = "This is a demo of the getChars method."; int start = 10; int end = 14; char buf[] = new char[end - start]; s.getChars(start, end, buf, 0); System.out.println(buf); } }
    Обратите внимание - метод getChars не включает в выходной буфер символ с индексом end. Это хорошо видно из вывода нашего примера - выводимая строка состоит из 4 символов. С:\> java getCharsDemo demo
    Для удобства работы в String есть еще одна функция - toCharArray, которая возвращает в выходном массиве типа char всю строку. Альтернативная форма того же самого механизма позволяет записать содержимое строки в массив типа byte, при этом значения старших бай-тов в 16-битных символах отбрасываются. Соответствующий метод на-зывается getBytes, и его параметры имеют тот же смысл, что и пара-метры getChars, но с единственной разницей - в качестве третьего параметра надо использовать массив типа byte.


    Java 1.1 : пакет за пакетом



    Java 1.1 : пакет за пакетом

    Пакеты и классы в библиотеке классов Java взаимосвязаны и взаимозависимы. Многие из новых особенностей Java 1.1 базируются на классах, принадлежащих к нескольким различным пакетам Java API. Ниже описывается каждый из 23 пакетов, образующих ядро Java 1.1 API. Здесь представлены новые пакеты, а также рассмотрены изменения, внесенные в имеющиеся пакеты.


    Java.applet



    Java.applet

    Кроме возможности создавать JAR-файлы и апплеты с цифровой подписью и вводить новые атрибуты в тег , в пакет java.applet никаких других существенных изменений внесено не было.


    Java.awt.datatransfer



    java.awt.datatransfer

    Классы и интерфейсы данного пакета образуют фундамент для обмена информацией между приложениями (а также внутри приложения). В этом пакете также содержатся классы, поддерживающие модель передачи информации путем операций копирования и вставки через буфер обмена (clipboard). Можно предполагать, что в будущем пакет будет расширен таким образом, чтобы обеспечить поддержку механизма обмена информацией посредством технологии drag-and-drop. Один из основополагающих механизмов обмена информацией, поддерживаемых данным пакетом, базируется на использовании API сериализации объектов (Object Serialization API) пакета java.io.


    Java.awt.event



    java.awt.event

    В данном пакете определены классы и интерфейсы новой модели обработки событий пакета AWT. Классы и интерфейсы этого пакета можно разделить на три категории:
  • Классы событий — классы, которые действительно описывают события.
  • Слушатели событий (listeners) — интерфейсы, определяющие методы, которые должны быть реализованы объектами, заинтересованными в получении уведомлений о событиях определенного типа.
  • Адаптеры событий (adaptors) — тривиальные безоператорные реализации интерфейсов слушателей событий, которые хорошо приспособлены для создания подклассов.

  • Все события и слушатели событий, определенные в этом пакете, представляют собой расширения класса EventObject или интерфейса Event-Listener, определенные в пакете java.util.


    Java.awt.image



    java.awt.image

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


    Java.awt.peer



    java.awt.peer

    Изменения, внесенные в этот пакет, в основном отражают изменения в java.awt. Например, к ним относятся новые интерфейсы, которые описывают зависящие от платформы контекстные меню и полосы прокрутки.


    Java.awt



    java.awt

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


    Java Bean-объект



    Java Bean-объект

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


    Java.beans



    java.beans

    В этом пакете содержится широко разрекламированный JavaBeans API, предназначенный для создания и использования встраиваемых программных компонентов многократного использования. Классы и интерфейсы данного пакета можно применять на трех различных уровнях:
  • Для создания средств построения приложений, которые программист (и даже не программист) может использовать при создании приложений из отдельных Bean-объектов.
  • Для разработки Bean-объектов, которые можно применять в упомянутых выше средствах построения приложений.
  • Для разработки приложений (без использования упомянутых выше средств построения), в которых применяются Bean-объекты.

  • Большинство классов и интерфейсов данного пакета предназначено для разработчиков приложений или более сложных Bean-объектов. Программистам, которые только используют Bean-объекты или разрабатывают простые Bean-объекты, не обязательно изучать большинство особенностей данного пакета. Работа средств построения приложений, применяющих Bean-объекты, базируется на Reflection API, определенном в пакете java.lang.reflect, а во многих Bean-объектах используются преимущества API сериализации объектов (Object Serialization API), определенного в пакете java.io. В JavaBeans API применяется та же модель обработки событий, что и в Java 1.1 AWT, и классы и интерфейсы данного пакета, обеспечивающие обработку событий, являются расширениями соответствующего класса и интерфейса, определенных в пакете java.util.


    Java Database Connectivity (JDBC)



    Java Database Connectivity (JDBC)

    Новый пакет, позволяющий Java-программам посылать SQL-запросы серверам баз данных. В его состав входит "мост", который обеспечивает взаимодействие с существующими серверами баз данных ODBC.


    Java.io



    java.io

    Пакет java.io — самый большой пакет ядра Java на сегодняшний день. Это случилось потому, что в Java 1.1 добавлены следующие компоненты:
  • Полный набор новых классов потока символов в дополнение к большинству существующих классов ввода-вывода через поток байтов. Эти новые потоки чтения-записи обеспечивают высокую эффективность и многоязыковую поддержку ввода-вывода текстовой информации.
  • Новые классы и интерфейсы для поддержки сериализации объектов.
  • Ряд новых типов семейства IOException.



  • Java.lang.reflect



    java.lang.reflect

    Этот новый пакет позволяет программе на Java проверять структуру классов Java и отражать ее на собственную структуру. В java.lang.reflect содержатся классы, которые описывают переменные, методы и конструкторы классов и позволяют программе получить исчерпывающую информацию о любом объекте, массиве, методе, конструкторе или переменной. Пакет java.Beans в огромной степени базируется именно на этом пакете.


    Java.lang



    java.lang

    В этом пакете содержится ряд новых семейств типа Exception и Error, а также новые классы Byte, short и Void, с добавлением которых всем простым типам данных Java (включая тип void) соответствуют определенные типы объектов. Это обстоятельство играет большую роль для пакета j ava. lang. reflect, где определяется новый Reflection API. К тому же, существенные изменения, направленные на поддержку работы Reflection API, внесены и в класс Class. В классах Class HClassLoader содержатся методы, обеспечивающие нахождение ресурсов, связанных с данным классом, таких как изображения, аудиофайлы, файлы свойств и т.д. Ресурсы играют важную роль в обеспечении многоязыковой поддержки в Java 1.1.


    Java.math



    Java.math

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


    Java.net



    java.net

    Изменения, внесенные в пакет java.net, реализованы на достаточно низком уровне. К ним относятся: широковещательные сокеты, опции для сокетов в стиле UNIX, а также исключения новых типов, которые обеспечивают большую глубину детализации при обработке сетевых исключений.


    Java.rmi.dgc



    java.rmi.dgc

    В этом небольшом пакете определены классы и интерфейсы, которые необходимы для реализации распределенного сбора мусора (DGC — Distributed Garbage Collection).


    Java.rmi.registry



    java.rmi.registry

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


    Java.rmi.server



    java.rmi.server

    Этот пакет является самым большим среди пакетов удаленного вызова методов и представляет собой сердцевину RMI. В нем определены классы и интерфейсы, позволяющие Java-программе создавать объекты, которые могут использоваться удаленно другими Java-программами.


    Java.rmi



    java.rmi

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


    Java.security.acl



    java.security.acl

    В этом пакете определены интерфейсы высокого уровня и некоторые исключения, предназначенные для работы со списками управления доступом (ACL — access control list).


    Java.security.interfaces



    java.security.interfaces

    В этом пакете определено несколько интерфейсов, которые необходимы для работы схемы безопасности Java Security API, независящей от реализации.


    Java.security



    java.security

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


    Java.sql



    java.sql

    В этом пакете содержится Java Database Connectivity (JDBC) API. Находящиеся здесь классы и интерфейсы позволяют программам на Java посылать SQL-запросы базам данных и получать на них ответы.


    Java.text



    java.text

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


    Java.util.zip



    java.util.zip

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


    Java.util



    java.util

    Как следует из названия данного пакета, в java.util содержатся вспомогательные классы. В этот пакет в Java 1.1 добавлены новые классы для поддержки моделей обработки событий пакетов AWT и Java Beans, для определения местности (locale) и групп ресурсов (resource bundles), используемых для обеспечения многоязыковой поддержки, а также классы для работы с датой, временем и временными поясами.


    Явные приоритеты



    Явные приоритеты

    Поскольку высший приоритет имеют круглые скобки, вы всегда можете добавить в выражение несколько пар скобок, если у вас есть сомнения по поводу порядка вычислений или вам просто хочется сделать свои код более читабельным. а >> b + 3
    Какому из двух выражений, а >> (b + 3) или (а >> b) + 3, соответствует первая строка? Поскольку у оператора сложения более высокий приоритет, чем у оператора сдвига, правильный ответ - а>> (b + а). Так что если вам требуется выполнить операцию (а>>b)+ 3 без скобок не обойтись.


    Элементы и связанные с ними события



    Элементы и связанные с ними события

    В таблице 5 для каждого элемента пакета AWT перечислены типы событий, которые он может порождать. В первом столбце таблицы указан тип элемента, а во втором - тип соответствующего ему события. Тип события представляет собой константу, которая записывается в переменную id объекта класса Event.
    В столбцах с третьего по седьмой указано, устанавливаются ли значения переменных -when (время события), х (координата х курсора мыши), у (координата у курсора мыши), key (нажатая кнопка) и modifiers (специальные клавиши, которые нажаты при этом) для данного события. Если в столбце стоит точка, значит, событие устанавливает значение соответствующей переменной. В восьмом столбце объяснено, что порождает данное событие и приведено значение, которое записывается в переменной arg объекта класса Event.
    События, перечисленные для элементов класса Component, применимы ко всем подклассам класса java.awt. Component, а события, приведенные для элементов класса window, относятся как к подклассам класса window, так и к классам Dialog и Frame.


    Классическое заключение



    Классическое заключение

    В этой главе вы научились создавать классы, конструкторы и методы. Вы осознали разницу между совмещением (overloading) и замещением (overriding) методов. Специальные переменные this и super помогут вам сослаться на текущий объект и на его суперкласс. В ходе эволюции языка Java стало ясно, что в язык нужно ввести еще несколько организационных механизмов - возможности более динамичного назначения методов и возможности более тонкого управления пространством имен класса и уровнями доступа к переменным и методам объектов. Оба этих механизма - интерфейсы и пакеты, описаны в следующей главе.


    Клинч (deadlock)



    Клинч (deadlock)

    Клинч - редкая, но очень трудноуловимая ошибка, при которой между двумя легковесными процессами существует кольцевая зависимость от пары синхронизированных объектов. Например, если один подпроцесс получает управление объектом X, а другой - объектом Y, после чего Х пытается вызвать любой синхронизированный метод Y, этот вызов, естественно блокируется. Если при этом и Y попытается вызвать синхронизированный метод X, то программа с такой структурой подпроцессов окажется заблокированной навсегда. В самом деле, ведь для того, чтобы один из подпроцессов захватил нужный ему объект, ему нужно снять свою блокировку, чтобы второй подпроцесс мог завершить работу.
    Сводка функций программного интерфейса легковесных процессов
    Ниже приведена сводка всех методов класса Thread, обсуждавшихся в этой главе.


    Хотя комментарии никак не влияют



    Комментарии

    Хотя комментарии никак не влияют на исполняемый код программы, при правильном использовании они оказываются весьма существенной частью исходного текста. Существует три разновидности комментариев: комментарии в одной строке, комментарии в нескольких строках и, наконец, комментарии для документирования. Комментарии, занимающие одну строку, начинаются с символов // и заканчиваются в конце строки. Такой стиль комментирования полезен для размещения кратких пояснений к отдельным строкам кода: а = 42; // если 42 - ответ, то каков же был вопрос?
    Для более подробных пояснений вы можете воспользоваться комментариями, размещенными на нескольких строках, начав текст комментариев символами /* и закончив символами */ При этом весь текст между этими парами символов будет расценен как комментарий и транслятор его проигнорирует. /* * Этот код несколько замысловат... * Попробую объяснить: * .... */
    Третья, особая форма комментариев, предназначена для сервисной программы javadoc, которая использует компоненты Java-транслятора для автоматической генерации документации по интерфейсам классов. Соглашение, используемое для комментариев этого вида, таково: для того, чтобы разместить перед объявлением открытого (public) класса, метода или переменной документирующий комментарий, нужно начать его с символов /** (косая черта и две звездочки). Заканчивается такой комментарий точно так же, как и обычный комментарий - символами */. Программа javadoc умеет различать в документирующих комментариях некоторые специальные переменные, имена которых начинаются с символа @. Вот пример такого комментария: /** * Этот класс умеет делать замечательные вещи. * Советуем всякому, кто * захочет написать еще более совершенный класс, * взять его в качестве базового. * @see Java. applet. Applet * (c)author Patrick Naughton * @version 1. 2 */ class CoolApplet extends Applet { /** * У этого метода два параметра: * @param key - это имя параметра. * @param value - это значение параметра с именем key. */ void put (String key, Object value) {

    Компоненты



    Компоненты

    Component - это абстрактный класс, который инкапсулирует все атрибуты визуального интерфейса - обработка ввода с клавиатуры, управление фокусом, взаимодействие с мышью, уведомление о входе/выходе из окна, изменения размеров и положения окон, прорисовка своего собственного графического представления, сохранение текущего текстового шрифта, цветов фона и переднего плана (более 10 методов). Перейдем к некоторым конкретным подклассам класса Component.


    Конструкторы



    Конструкторы

    Инициализировать все переменные класса всякий раз, когда создается его очередной представитель - довольно утомительное дело даже в том случае, когда в классе имеются функции, подобные методу init. Для этого в Java предусмотрены специальные методы, называемые конструкторами. Конструктор - это метод класса, который инициализирует новый объект после его создания. Имя конструктора всегда совпадает с именем класса, в котором он расположен (также, как и в C++). У конструкторов нет типа возвращаемого результата - никакого, даже void. Заменим метод init из предыдущего примера конструктором. class Point { int х, у; Point(int х, int у) { this.x = х; this.у = у; } } class PointCreate { public static void main(String args[]) { Point p = new Point(10,20); System.out.println("x = " + p.x + " у = " + p.у); } }
    Программисты на Pascal (Delphi) для обозначения конструктора используют ключевое слово constructor.


    Конструкторы



    Конструкторы

    Как и в случае любого другого класса, вы можете создавать объекты типа String с помощью оператора new. Для создания пустой строки ис-пользуется конструктор без параметров: String s = new String():
    Приведенный ниже фрагмент кода создает объект s типа String иници-ализируя его строкой из трех символов, переданных конструктору в ка-честве параметра в символьном массиве. char chars[] = { 'а', 'b', 'с' }: String s = new String(chars); System.out.println(s):
    Этот фрагмент кода выводит строку . Итак, у этого конструктора - 3 параметра: String(char chars[], int начальныйИндекс, int числоСимволов);
    Используем такой способ инициализации в нашем очередном примере: char chars[] = { 'a', 'b', 'с', 'd', 'e', 'f' }: String s = new String(chars,2,3); System.out.println(s);
    Этот фрагмент выведет: cde.


    Конструкторы



    Конструкторы

    Объект StringBuffer можно создать без параметров, при этом в нем будет зарезервировано место для размещения 16 символов без возмож-ности изменения длины строки. Вы также можете передать конструкто-ру целое число, для того чтобы явно задать требуемый размер буфера. И, наконец, вы можете передать конструктору строку, при этом она будет скопирована в объект и дополнительно к этому в нем будет заре-зервировано место еще для 16 символов. Текущую длину StringBuffer можно определить, вызвав метод length, а для определения всего места, зарезервированного под строку в объекте StringBuffer нужно воспользоваться методом capacity. Ниже приведен пример, поясняющий это: class StringBufferDemo { public static void main(String args[]) { StringBuffer sb = new StringBuffer("Hello"); System.out.println("buffer = " + sb); System.out.println("length = " + sb.length()); System.out. println("capacity = " + sb.capacity()); } }
    Вот вывод этой программы, из которого видно, что в объекте String-Buffer для манипуляций со строкой зарезервировано дополнительное место. С:\> java StringBufferDemo buffer = Hello length = 5 capacity = 21


    Контекст апплета



    Контекст апплета









    Label



    Label

    Функциональность класса Label сводится к тому, что он знает, как нарисовать объект String - текстовую строку, выровняв ее нужным образом. Шрифт и цвет, которыми отрисовывается строка метки, являются частью базового определения класса Component. Для работы с этими атрибутами предусмотрены пары методов getFont/setFont и getForeground/setForeground. Задать или изменить текст строки после создания объекта с помощью метода setText. Для задания режимов выравнивания в классе Label определены три константы - LEFT, RIGHT и CENTER. Ниже приведен пример, в котором создаются три метки, каждая - со своим режимом выравнивания. /* */ import java.awt.*; import java.applet.*; public class LabelDemo extends Applet { public void init() { setLayout(null); int width = Integer.parseInt(getParameter("width")); int height = Integer.parseInt(getParameter("height")); Label left = new Label("Left", Label.LEFT); Label right = new Label("Right", Label.RIGHT); Label center = new Label("Center", Label.CENTER); add(left); add(right); add(center); left.reshape(0, 0, width, height / 3); right.reshape(0, height / 3, width, height / 3); center.reshape(0, 2 * height / 3, width, height / 3); } }
    На этот раз, чтобы одновременно переместить и изменить размер объектов Label, мы использовали метод reshape. Ширина каждой из меток равна полной ширине апплета, высота - 1/3 высоты апплета. Вот как этот апплет должен выглядеть, если его запустить - LabelDemo.html.


    Layout



    Layout

    Все компоненты, с которыми мы работали до сих пор в этой главе, размещались "вручную". И в каждом примере мы вызывали загадочный метод setLayout(null). Этот вызов запрещал использование предусмотренного по умолчанию механизма управления размещением компонентов. Для решения подобных задач в AWT предусмотрены диспетчеры размещения (layout managers).


    LayoutManager.



    LayoutManager.

    Каждый класс, реализующий интерфейс LayoutManager, следит за списком компонентов, которые хранятся с именами типа String. Всякий раз, когда вы добавляете компонент в Panel, диспетчер размещения уведомляется об этом. Если требуется изменить размер объекта Panel, то идет обращение к диспетчеру посредством методов minimumLayoutSize и preferredLayoutSize. В каждом компоненте, который приходится обрабатывать диспетчеру, должны присутствовать реализации методов preferredSize и minimumSize. Эти методы должны возвращать предпочтительный и минимальный размеры для прорисовки компонента, соответственно. Диспетчер размещения по возможности будет пытаться удовлетворить эти запросы, в то же время заботясь о целостности всей картины взаимного расположения компонентов.
    В Java есть несколько предопределенных классов - диспетчеров размещения, описываемых ниже.


    Лексические основы



    Лексические основы

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


    List



    List

    Класс List представляет собой компактный список с возможностью выбора нескольких вариантов и с прокруткой (аналог ListBox в Windows). Ниже приведен пример с двумя списками выбора, один из которых допускает выбор нескольких элементов, а второй - выбор единственного элемента. /* */ import java.awt.*; import java.applet.*; public class ListDemo extends Applet { public void init() { setLayout(null); int width = Integer.parseInt(getParameter("width")); int height = Integer.parseInt(getParameter("height")); List os = new List(0, true); List browser = new List(0, false); 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("lnternet Explorer 4.0"); browser.addItem("Mosaic 3.0"); browser.addItem("Lynx 2.4"); browser.select(1); add(os); add(browser); os.reshape(0, 0, width, height / 2); browser.reshape(0, height / 2, width, height / 2); } }
    Заметьте, что у нижнего списка имеется линейка прокрутки, поскольку все его элементы не уместились в заданный нами размер - ListDemo.html.


    Литералы с плавающей точкой



    Литералы с плавающей точкой

    Числа с плавающей точкой представляют десятичные значения, у которых есть дробная часть. Их можно записывать либо в обычном, либо экспоненциальном форматах. В обычном формате число состоит из некоторого количества десятичных цифр, стоящей после них десятичной точки, и следующих за ней десятичных цифр дробной части. Например, 2.0, 3.14159 и .6667 - это допустимые значения чисел с плавающей точкой, записанных в стандартном формате. В экспоненциальном формате после перечисленных элементов дополнительно указывается десятичный порядок. Порядок определяется положительным или отрицательным десятичным числом, следующим за символом Е или е. Примеры чисел в экспоненциальном формате: 6.022е23, 314159Е-05, 2е+100. В Java числа с плавающей точкой по умолчанию рассматриваются, как значения типа double. Если вам требуется константа типа float, справа к литералу надо приписать символ F или f. Если вы любитель избыточных определений - можете добавлять к литералам типа double символ D или d. Значения используемого по умолчанию типа double хранятся в 64-битовом слове, менее точные значения типа float - в 32-битовых.


    Литералы



    Литералы

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


    Литература



    Литература

  • Нотон П. JAVA:Справ.руководство :Пер.с англ./Под ред.А.Тихонова.-М.:БИНОМ: Восточ.Кн.Компания,1996:Восточ.Кн.Компания.-447с..-(Club Computer)
  • Патрик Нотон, Герберт Шилдт Полный справочник по Java .- McGraw-Hill,1997, Издательство "Диалектика",1997
  • Дэвид Флэнэген Java in a Nutshell .- O'Reilly & Associates, Inc., 1997, Издательская группа BHV, Киев, 1998
  • Ренеган Э.Дж.(мл.) 1001 адрес WEB для программистов :Новейший путеводитель программиста по ресурсам World Wide Web:Пер.с англ..-Минск:Попурри,1997.-512с.ил.
  • Сокольский М.В. Все об Intranet и Internet .-М.:Элиот,1998.-254с.ил.
  • Чен М.С. и др. Программирование на JAVA:1001 совет:Наиболее полное руководство по Java и Visual J++ :Пер.с англ./Чен М.С.,Грифис С.В.,Изи Э.Ф..-Минск:Попурри,1997.-640с.ил.+ Прил.(1диск.)
  • Майкл Эферган Java: справочник .- QUE Corporation, 1997, Издательство "Питер Ком", 1998
  • Джо Вебер Технология Java в подлиннике .- QUE Corporation, 1996, "BHV-Санкт-Петербург",1997
  • Джейсон Мейнджер Java: Основы программирования .- McGraw-Hill,Inc.,1996, Издательская группа BHV, Киев,1997
  • И.Ю.Баженова Язык программирования Java .- АО "Диалог-МИФИ", 1997
  • Джон Родли Создание Java-апплетов .- The Coriolis Group,Inc.,1996, Издательство НИПФ "ДиаСофт Лтд.",1996
  • Майкл Томас, Пратик Пател, Алан Хадсон, Доналд Болл(мл.) Секреты программирования для Internet на Java .- Ventana Press, Ventana Communications Group, U.S.A.,1996, Издательство "Питер Пресс", 1997
  • Аарон И.Волш Основы программирования на Java для World Wide Web .- IDG Books Worldwide,Inc.,1996, Издательство "Диалектика",1996
  • Кен Арнольд, Джеймс Гослинг Язык программирования Java .- Addison-Wesley Longman,U.S.A.,1996, Издательство "Питер-Пресс", 1997
  • Нейл Бартлетт, Алекс Лесли, Стив Симкин Программирование на Java. Путеводитель .- The Coriolis Group,Inc.,1996, Издательство НИПФ "ДиаСофт Лтд.",1996
  • Крис Джамса Библиотека программиста Java .- Jamsa Press, 1996, ООО "Попурри", 1996








  • Логические литералы



    Логические литералы

    У логической переменной может быть лишь два значения - true (истина) и false (ложь). Логические значения true и false не преобразуются ни в какое числовое представление. Ключевое слово true в Java не равно 1, a false не равно 0. В Java эти значения могут присваиваться только переменным типа boolean либо использоваться в выражениях с логическими операторами.


    Long



    long

    Тип long предназначен для представления 64-битовых чисел со знаком. Его диапазон допустимых значений достаточно велик даже для таких задач, как подсчет числа атомов во вселенной. long m; long n = Ох55аа000055аа0000;
    Не надо отождествлять разрядность целочисленного типа с занимаемым им количеством памяти. Исполняющий код Java может использовать для ваших переменных то количество памяти, которое сочтет нужным, лишь бы только их поведение соответствовало поведению типов, заданных вами. Фактически, нынешняя реализация Java из соображений эффективности хранит переменные типа byte и short в виде 32-битовых значений, поскольку этот размер соответствует машинному слову большинства современных компьютеров (СМ - 8 бит, 8086 - 16 бит, 80386/486 - 32 бит, Pentium - 64 бит).
    Ниже приведена таблица разрядностей и допустимых диапазонов для различных типов целых чисел.
    Имя Разрядность Диапазон
    long 64 -9, 223, 372, 036, 854, 775, 808.. 9, 223, 372, 036, 854, 775, 807
    Int32-2, 147, 483, 648.. 2, 147, 483, 647
    Short 16-32, 768.. 32, 767
    byte 8-128.. 127


    Main



    main

    Наконец, мы добрались до имени метода main. Здесь нет ничего необычного, просто все существующие реализации Java-интерпретаторов, получив команду интерпретировать класс, начинают свою работу с вызова метода main. Java-транслятор может оттранслировать класс, в котором нет метода main. А вот Java-интерпретатор запускать классы без метода main не умеет.
    Все параметры, которые нужно передать методу, указываются внутри пары круглых скобок в виде списка элементов, разделенных символами ";" (точка с запятой). Каждый элемент списка параметров состоит из разделенных пробелом типа и идентификатора. Даже если у метода нет параметров, после его имени все равно нужно поставить пару круглых скобок. В примере, который мы сейчас обсуждаем, у метода main только один параметр, правда довольно сложного типа.
    Элемент String args[] объявляет параметр с именем args, который является массивом объектов - представителей класса String. Обратите внимание на квадратные скобки, стоящие после идентификатора args. Они говорят о том, что мы имеем дело с массивом, а не с одиночным элементом указанного типа. Мы вернемся к обсуждению массивов в следующей главе, а пока отметим, что тип String - это класс. Более детально о строках мы поговорим в главе 9.


    Массивы



    Массивы

    Для объявления типа массива используются квадратные скобки. В приведенной ниже строке объявляется переменная month_days, тип которой - "массив целых чисел типа int". int month_days [];
    Для того, чтобы зарезервировать память под массив, используется специальный оператор new. В приведенной ниже строке кода с помощью оператора new массиву month_days выделяется память для хранения двенадцати целых чисел. month_days = new int [12];
    Итак, теперь month_days - это ссылка на двенадцать целых чисел. Ниже приведен пример, в котором создается массив, элементы которого содержат число дней в месяцах года (невисокосного). class Array { public static void main (String args []) { int month_days[]; month_days = new int[12]; month_days[0] = 31; month_days[1] = 28; month_days[2] = 31; month_days[3] = 30; month_days[4] = 31; month_days[5] = 30; month_days[6] = 31; month_days[7] = 31; month_days[8] = 30; month_days[9] = 31; month_days[10] = 30; month_days[11] = 31; System.out.println("April has " + month_days[3] + " days."); } }
    При запуске эта программа печатает количество дней в апреле, как это показано ниже. Нумерация элементов массива в Java начинается с нуля, так что число дней в апреле - это month_days [3]. С: \> java Array April has 30 days.
    Имеется возможность автоматически инициализировать массивы способом, во многом напоминающим инициализацию переменных простых типов. Инициализатор массива представляет собой список разделенных запятыми выражений, заключенный в фигурные скобки. Запятые отделяют друг от друга значения элементов массива. При таком способе создания массив будет содержать ровно столько элементов, сколько требуется для хранения значений, указанных в списке инициализации. class AutoArray { public static void main(String args[]) { int month_days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; System.out.println("April has " + month_days[3] + " days."); } }
    В результате работы этой программы, вы получите точно такой же результат, как и от ее более длинной предшественницы.
    Java строго следит за тем, чтобы вы случайно не записали или не попытались получить значения, выйдя за границы массива. Если же вы попытаетесь использовать в качестве индексов значения, выходящие за границы массива - отрицательные числа либо числа, которые больше или равны количеству элементов в массиве, то получите сообщение об ошибке времени выполнения. В главе 10 мы подробно расскажем о том, что делать при возникновении подобных ошибок.


    Math



    Math

    Класс Math содержит функции с плавающей точкой, которые используются в геометрии и тригонометрии. Кроме того, в нем есть две константы, используемые в такого рода вычислениях: - Е (приблизительно 2.72) и PI (приблизительно 3.14159).


    MediaTracker



    MediaTracker

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


    MemorylmageSource



    MemorylmageSource

    MemoryImageSource - класс, используемый для создания нового изображения из массива пикселей. Вот конструктор, используемый для создания объекта MemoryImageSource:
    MemoryImageSource(int width, int height, int pixel[], int offset, int scanLineWidth)
    Объект MemoryImageSource собирается из массива целых величин pixel[] в используемой по умолчанию модели цветов RGB для генерации данных объекта Image. В используемой по умолчанию цветовой модели пиксель - это целая величина состоящая из Alpha, Red, Green и Blue (OxAARRGGBB). Величина Alpha обозначает степень прозрачности элемента изображения.
    MemoryImageSource возвращает объект ImageProducer, который используется с createImage для получения изображения, пригодного к использованию. Приведенный ниже короткий пример создает MemoryImageSource, используя вариант простого алгоритма (побитовое исключающее ИЛИ значений х и у координат каждого элемента изображения) из книги Gerard J.Holzmann "Beyond Photography, The Digital Darkroom". /* Memory Image Generator * * */ import java.applet.*; import java.awt.*; import java.awt.image.*; public class MemoryImager extends Applet { Image art; Dimension d; public void init() { generateImage(); } public void generateImage() { int pixels[] = new int[d.width * d.height]; int i = 0; int r, g, b; for(int y=0; y Посмотрите как это интересное изображение выглядит на экране - MemoryImager.html.


    Меню



    Меню

    С каждым окном верхнего уровня может быть связана линейка меню. Объект MenuBar может включать в себя несколько объектов Menu. Последние, в свою очередь, содержат в себе список вариантов выбора - объектов MenuItem. Menu - подкласс MenuItem, так что объекты Menu также могут включаться в этот список, что позволяет создавать иерархически вложенные подменю. Вот пример, в котором к окну добавлены несколько вложенных меню. /* */ import java.awt.*; import java.applet. *; public class MenuDemo extends Applet { public void init() { int width = Integer.parseInt(getParameter("width")); int height = Integer.parseInt(getParameter("height")); Frame f = new Frame("Demo Frame"); f.setSize(width, height); MenuBar mbar = new MenuBar(); f.setMenuBar(mbar); Menu file = new Menu("File"); file.add(new MenuItem("New... ")); file.add(new MenuItem("0pen...")); file.add(new MenuItem("Close")); file.add(new MenuItem("-")); file.add(new MenuItem("Quit...")); mbar.add(file); Menu edit = new Menu("Edit"); edit.add(new MenuItem("Cut")); edit.add(new MenuItem("Copy")); edit.add(new Menultem("Paste")); edit.add(new MenuItem("-")); Menu sub = new Menu("Special"); sub.add(new MenuItem("First")); sub.add(new MenuItem("Second")); sub.add(new MenuItem("Third")); edit.add(sub); edit.add(new CheckBoxMenuItem("Debug")); edit.add(new CheckBoxMenuItem("Testing")); mbar.add(edit); f.show(); } }


    Методы класса Color



    Методы класса Color

    HSBtoRGB(float, float, float) RGBtoHSB(int, int, int, float[1) HSBtoRGB преобразует цвет, заданный оттенком, насыщенностью и яркостью (HSB), в целое число в формате RGB, готовое для использования в качестве параметра конструктора Color(int). RGBtoHSB преобразует цвет, заданный тремя базовыми компонентами, в массив типа float со значениями HSB, соответствующими данному цвету.
    Цветовая модель HSB (Hue-Saturation-Brightness, оттенок-насыщенность-яркость) является альтернативой модели Red-Green-Blue для задания цветов. В этой модели оттенки можно представить как круг с различными цветами (оттенок может принимать значения от 0.0 до 1.0, цвета на этом круге идут в том же порядке, что и в радуге - красный, оранжевый, желтый, зеленый, голубой, синий, фиолетовый). Насыщенность (значение в диапазоне от 0.0 до 1.0) - это шкала глубины цвета, от легкой пастели до сочных цветов. Яркость - это также число в диапазоне от 0.0 до 1.0, причем меньшие значения соответствуют более темным цветам, а большие - более ярким. getRedQ, getGreenO, setBlue()
    Каждый из этих методов возвращает в младших восьми битах результата значение соответствующего базового компонента цвета. getRGB()
    Этот метод возвращает целое число, в котором упакованы значения базовых компонентов цвета, причем red = Oxff & (getRGB() >> 16); green = Oxff & (getRGB() >> 8); blue = Oxff & getRGB();


    Методы класса



    Методы класса

    Методы класса - это статические методы, которые можно вызывать непосредственно с именем класса Thread.


    Методы объекта



    Методы объекта









    Многоязыковая поддержка



    Многоязыковая поддержка

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


    Многомерные массивы



    Многомерные массивы

    На самом деле, настоящих многомерных массивов в Java не существует. Зато имеются массивы массивов, которые ведут себя подобно многомерным массивам, за исключением нескольких незначительных отличий. Приведенный ниже код создает традиционную матрицу из шестнадцати элементов типа double, каждый из которых инициализируется нулем. Внутренняя реализация этой матрицы - массив массивов double. double matrix [][] = new double [4][4];
    Следующий фрагмент кода инициализирует такое же количество памяти, но память под вторую размерность отводится вручную. Это сделано для того, чтобы наглядно показать, что матрица на самом деле представляет собой вложенные массивы. double matrix [][] = new double [4][]; matrix [0] = new double[4]; matrix[1] = new double[4]; matrix[2] = new double[4], matrix[3] = { 0, 1, 2, 3 };
    В следующем примере создается матрица размером 4 на 4 с элементами типа double, причем ее диагональные элементы (те, для которых х==у) заполняются единицами, а все остальные элементы остаются равными нулю. class Matrix { public static void main(String args[]) { double m[][]; m = new double[4][4]; m[0][0] = 1; m[1][1] = 1; m[2][2] = 1; m[3][3] = 1; System.out.println(m[0][0] +" "+ m[0][1] +" "+ m[0][2] +" "+ m[0][3]); System.out.println(m[1][0] +" "+ m[1][1] +" "+ m[1][2] +" "+ m[1][3]); System.out.println(m[2][0] +" "+ m[2][1] +" "+ m[2][2] +" "+ m[2][3]); System.out.println(m[3][0] +" "+ m[3][1] +" "+ m[3][2] +" "+ m[3][3]); } }
    Запустив эту программу, вы получите следующий результат: C : \> Java Matrix 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1
    Обратите внимание - если вы хотите, чтобы значение элемента было нулевым, вам не нужно его инициализировать, это делается автоматически.
    Для задания начальных значений массивов существует специальная форма инициализатора, пригодная и в многомерном случае. В программе, приведенной ниже, создается матрица, каждый элемент которой содержит произведение номера строки на номер столбца. Обратите внимание на тот факт, что внутри инициализатора массива можно использовать не только литералы, но и выражения. class AutoMatrix { public static void main(String args[]) { double m[][] = { { 0*0, 1*0, 2*0, 3*0 }, { 0*1, 1*1, 2*1, 3*1 }, { 0*2. 1*2, 2*2, 3*2 }, { 0*3, 1*3. 2*3, 3*3 } }: System.out.println(m[0][0] +" "+m[0][1] +" "+ m[0][2] +" "+ m[0][3]); System.out.println(m[1][0] +" "+m[1][1] +" "+ m[1][2] +" "+ m[1][3]); System.out.println(m[2][0] +" "+m[2][1] +" "+ m[2][2] +" "+ m[2][3]); System.out.println(m[3][0] +" "+m[3][1] +" "+ m[3][2] +" "+ m[3][3]); } }
    Запустив эту программу, вы получите следующий результат: С: \> Java AutoMatrix 0 0 0 0 0 1 2 3 0 2 4 6 0 3 6 9


    Модель легковесных процессов в Java



    Модель легковесных процессов в Java

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


    с вами до сих пор



    Модель обработки событий Java 1.0

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

    Каждый компонент может обрабатывать события, заместив определенные методы, вызываемые используемой по умолчанию реализацией метода handleEvents класса Component. Этот метод вызывается с объектом класса Event, описывающего все возможные типы событий. Наиболее часто используемые события, например, те, что связаны с мышью и клавиатурой, диспетчеризируются другим методам класса Component.

    Все события, связанные с мышью, вызываются с копией оригинального события, а также с координатами х и у, в которых это событие произошло.
  • mouseEnter вызывается в том случае, когда мышь входит в компонент.
  • mouseExit вызывается при выходе мыши из области компонента.
  • mouseMove вызывается при перемещении мыши в области компонента.
  • mouseDown вызывается при нажатии кнопки мыши.
  • mouseDrag вызывается при перемещении мыши с нажатой кнопкой.
  • mouseUp вызывается при отпускании кнопки мыши.


  • Аналогично, keyDown и keyUp вызываются при каждом нажатии и отпускании клавиши. Событие передается методу вместе с кодом нажатой клавиши. Событие можно проверить, чтобы посмотреть, нажаты ли в данный момент какие либо клавиши-модификаторы, для этой цели можно также пользоваться методами shiftDown, controlDown и metaDown. В классе Event определены десятки констант, позволяющих использовать символические имена, например, PGUP и HOME.

    Наконец, для работы со специальными событиями, например, с обратными вызовами (callback) из компонентов Button, Scrollbar и Menu, вам придется замещать метод action. Этот метод вызывается с исходным событием и со вторым параметром, который представляет собой компонент пользовательского интерфейса, создавший это событие. Вы должны проверить этот объект, разобраться, какой из компонентов послал вам событие, после чего передать управление соответствующему данному компоненту обработчику. Для того, чтобы перед приведением типа проверить, принадлежит ли объект к определенному классу, например, к классу Button, вы можете использовать оператор instanceof.

    А вот и пример на обработку событий. Мы добавили объект Label к примеру с игрой в "пятнашки", а также заместили метод action для того, чтобы обрабатывать события, возникающие при нажатии кнопок. Точно такой же механизм можно использовать для управления вводом через любой из подклассов Component. /* */ import java.awt.*; import java.applet.*; public class EventDemo extends Applet { static final int n = 4; Label lab = new Label("?", Label.CENTER); public void init() { setLayout(new GridLayout(n, n)); setFont(new Font("Helvetica", Font.BOLD, 24)); int width = Integer.parseInt(getParameter("width")); int height = Integer.parseInt(getParameter("height")); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { int k = i * n + j; if (k > 0) add(new Button("" + k)); } } lab.setFont(new Font("Helvetica", Font.ITALIC, 24)); add(lab); } public boolean action(Event e, Object o) { if (o instanceof String) { lab.setText((String) o); } return false; } }


    Новая модель обработки событий представляет



    Модель обработки событий Java 1.1

    Новая модель обработки событий представляет собой, по существу, модель обратных вызовов (callback). При создании GUI-элемента ему сообщается, какой метод или методы он должен вызывать при возникновении в нем определенного события (нажатия кнопки, мыши и т.п.). Эту модель очень легко использовать в C++, поскольку этот язык позволяет оперировать указателями на методы (чтобы определить обратный вызов, необходимо всего лишь передать указатель на функцию). Однако в Java это недопустимо (методы не являются объектами). Поэтому для реализации новой модели необходимо определить класс, реализующий некоторый специальный интерфейс. Затем можно передать экземпляр такого класса GUI-элементу, обеспечивая таким образом обратный вызов. Когда наступит ожидаемое событие, GUI-элемент вызовет соответствующий метод объекта, определенного ранее.

    Модель обработки событий Java 1.1 используется как в пакете AWT, так и в JavaBeans API. В этой модели разным типам событий соответствуют различные классы Java. Каждое событие является подклассом класса java.util.EventObject. События пакета AWT, которые и рассматриваются в данной главе, являются подклассом java.awt.AWTEvent. Для удобства события различных типов пакета AWT (например, MouseEvent или АсtionEvent) помещены в новый пакет java.awt.event.

    Для каждого события существует порождающий его объект, который можно получить с помощью метода getSource(), и каждому событию пакета AWT соответствует определенный идентификатор, который позволяет получить метод getid(). Это значение используется для того, чтобы отличать события различных типов, которые могут описываться одним и тем же классом событий. Например, для класса FocusEvent возможны два типа событий: FocusEvent.FOCUS_GAINED и FocusEvent.FOCUS_LOST. Подклассы событий содержат информацию, связанную с данным типом события. Например, в классе MouseEvent существуют методы getX(), getY() и getClickCount (). Этот класс наследует, в числе прочих, и методы getModifiers() и getWhen().

    Модель обработки событий Java 1.1 базируется на концепции слушателя событий. Слушателем события является объект, заинтересованный в получении данного события. В объекте, который порождает событие (в источнике событий), содержится список слушателей, заинтересованных в получении уведомления о том, что данное событие произошло, а также методы, которые позволяют слушателям добавлять или удалять себя из этого списка. Когда источник порождает событие (или когда объект источника зарегистрирует событие, связанное с вводом информации пользователем), он оповещает все объекты слушателей событий о том, что данное событие произошло.

    Источник события оповещает объект слушателя путем вызова специального метода и передачи ему объекта события (экземпляра подкласса EventObject). Для того чтобы источник мог вызвать данный метод, он должен быть реализован для каждого слушателя. Это объясняется тем, что все слушатели событий определенного типа должны реализовывать соответствующий интерфейс. Например, объекты слушателей событий ActionEvent должны реализовывать интерфейс ActionListener. В пакете Java.awt.event определены интерфейсы слушателей для каждого из определенных в нем типов событий (например, для событий MouseEvent здесь определено два интерфейса слушателей: MouseListener и MouseMotionListener). Все интерфейсы слушателей событий являются расширениями интерфейса java.util.EventListener. В этом интерфейсе не определяется ни один из методов, но он играет роль интерфейса-метки, в котором однозначно определены все слушатели событий как таковые.

    В интерфейсе слушателя событий может определяться несколько методов. Например, класс событий, подобный MouseEvent, описывает несколько событий, связанных с мышью, таких как события нажатия и отпускания кнопки мыши. Эти события вызывают различные методы соответствующего слушателя. По установленному соглашению, методам слушателей событий может быть передан один единственный аргумент, являющийся объектом того события, которое соответствует данному слушателю. В этом объекте должна содержаться вся информация, необходимая программе для формирования реакции на данное событие. В таблице 6 приведены определенные в пакете java.awt.event типы событий, соответствующие им слушатели, а также методы, определенные в каждом интерфейсе слушателя.


    Модификация строк при копировании



    Модификация строк при копировании

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


    Мультимедиа-горизонты



    Мультимедиа-горизонты

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


    Надежность



    Надежность

    Java ограничивает вас в нескольких ключевых областях и таким образом способствует обнаружению ошибок на ранних стадиях разработки программы. В то же время в ней отсутствуют многие источники ошибок, свойственных другим языкам программирования (строгая типизация, например). Большинство используемых сегодня программ “отказывают” в одной из двух ситуаций: при выделении памяти, либо при возникновении исключительных ситуаций. В традиционных средах программирования распределение памяти является довольно нудным занятием — программисту приходится самому следить за всей используемой в программе памятью, не забывая освобождать ее по мере того, как потребность в ней отпадает. Зачастую программисты забывают освобождать захваченную ими память или, что еще хуже, освобождают ту память, которая все еще используется какой-либо частью программы. Исключительные ситуации в традиционных средах программирования часто возникают в таких, например, случаях, как деление на нуль или попытка открыть несуществующий файл, и их приходится обрабатывать с помощью неуклюжих и нечитабельных конструкций (кроме Delphi). Java фактически снимает обе эти проблемы, используя сборщик мусора для освобождения незанятой памяти и встроенные объектно-ориентированные средства для обработки исключительных ситуаций.


    NAME = appletInstanceName



    NAME = appletInstanceName

    NAME - необязательный атрибут, используемый для задания имени для данного экземпляра апплета. Присвоение апплетам имен необходимо для того, чтобы другие апплеты на этой же странице могли находить их и общаться с ними. Для того, чтобы получить доступ к подклассу MyApplet класса Applet с именем "Duke", нужно написать: MyApplet a = getAppletContext().getApplet("Duke");
    После того, как вы получили таким образом дескриптор именованного экземпляра апплета, вы можете вызывать его методы точно так же, как это делается с любым другим объектом.


    Наследование



    Наследование

    Вторым фундаментальным свойством объектно-ориентированного подхода является наследование (первый - инкапсуляция). Классы-потомки имеют возможность не только создавать свои собственные переменные и методы, но и наследовать переменные и методы классов-предков. Классы-потомки принято называть подклассами. Непосредственного предка данного класса называют его суперклассом. В очередном примере показано, как расширить класс Point таким образом, чтобы включить в него третью координату z. class Point3D extends Point { int z; Point3D(int x, int y, int z) { this.x = x; this.у = у; this.z = z; } Point3D() { this(-1,-1,-1); } }
    В этом примере ключевое слово extends используется для того, чтобы сообщить транслятору о намерении создать подкласс класса Point. Как видите, в этом классе не понадобилось объявлять переменные х и у, поскольку Point3D унаследовал их от своего суперкласса Point.


    Ненадежное приведение типов



    Ненадежное приведение типов

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


    Ненадежные списки аргументов



    Ненадежные списки аргументов

    C++ гордится своей возможностью передавать указатели на произвольные типы в списках аргументов переменной длины, известных под названием varargs. Интерфейс varargs - простое расширение, основанное на возможности приведения любого адреса к произвольному типу, при этом заботы о проверке допустимости типов ложатся на плечи программиста.
    Было бы прекрасно, если бы в Java существовала безопасная возможность объявлять и передавать списки аргументов переменной длины, но в Java 1. 0 такие средства отсутствуют.


    Ненадежные структуры



    Ненадежные структуры

    С++ пытается предоставить программисту возможность инкапсуляции данных посредством объявления структур (struct) и полиморфизм с помощью объединений (union). Эти две конструкции прикрывают критические и катастрофические машинно-зависимые ограничения по размеру и выравниванию данных.
    В Java нет конструкций struct и union, все это объединено в концепции классов.


    Неперехваченные исключения



    Неперехваченные исключения

    Объекты-исключения автоматически создаются исполняющей средой Java в результате возникновения определенных исключительных состо-яний. Например, очередная наша программа содержит выражение, при вычислении которого возникает деление на нуль. class Exc0 { public static void main(string args[]) { int d = 0; int a = 42 / d; } }
    Вот вывод, полученный при запуске нашего примера. С:\> java Exc0 java.lang.ArithmeticException: / by zero at Exc0.main(Exc0.java:4)
    Обратите внимание на тот факт что типом возбужденного исклю-чения был не Exception и не Throwable. Это подкласс класса Exception, а именно: ArithmeticException, поясняющий, какая ошибка возникла при выполнении программы. Вот другая версия того же класса, в кото-рой возникает та же исключительная ситуация, но на этот раз не в про-граммном коде метода main. class Exc1 { static void subroutine() { int d = 0; int a = 10 / d; } public static void main(String args[]) { Exc1.subroutine(); } }
    Вывод этой программы показывает, как обработчик исключений ис-полняющей системы Java выводит содержимое всего стека вызовов. С:\> java Exc1 java.lang.ArithmeticException: / by zero at Exc1.subroutine(Exc1.java:4) at Exc1.main(Exc1.java:7)


    Несколько разделов catch



    Несколько разделов catch

    В некоторых случаях один и тот же блок программного кода может воз-буждать исключения различных типов. Для того, чтобы обрабатывать по-добные ситуации, Java позволяет использовать любое количество catch-разделов для try-блока. Наиболее специализированные классы исключений должны идти первыми, поскольку ни один подкласс не будет достигнут, если поставить его после суперкласса. Следующая про-грамма перехватывает два различных типа исключений, причем за этими двумя специализированными обработчиками следует раздел catch общего назначения, перехватывающий все подклассы класса Throwable. class MultiCatch { public static void main(String args[]) { try { int a = args.length; System.out.println("a = " + a); int b = 42 / a; int c[] = { 1 }; c[42] = 99; } catch (ArithmeticException e) { System.out.println("div by 0: " + e); } catch(ArrayIndexOutOfBoundsException e) { System.out.println("array index oob: " + e); } } }
    Этот пример, запущенный без параметров, вызывает возбуждение ис-ключительной ситуации деления на нуль. Если же мы зададим в командной строке один или несколько параметров, тем самым установив а в значение боль-ше нуля, наш пример переживет оператор деления, но в следующем опе-раторе будет возбуждено исключение выхода индекса за границы масси-ва ArrayIndexOutOf Bounds. Ниже приведены результаты работы этой программы, за-пущенной и тем и другим способом. С:\> java MultiCatch а = 0 div by 0: java.lang.ArithmeticException: / by zero C:\> java MultiCatch 1 a = 1 array index oob: java.lang.ArrayIndexOutOfBoundsException: 42


    Независимость от архитектуры ЭВМ



    Независимость от архитектуры ЭВМ

    Вопрос о долговечности и переносимости кода важнее религиозных войн между ПК и Макинтошами. Создатели Java наложили на язык и на среду времени выполнения несколько жестких требований, которые на деле, а не на словах позволяют, однажды написав, всегда запускать программу в любом месте и в любое время (где существует виртуальная Java-машина – броузеры на всех платформах, OS/2, Netware).


    Новая модель обработки событий



    Новая модель обработки событий

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


    Number Абстрактный класс Number



    Number Абстрактный класс Number представляет собой интерфейс для работы со всеми стандартными скалярными типами: - long, int, float и double.
    У этого класса есть методы доступа к содержимому объекта, которые возвращают (возможно округленное) значение объекта в виде значения каждого из примитивных типов:
  • doubleValue() возвращает содержимое объекта в виде значения типа double.
  • floatValue() возвращает значение типа float.
  • intValue() возвращает значение типа int.
  • longValue() возвращает значение типа long.

  • Double и Float


    Double и Float - подклассы класса Number. В дополнение к четырем методам доступа, объявленным в суперклассе, эти классы содержат несколько сервисных функций, которые облегчают работу со значениями double и float. У каждого из классов есть конструкторы, позволяющие инициализировать объекты значениями типов double и float, кроме того, для удобства пользователя, эти объекты можно инициализировать и объектом String, содержащим текстовое представление вещественного числа. Приведенный ниже пример иллюстрирует создание представителей класса Double с помощью обоих конструкторов. class DoubleDemo { public static void main(String args[]) { Double d1 = new Double(3.14159); Double d2 = new Double("314159E-5"); System.out.println(d1+"="+d2+"->"+d1.equals(d2)); } }
    Как вы можете видеть из результата работы этой программы, метод equals возвращает значение true, а это означает, что оба использованных в примере конструктора создают идентичные объекты класса Double. С:\> java DoubleDemo 3.14159 = 3.14159 -> true


    Объектная ориентированность



    Объектная ориентированность

    Забавно наблюдать, как многочисленные новые диалекты старых языков безапелляционно объявляются объектно-ориентированными. Поскольку при разработке языка отсутствовала тяжелая наследственность, для реализации объектов был избран удобный прагматичный подход. Разработчики Java старались выдержать разумный компромисс между моделью пуристов — “все является объектами”, и моделью хакеров — “уйди с моей дороги”. Объектная модель в Java проста и легко расширяется, в то же время, ради повышения производительности, числа и другие простые типы данных Java не являются объектами.


    Объявление методов



    Объявление методов

    Методы - это подпрограммы, присоединенные к конкретным определениям классов. Они описываются внутри определения класса на том же уровне, что и переменные объектов. При объявлении метода задаются тип возвращаемого им результата и список параметров. Общая форма объявления метода такова: тип имя_метода (список формальных параметров) { тело метода: }
    Тип результата, который должен возвращать метод может быть любым, в том числе и типом void - в тех случаях, когда возвращать результат не требуется. Список формальных параметров - это последовательность пар тип-идентификатор, разделенных запятыми. Если у метода параметры отсутствуют, то после имени метода должны стоять пустые круглые скобки. class Point { int х, у; void init(int a, int b) { х = а; У = b; } }


    Объявление переменной



    Объявление переменной

    Основная форма объявления переменной такова: тип идентификатор [ = значение] [, идентификатор [ = значение 7...];
    Тип - это либо один из встроенных типов, то есть, byte, short, int, long, char, float, double, boolean, либо имя класса или интерфейса. Мы подробно обсудим все эти типы в следующей главе. Ниже приведено несколько примеров объявления переменных различных типов. Обратите внимание на то, что некоторые примеры включают в себя инициализацию начального значения. Переменные, для которых начальные значения не указаны, автоматически инициализируются нулем. int a, b, с;
    Объявляет три целых переменных а, b, с. int d = 3, e, f = 5;
    Объявляет еще три целых переменных, инициализирует d и f. byte z = 22;
    Инициализирует z. double pi = 3. 14159;
    Объявляет число пи (не очень точное, но все таки пи). char x = 'x';
    Переменная х получает значение 'х'.
    В приведенном ниже примере создаются три переменные, соответствующие сторонам прямоугольного треугольника, а затем c помощью теоремы Пифагора вычисляется длина гипотенузы, в данном случае числа 5, величины гипотенузы классического прямоугольного треугольника со сторонами 3-4-5. class Variables { public static void main (String args []) { double a = 3; double b = 4; double c; с = Math.sqrt (a* a + b* b); System.out.println ("c = "+ c); } }


    OBJECT = appletClassSerialFile



    OBJECT = appletClassSerialFile

    Указывает имя файла, содержащего сериализованный апплет, из которого последний будет восстановлен. При запуске определяемого таким образом апплета должен вызываться не метод init(), а метод start(). Для апплета необходимо задать либо атрибут CODE, либо атрибут OBJECT, но задавать эти атрибуты одновременно нельзя.


    Ограничение доступа



    Ограничение доступа

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

  • В языке Java имеется три уровня доступа, определяемых ключевыми словами: private (закрытый), public (открытый) и protected (защищенный), которые употребляются в различных комбинациях. Содержимое ячеек таблицы определяет доступность переменной с данной комбинацией модификаторов (столбец) из указанного места (строка).
    privateмодификатор отсутствуетprivate protectedprotectedpublic
    тот же классдадаДадада
    подкласс в том же пакетенетдаДадада
    независимый класс в том же пакетенетдаНетдада
    подкласс в другом пакетенетнетДадада
    независимый класс в другом пакетенетнетНетнетда
    На первый взгляд все это может показаться чрезмерно сложным, но есть несколько правил, которые помогут вам разобраться. Элемент, объявленный public, доступен из любого места. Все, что объявлено private, доступно только внутри класса, и нигде больше. Если у элемента вообще не указан модификатор уровня доступа, то такой элемент будет виден из подклассов и классов того же пакета. Именно такой уровень доступа используется в языке Java по умолчанию. Если же вы хотите, чтобы элемент был доступен извне пакета, но только подклассам того класса, которому он принадлежит, вам нужно объявить такой элемент protected. И наконец, если вы хотите, чтобы элемент был доступен только подклассам, причем независимо от того, находятся ли они в данном пакете или нет - используйте комбинацию private protected.
    Ниже приведен довольно длинный пример, в котором представлены все допустимые комбинации модификаторов уровня доступа. В исходном коде первого пакета определяется три класса: Protection, Derived и SamePackage. В первом из этих классов определено пять целых переменных - по одной на каждую из возможных комбинаций уровня доступа. Переменной n приписан уровень доступа по умолчанию, n_pri - уровень private, n_pro - protected, n_pripro - private protected и n_pub - public. Во всех остальных классах мы пытаемся использовать переменные первого класса. Те строки кода, которые из-за ограничения доступа привели бы к ошибкам при трансляции, закомментированы с помощью однострочных комментариев (//) - перед каждой указано, откуда доступ при такой комбинации модификаторов был бы возможен. Второй класс - Derived - является подклассом класса Protection и расположен в том же пакете р1. Поэтому ему доступны все перечисленные переменные за исключением n_pri. Третий класс, SamePackage, расположен в том же пакете, но при этом не является подклассом Protection. По этой причине для него недоступна не только переменная n_pri, но и n_pripro, уровень доступа которой - private protected. package р1; public class Protection { int n = 1; private int n_pri = 2; protected int n_pro = 3; private protected int n_pripro = 4; public int n_pub = 5; public Protection() { System.out.println("base constructor"); System.out.println("n="+n); System.out.println("n_pri="+n_pri); System.out.println("n_pro="+n_pro); System.out.println("n_pripro="+n_pripro); System.out.println("n_pub="+n_pub); } } class Derived extends Protection { Derived() { System.out.println("derived constructor"); System.out.println("n = " + n); // только в классе // System.out.println("n_pri="+n_pri); System.out.println("n_pro="+n_pro); System.out.println("n_pripro="+n_pripro); System.out.println("n_pub="+n_pub); } } class SamePackage { SamePackage() { Protection p = new Protection(); System.out.println("same package constructor"); System.out.println("n="+p.n); // только в классе // System.out.println("n_pri="+p.n_pri); System.out.println("n_pro="+p.n_pro); // только в классе и подклассе // System.out.println("n_pripro="+p.n_pripro): System.out.println("n_pub="+p.n_pub): } }


    Округление



    Округление

  • ceil(double а) возвращает наименьшее целое число, значение которого больше или равно а.
  • floor(double а) возвращает наибольшее целое число, значение которого меньше или равно а.
  • rint(double а) возвращает в типе double значение а с отброшенной дробной частью.
  • round(float а) возвращает округленное до ближайшего целого значение а.
  • round(double а) возвращает округленное до ближайшего длинного целого значение а.
  • Кроме того, в классе Math имеются полиморфные версии методов для получения модуля, нахождения минимального и максимального значений, работающие с числами типов int, long, float и double:
  • abs(a) возвращает модуль (абсолютное значение) а.
  • max(a, b) возвращает наибольший из своих аргументов.
  • min(a, b) возвращает наименьший из своих аргументов.



  • Оператор деления по модулю



    Оператор деления по модулю

    Оператор деления по модулю, или оператор mod, обозначается символом %. Этот оператор возвращает остаток от деления первого операнда на второй. В отличие от C++, функция mod в Java работает не только с целыми, но и с вещественными типами. Приведенная ниже программа иллюстрирует работу этого оператора. class Modulus { public static void main (String args []) { int x = 42; double у = 42.3; System.out.println("x mod 10 = " + x % 10); System.out.println("y mod 10 = " + у % 10); } }
    Выполнив эту программу, вы получите следующий результат: С:\> Modulus x mod 10 = 2 y mod 10 = 2.3


    Оператор implements



    Оператор implements

    Оператор implements - это дополнение к определению класса, реализующего некоторый интерфейс(ы). class имя_класса [extends суперкласс] [implements интерфейс0 [, интерфейс1...]] { тело класса }
    Если в классе реализуется несколько интерфейсов, то их имена разделяются запятыми. Ниже приведен пример класса, в котором реализуется определенный нами интерфейс: class Client implements Callback { void callback(int p) { System.out.println("callback called with " + p); } }
    В очередном примере метод callback интерфейса, определенного ранее, вызывается через переменную - ссылку на интерфейс: class TestIface { public static void main(String args[]) { Callback с = new client(); c.callback(42); } }
    Ниже приведен результат работы программы: С:\> Java TestIface callback called with 42


    Оператор import



    Оператор import

    После оператора package, но до любого определения классов в исходном Java-файле, может присутствовать список операторов import. Пакеты являются хорошим механизмом для отделения классов друг от друга, поэтому все встроенные в Java классы хранятся в пакетах. Общая форма оператора import такова: import пакет1 [.пакет2].(имякласса|*);
    Здесь пакет1 - имя пакета верхнего уровня, пакет2 - это необязательное имя пакета, вложенного в первый пакет и отделенное точкой. И, наконец, после указания пути в иерархии пакетов, указывается либо имя класса, либо метасимвол звездочка. Звездочка означает, что, если Java-транслятору потребуется какой-либо класс, для которого пакет не указан явно, он должен просмотреть все содержимое пакета со звездочкой вместо имени класса. В приведенном ниже фрагменте кода показаны обе формы использования оператора import : import java.util.Date import java.io.*; Замечание
    Замечание


    Но использовать без нужды форму записи оператора import с использованием звездочки не рекомендуется, т.к. это может значительно увеличить время трансляции кода (на скорость работы и размер программы это не влияет).
    Все встроенные в Java классы, которые входят в комплект поставки, хранятся в пакете с именем java. Базовые функции языка хранятся во вложенном пакете java.lang. Весь этот пакет автоматически импортируется транслятором во все программы. Это эквивалентно размещению в начале каждой программы оператора import java.lang.*;
    Если в двух пакетах, подключаемых с помощью формы оператора im-port со звездочкой, есть классы с одинаковыми именами, однако вы их не используете, транслятор не отреагирует. А вот при попытке использовать такой класс, вы сразу получите сообщение об ошибке, и вам придется переписать операторы import, чтобы явно указать, класс какого пакета вы имеете ввиду. class MyDate extends Java.util.Date { }


    Оператор interface



    Оператор interface

    Определение интерфейса сходно с определением класса, отличие состоит в том, что в интерфейсе отсутствуют объявления данных и конструкторов. Общая форма интерфейса приведена ниже: interface имя { тип_результата имя_метода1(список параметров); тип имя_final1-переменной = значение; }
    Обратите внимание - у объявляемых в интерфейсе методов отсутствуют операторы тела. Объявление методов завершается символом ; (точка с запятой). В интерфейсе можно объявлять и переменные, при этом они неявно объявляются final - переменными. Это означает, что класс реализации не может изменять их значения. Кроме того, при объявлении переменных в интерфейсе их обязательно нужно инициализировать константными значениями. Ниже приведен пример определения интерфейса, содержащего единственный метод с именем callback и одним параметром типа int. interface Callback { void callback(int param); }


    Оператор new



    Оператор new

    Оператор new создает экземпляр указанного класса и возвращает ссылку на вновь созданный объект. Ниже приведен пример создания и присваивание переменной р экземпляра класса Point. Point р = new Point();
    Вы можете создать несколько ссылок на один и тот же объект. Приведенная ниже программа создает два различных объекта класса Point и в каждый из них заносит свои собственные значения. Оператор точка используется для доступа к переменным и методам объекта. class TwoPoints { public static void main(String args[]) { Point p1 = new Point(); Point p2 = new Point(); p1.x = 10; p1.y = 20; р2.х = 42; р2.у = 99; System.out.println("x = " + p1.x + " у = " + p1.y); System.out.println("x = " + р2.х + " у = " + р2.у); } }
    В этом примере снова использовался класс Point, было создано два объекта этого класса, и их переменным х и у присвоены различные значения. Таким образом мы продемонстрировали, что переменные различных объектов независимы на самом деле. Ниже приведен результат, полученный при выполнении этой программы. С:\> Java TwoPoints х = 10 у = 20 х = 42 у = 99 Замечание
    Замечание


    Поскольку при запуске интерпретатора мы указали в командной строке не класс Point, а класс TwoPoints, метод main класса Point был полностью проигнорирован. Добавим в класс Point метод main и, тем самым, получим законченную программу. class Point { int х, у; public static void main(String args[]) { Point p = new Point(); р.х = 10; p.у = 20; System.out.println("x = " + р.х + " у = " + p.y); } }


    Оператор package Первое, что может



    Оператор package Первое, что может появиться в исходном файле Java - это оператор package, который сообщает транслятору, в каком пакете должны определяться содержащиеся в данном файле классы. Пакеты задают набор раздельных пространств имен, в которых хранятся имена классов. Если оператор package не указан, классы попадают в безымянное пространство имен, используемое по умолчанию. Если вы объявляете класс, как принадлежащий определенному пакету, например, package java.awt.image;
    то и исходный код этого класса должен храниться в каталоге java/awt/image.
    Замечание


    Каталог, который транслятор Java будет рассматривать, как корневой для иерархии пакетов, можно задавать с помощью переменной окружения СLASSPATH. С помощью этой переменной можно задать несколько корневых каталогов для иерархии пакетов (через ; как в обычном PATH).


    Оператор запятая



    Оператор запятая

    Иногда возникают ситуации, когда разделы инициализации или итерации цикла for требуют нескольких операторов. Поскольку составной оператор в фигурных скобках в заголовок цикла for вставлять нельзя, Java предоставляет альтернативный путь. Применение запятой (,) для разделения нескольких операторов допускается только внутри круглых скобок оператора for. Ниже приведен тривиальный пример цикла for, в котором в разделах инициализации и итерации стоит несколько операторов. class Comma { public static void main(String args[]) { int a, b; for (a = 1, b = 4; a < b; a++, b--) { System.out.println("a = " + a); System.out.println("b = " + b); } } }
    Вывод этой программы показывает, что цикл выполняется всего два раза. С: \> java Comma а = 1 b = 4 а = 2 b = 3


    Операторы отношения



    Операторы отношения

    Для того, чтобы можно было сравнивать два значения, в Java имеется набор операторов, описывающих отношение и равенство. Список таких операторов приведен в таблице.
    ОператорРезультат
    ==равно
    !=не равно
    >больше
    <меньше
    >=больше или равно
    <=меньше или равно

    Значения любых типов, включая целые и вещественные числа, символы, логические значения и ссылки, можно сравнивать, используя оператор проверки на равенство == и неравенство !=. Обратите внимание - в языке Java, так же, как в С и C++ проверка на равенство обозначается последовательностью (==). Один знак (=) - это оператор присваивания.


    Операторы



    Операторы

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


    Основы



    Основы

    К механизму обработки исключений в Java имеют отношение 5 клю-чевых слов: - try, catch, throw, throws и finally. Схема работы этого механизма следующая. Вы пытаетесь (try) выполнить блок кода, и если при этом возникает ошибка, система возбуждает (throw) исключение, ко-торое в зависимости от его типа вы можете перехватить (catch) или пере-дать умалчиваемому (finally) обработчику.
    Ниже приведена общая форма блока обработки исключений. try { // блок кода } catch (ТипИсключения1 е) { // обработчик исключений типа ТипИсключения1 } catch (ТипИсключения2 е) { // обработчик исключений типа ТипИсключения2 throw(e) // повторное возбуждение исключения } finally { } Замечание
    Замечание


    В языке Delphi вместо ключевого слова catch используется except.


    Отладочная печать



    Отладочная печать

    Отладочную печать можно выводить в два места: на консоль и в статусную строку программы просмотра апплетов. Для того, чтобы вывести сообщение на консоль, надо написать: System.out.println("Hello there, welcome to Java");
    Сообщения на консоли очень удобны, поскольку консоль обычно не видна пользователям апплета, и в ней достаточно места для нескольких сообщений. В браузере Netscape консоль Java доступна из меню Options, пункт "Show Java Console".
    Метод showStatus выводит текст в статусной области программы арpletviewer или браузера с поддержкой Java. В статусной области можно вывести только одну строку сообщения.


    Отличия Java от C++



    Отличия Java от C++

    В большинстве книг по C++ вы найдете такое же описание достоинств объектно-ориентированного программирования и доказательства того, что это - очередная ступень в развитии индустрии программирования. В чем же беда C++ и почему была создана Java?
    Фактически, большинство архитектурных решений, принятых при создании Java, было продиктовано желанием предоставить синтаксис, сходный с С и C++. В Java используются практически идентичные соглашения для объявления переменных, передачи параметров, операторов и для управления потоком выполнением кода. В Java добавлены все хорошие черты C++, но исключены недостатки последнего.


    Отражение



    Отражение

    Программы на Java могут теперь отражаться (reflection) на самих себя или на другой класс с целью определения методов и переменных, заданных в этом классе, аргументов, передаваемых методам, и т.д. Reflection API позволяет также вызывать методы по имени.


    Paint



    paint

    Метод paint вызывается каждый раз при повреждении апплета. AWT следит за состоянием окон в системе и замечает такие случаи, как, например, перекрытие окна апплета другим окном. В таких случаях, после того, как апплет снова оказывается видимым, для восстановления его изображения вызывается метод paint.


    Пакеты



    Пакеты

    Все идентификаторы, которые мы до сих пор использовали в наших примерах, располагались в одном и том же пространстве имен (name space). Это означает, что нам во избежание конфликтных ситуаций приходилось заботиться о том, чтобы у каждого класса было свое уникальное имя. Пакеты - это механизм, который служит как для работы с пространством имен, так и для ограничения видимости. У каждого файла .java есть 4 одинаковых внутренних части, из которых мы до сих пор в наших примерах использовали только одну. Ниже приведена общая форма исходного файла Java.
  • одиночный оператор package (необязателен)
  • любое количество операторов import (необязательны)
  • одиночное объявление открытого (public) класса
  • любое количество закрытых (private) классов пакета (необязательны)



  • Panel



    Panel

    Класс Panel - это очень простая специализация класса Container. В отличие от последнего, он не является абстрактным классом. Поэтому о Panel можно думать, как о допускающем рекурсивную вложенность экранном компоненте. С помощью метода add в объекты Panel можно добавлять другие компоненты. После того, как в него добавлены какие-либо компоненты, можно вручную задавать их положение и изменять размер с помощью методов move, resize и reshape класса Component.
    В предыдущей главе мы уже использовали один из подклассов Panel - Applet. Каждый раз, когда мы создавали Applet, методы paint и update рисовали его изображение на поверхности объекта Panel. Прежде, чем мы углубимся в методы Panel, давайте познакомимся с компонентом Canvas, который можно вставлять в пустую Panel при работе с объектом Applet.


    Этот тег дает возможность



    PARAM NAME = appletAttribute1 VALUE = value1

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


    Перечисления



    Перечисления

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


    Передача параметров



    Передача параметров

    getParameter(String) Метод getParameter возвращает значение типа String, соответствующее указанному имени параметра. Если вам в качестве параметра требуется значение какого-либо другого типа, вы должны преобразовать строку-параметр самостоятельно. Вы сейчас увидите некоторые примеры использования метода getParameter для извлечения параметров из приведенного ниже примера:
    Ниже показано, как извлекается каждый из этих параметров: String FontName = getParameter ("fontName"); String FontSize = Integer.parseInt(getParameter ("fontSize")); String Leading = Float.valueOf(getParameter ("leading")); String PaidUp = Boolean.valueOf(getParameter ("accountEnabled"));


    Переменные представителей (instance variables)



    Переменные представителей (instance variables)

    Данные инкапсулируются в класс путем объявления переменных между открывающей и закрывающей фигурными скобками, выделяющими в определении класса его тело. Эти переменные объявляются точно так же, как объявлялись локальные переменные в предыдущих примерах. Единственное отличие состоит в том, что их надо объявлять вне методов, в том числе вне метода main. Ниже приведен фрагмент кода, в котором объявлен класс Point с двумя переменными типа int. class Point { int х, у; }
    В качестве типа для переменных объектов можно использовать как любой из простых типов, описанных в главе 4, так и классовые типы. Скоро мы добавим к приведенному выше классу метод main, чтобы его можно было запустить из командной строки и создать несколько объектов.


    Переменные в интерфейсах



    Переменные в интерфейсах

    Интерфейсы можно использовать для импорта в различные классы совместно используемых констант. В том случае, когда вы реализуете в классе какойлибо интерфейс, все имена переменных этого интерфейса будут видимы в классе как константы. Это аналогично использованию файлов-заголовков для задания в С и C++ констант с помощью директив #define или ключевого слова const в Pascal / Delphi.
    Если интерфейс не включает в себя методы, то любой класс, объявляемый реализацией этого интерфейса, может вообще ничего не реализовывать. Для импорта констант в пространство имен класса предпочтительнее использовать переменные с модификатором final. В приведенном ниже примере проиллюстрировано использование интерфейса для совместно используемых констант. import java.util.Random; interface SharedConstants { int NO = 0; int YES = 1; int MAYBE = 2; int LATER = 3; int SOON = 4; int NEVER = 5; } class Question implements SharedConstants { Random rand = new Random(); int ask() { int prob = (int) (100 * rand.nextDouble()); if (prob < 30) return NO; // 30% else if (prob < 60) return YES; // 30% else if (prob < 75) return LATER; // 15% else if (prob < 98) return SOON; // 13% else return NEVER; // 2% } } class AskMe implements SharedConstants { static void answer(int result) { switch(result) { case NO: System.out.println("No"); break; case YES: System.out.println("Yes"); break; case MAYBE: System.out.println("Maybe"); break; case LATER: System.out.println("Later"); break; case SOON: System.out.priniln("Soon"); break; case NEVER: System.out.println("Never"); break; } } public static void main(String args[]) { Question q = new Question(); answer(q.ask()); answer(q.ask()); answer(q.askO); answer(q.ask()); } }
    Обратите внимание на то, что результаты при разных запусках программы отличаются, поскольку в ней используется класс генерации случайных чисел Random пакета java.util. Описание этого пакета приведено в главе 12. С:\> Java AskMe Later Scon No Yes


    Переменные



    Переменные

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


    Перерисовка



    Перерисовка

    Возвратимся к апплету HelloWorldApplet. В нем мы заместили метод paint, что позволило апплету выполнить отрисовку. В классе Applet предусмотрены дополнительные методы рисования, позволяющие эффективно закрашивать части экрана. При разработке первых апплетов порой непросто понять, почему метод update никогда не вызывается. Для инициации update предусмотрены три варианта метода repaint.


    Подклассы Exception Только подклассы



    Подклассы Exception Только подклассы класса Throwable могут быть возбуждены или пере-хвачены. Простые типы - int, char и т.п., а также классы, не являю-щиеся подклассами Throwable, например, String и Object, использоваться в качестве исключений не могут. Наиболее общий путь для использова-ния исключений - создание своих собственных подклассов класса Ex-ception. Ниже приведена программа, в которой объявлен новый подкласс класса Exception. class MyException extends Exception { private int detail; MyException(int a) { detail = a: } public String toString() { return "MyException["+detail+"]"; } } class ExceptionDemo { static void compute(int a) throws MyException { System.out.println("called computer+a+")."); if (a > 10) throw new MyException(a); System.out.println("normal exit."); } public static void main(String args[]) { try { compute(1); compute(20); } catch (MyException e) { System.out.println("caught" + e); } } }
    Этот пример довольно сложен. В нем сделано объявление подкласса MyException класса Exception. У этого подкласса есть специальный кон-структор, который записывает в переменную объекта целочисленное значение, и совмещенный метод toString, выводящий значение, хранящееся в объекте-исключении. Класс ExceptionDemo определяет метод compute, который возбуждает исключение типа MyExcepton. Простая логика метода compute возбуждает исключение в том случае, когда значение пара-ветра метода больше 10. Метод main в защищенном блоке вызывает метод compute сначала с допустимым значением, а затем - с недопус-тимым (больше 10), что позволяет продемонстрировать работу при обоих путях выполнения кода. Ниже приведен результат выполнения програм-мы. С:\> java ExceptionDemo called compute(1). normal exit. called compute(20). caught MyException[20]
    Заключительное резюме


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


    Подпроцесс



    Подпроцесс

    Класс Thread инкапсулирует все средства, которые могут вам потребоваться при работе с подпроцессами. При запуске Java-программы в ней уже есть один выполняющийся подпроцесс. Вы всегда можете выяснить, какой именно подпроцесс выполняется в данный момент, с помощью вызова статического метода Thread.currentThread. После того, как вы получите дескриптор подпроцесса, вы можете выполнять над этим подпроцессом различные операции даже в том случае, когда параллельные подпроцессы отсутствуют. В очередном нашем примере показано, как можно управлять выполняющимся в данный момент подпроцессом. class CurrentThreadDemo { public static void main(String args[]) { Thread t = Thread.currentThread(); t.setName("My Thread"); System.out. println("current thread: " + t); try { for (int n = 5; n > 0; n--) { System.out.println(" " + n); Thread.sleep(1000); } } catch (InterruptedException e) { System.out.println("interrupted"); } } }
    В этом примере текущий подпроцесс хранится в локальной переменной t. Затем мы используем эту переменную для вызова метода setName, который изменяет внутреннее имя подпроцесса на “My Thread”, с тем, чтобы вывод программы был удобочитаемым. На следующем шаге мы входим в цикл, в котором ведется обратный отсчет от 5, причем на каждой итерации с помощью вызова метода Thread.sleep() делается пауза длительностью в 1 секунду. Аргументом для этого метода является значение временного интервала в миллисекундах, хотя системные часы на многих платформах не позволяют точно выдерживать интервалы короче 10 миллисекунд. Обратите внимание — цикл заключен в try/catch блок. Дело в том, что метод Thread.sleep() может возбуждать исключение InterruptedException. Это исключение возбуждается в том случае, если какому-либо другому подпроцессу понадобится прервать данный подпроцесс. В данном примере мы в такой ситуации просто выводим сообщение о перехвате исключения. Ниже приведен вывод этой программы: С:\>; java CurrentThreadDemo current thread: Thread[My Thread,5,main] 5 4 3 2 1
    Обратите внимание на то, что в текстовом представлении объекта Thread содержится заданное нами имя легковесного процесса — My Thread. Число 5 — это приоритет подпроцесса, оно соответствует приоритету по умолчанию, “main” — имя группы подпроцессов, к которой принадлежит данный подпроцесс.


    Порядок инициализации апплета



    Порядок инициализации апплета

    Ниже приведен порядок, в котором вызываются методы класса Applet, с пояснениями, нужно или нет переопределять данный метод.


    Последовательность выполнения операторов



    Последовательность выполнения операторов

    Давайте еще раз обратимся к нашему последнему примеру:
    String s = "Не is " + age + " years old."; В том случае, когда age - не String, а переменная, скажем, типа int, в этой строке кода заключено еще больше магии транслятора. Целое значение переменной int передается совмещенному методу append класса StringBuffer, который преобразует его в текстовый вид и добавляет в конец содержащейся в объекте строки. Вам нужно быть вниматель-ным при совместном использовании целых выражений и слияния строк, в противном случае результат может получиться совсем не тот, который вы ждали. Взгляните на следующую строку: String s = "four: " + 2 + 2;
    Быть может, вы надеетесь, что в s будет записана строка ? Не угадали - с вами сыграла злую шутку последовательность выпол-нения операторов. Так что в результате получа-ется "four: 22".
    Для того, чтобы первым выполнилось сложение целых чисел, нужно использовать скобки : String s = "four: " + (2 + 2);


    Позиционирование и шрифты: FontMetrics



    Позиционирование и шрифты: FontMetrics

    В Java используются различные шрифты, а класс FontMetrics позволяет программисту точно задавать положение выводимого в апплете текста. Прежде всего нам нужно понять кое-что из обычной терминологии, употребляемой при работе со шрифтами:
  • Высота (height) - размер от верхней до нижней точки самого высокого символа в шрифте.
  • Базовая линия (baseline) - линия, по которой выравниваются нижние границы символов (не считая снижения (descent)).
  • Подъем (ascent) - расстояние от базовой линии до верхней точки символа.
  • Снижение (descent) - расстояние от базовой линии до нижней точки символа.
  • Использование FontMetrics

  • Ниже приведены некоторые методы класса FontMetrics:


    Преобразование строк



    Преобразование строк

    В каждом классе String есть метод toString - либо своя собственная реализация, либо вариант по умолчанию, наследуемый от класса Object. Класс в нашем очередном примере замещает наследуемый метод toStrring своим собственным, что позволяет ему выводить значения переменных объекта. class Point { int х, у; Point(int x, int у) { this.x = х; this.у = у; } public String toString() { return "Point[" + x + ", " + у + "]"; } } class toStringDemo { public static void main(String args[]) { Point p = new Point(10, 20); System.out.println("p = " + p); } }
    Ниже приведен результат, полученный при запуске этого примера. С:\> Java toStringDemo p = Point[10, 20]


    Препроцессорная обработка



    Препроцессорная обработка

    Работа препроцессора C++ которого заключается в поиске специальных команд, начинающихся с символа #. Эти команды позволяют выполнять простую условную трансляцию и расширение макроопределений.
    Java управляется со своими задачами без помощи препроцессора, вместо принятого в С стиля определения констант с помощью директивы #define в ней используется ключевое слово final.


    Скоро надо будет готовить приложение



    Приложение - Новое в Java 1.1

    Скоро надо будет готовить приложение по Java 1.2 (срок выхода – декабрь 1998 года). А пока новшествами Java 1.1 являются :


    Пример программы, манипулирующей с битами



    Пример программы, манипулирующей с битами

    В таблице, приведенной ниже, показано, как каждый из операторов битовой арифметики воздействует на возможные комбинации битов своих операндов. Приведенный после таблицы пример иллюстрирует использование этих операторов в программе на языке Java.
    АВORANDXORNOT A
    000001
    101010
    011011
    111100
    class Bitlogic { public static void main(String args []) { String binary[] = { "OOOO", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" }; int a = 3; // 0+2+1 или двоичное 0011 int b = 6; // 4+2+0 или двоичное 0110 int c = a | b; int d = a & b; int e = a ^ b; int f = (~a & b) | (a & ~b); int g = ~a & 0x0f; System.out.println(" a = " + binary[a]); System.out.println(" b = " + binary[b]); System.out.println(" ab = " + binary[c]); System.out.println(" a&b = " + binary[d]); System.out.println(" a^b = " + binary[e]); System.out.рrintln("~a&b|а^~Ь = " + binary[f]); System.out.println(" ~a = " + binary[g]); } } Ниже приведен результат, полученный при выполнении этой программы:
    Ниже приведен результат, полученный при выполнении этой программы: С: \> Java BitLogic a = 0011 b = 0110 a | b = 0111 a & b = 0010 a ^ b = 0101 ~a & b | a & ~b = 0101 ~а = 1100


    Приоритеты операторов



    Приоритеты операторов

    В Java действует определенный порядок, или приоритет, операций. В элементарной алгебре нас учили тому, что у умножения и деления более высокий приоритет, чем у сложения и вычитания. В программировании также приходится следить и за приоритетами операций. В таблице ука-заны в порядке убывания приоритеты всех операций языка Java.
    Высший
    ( )[ ].
    ~!
    */%
    +-
    >>>>><<
    >>=<<=
    ==!=
    &
    ^
    |
    &&
    | |
    ?:
    =op=
    Низший
    В первой строке таблицы приведены три необычных оператора, о которых мы пока не говорили. Круглые скобки () используются для явной установки приоритета. Как вы узнали из предыдущей главы, квадратные скобки [] используются для индексирования переменной-массива. Оператор . (точка) используется для выделения элементов из ссылки на объект - об этом мы поговорим в главе 7. Все же остальные операторы уже обсуждались в этой главе.


    Приоритеты подпроцессов



    Приоритеты подпроцессов

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


    Приведение типа



    Приведение типа

    Приведение типов (type casting) - одно из неприятных свойств C++, тем не менее приведение типов сохранено и в языке Java. Иногда возникают ситуации, когда у вас есть величина какого-то определенного типа, а вам нужно ее присвоить переменной другого типа. Для некоторых типов это можно проделать и без приведения типа, в таких случаях говорят об автоматическом преобразовании типов. В Java автоматическое преобразование возможно только в том случае, когда точности представления чисел переменной-приемника достаточно для хранения исходного значения. Такое преобразование происходит, например, при занесении литеральной константы или значения переменной типа byte или short в переменную типа int. Это называется расширением (widening) или повышением (promotion), поскольку тип меньшей разрядности расширяется (повышается) до большего совместимого типа. Размера типа int всегда достаточно для хранения чисел из диапазона, допустимого для типа byte, поэтому в подобных ситуациях оператора явного приведения типа не требуется. Обратное в большинстве случаев неверно, поэтому для занесения значения типа int в переменную типа byte необходимо использовать оператор приведения типа. Эту процедуру иногда называют сужением (narrowing), поскольку вы явно сообщаете транслятору, что величину необходимо преобразовать, чтобы она уместилась в переменную нужного вам типа. Для приведения величины к определенному типу перед ней нужно указать этот тип, заключенный в круглые скобки. В приведенном ниже фрагменте кода демонстрируется приведение типа источника (переменной типа int) к типу приемника (переменной типа byte). Если бы при такой операции целое значение выходило за границы допустимого для типа byte диапазона, оно было бы уменьшено путем деления по модулю на допустимый для byte диапазон (результат деления по модулю на число - это остаток от деления на это число). int a = 100; byte b = (byte) a;


    Пробелы



    Пробелы

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


    Программирование на языке JAVA (оглавление)



    Программирование на языке JAVA (оглавление)

    1. Революция по имени Java
    2. Отличия Java от C++
    3. Введение в язык Java
    4. Типы
    5. Операторы
    6. Управление выполнением программы
    7. Классы
    8. Пакеты и интерфейсы
    9. Работа со строками
    10. Обработка исключений
    11. Легковесные процессы и синхронизация
    12. Утилиты
    13. Ввод-вывод
    14. Сетевые средства
    15. Апплеты
    16. Набор абстракций для работы с окнами
    17. Модели обработки событий
    18. Работа с изображениями
    Приложение. Новое в Java 1.1
    Литература










    Управление качеством

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

    Управление качеством - ISO
    Лекции по управлению
    Управление качеством
    Менеджмент в управлении
    Управление - Образование

    Учебник по управлению качеством
    Управление - Предприятие
    Управление качеством - Продукт
    Охрана природы

        Бизнес: Предпринимательство - Малый бизнес - Управление


    Properties



    Properties

    Properties - подкласс HashTable, в который для удобства использования добавлено несколько методов, позволяющих получать значения, которые, возможно, не определены в таблице. В методе getProperty вместе с именем можно указывать значение по умолчанию: getРгореrtу("имя","значение_по_умолчанию");
    При этом, если в таблице свойство "имя" отсутствует, метод вернет "значение_по_умолчанию". Кроме того, при создании нового объекта этого класса конструктору в качестве параметра можно передать другой объект Properties, при этом его содержимое будет использоваться в качестве значений по умолчанию для свойств нового объекта. Объект Properties в любой момент можно записать либо считать из потока - объекта Stream (потоки будут обсуждаться в главе 13). Ниже приведен пример, в котором создаются и впоследствии считываются некоторые свойства: import java.util.Properties; class PropDemo { static Properties prop = new Properties(); public static void main(String args[]) { prop.put("Title", "put title here"); prop.put("Author", "put name here"); prop.put("isbn", "isbn not set"); Properties book = new Properties(prop); book.put("Title", "The Java Handbook"); book.put("Author", "Patrick Naughton"); System.out.println("Title: " + book.getProperty("Title")); System.out.println("Author: " + book.getProperty("Author")); System.out.println("isbn: " + book.getProperty("isbn")); System.out.println("ean: " + book.getProperty("ean", "???")); } }
    Здесь мы создали объект prop класса Properties, содержащий три значения по умолчанию для полей Title, Author и isbn. После этого мы создали еще один объект Properties с именем book, в который мы поместили реальные значения для полей Title и Author. В следующих трех строках примера мы вывели результат, возвращенный методом getProperty для всех трех имеющихся ключей. В четвертом вызове getProperty стоял несуществующий ключ "еаn". Поскольку этот ключ отсутствовал в объекте book и в объекте по умолчанию prop, метод getProperty выдал нам указанное в его вызове значение по умолчанию, то есть "???": С:\> java PropDemo Title: The Java Handbook Author: Patrick Naughton isbn: isbn not set ean: ???


    Простой загрузчик изображений



    Простой загрузчик изображений

    Простейший случай - загрузка в страницу одиночного изображения. Вот маленький апплет, выполняющий эту работу: /* SimpleImageLoad * * * */ import java.applet.*; import java.awt.*; public class SimpleImageLoad extends Applet { Image art; public void init() { art = getImage(getDocumentBase(), getParameter("img")); } public void paint(Graphics g) { g.drawImage(art, 0, 0, this); } }
    Метод paint использует drawlmage с четырьмя аргументами: это ссылка на изображение art, координаты левого верхнего угла рисунка х, у и объект типа ImageObserver. Мы поговорим подробнее об ImageObserver в следующем параграфе; здесь мы использовали this в качестве имени ImageObserver, поскольку он встроен в апплет. Когда этот апплет запускается, он в методе init начинает загрузку art. Процесс загрузки изображения по сети хорошо заметен - SimpleImageLoad.html, поскольку встроенный интерфейс ImageObserver вызывает процедуру paint при каждом поступлении новой порции данных из сети. Вы можете использовать ImageObserver для отслеживания загрузки изображения, а в это время выводить на экран другую информацию.


    Простота и мощь



    Простота и мощь

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


    Простые оболочки для типов.



    Простые оболочки для типов.

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


    Простые типы



    Простые типы

    Простые типы в Java не являются объектно-ориентированными, они аналогичны простым типам большинства традиционных языков программирования. В Java имеется восемь простых типов: - byte, short, int, long, char, float, double и boolean. Их можно разделить на четыре группы:
  • Целые. К ним относятся типы byte, short, int и long. Эти типы предназначены для целых чисел со знаком.
  • Типы с плавающей точкой - float и double. Они служат для представления чисел, имеющих дробную часть.
  • Символьный тип char. Этот тип предназначен для представления элементов из таблицы символов, например, букв или цифр.
  • Логический тип boolean. Это специальный тип, используемый для представления логических величин.

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


    Public



    public

    Разбивая эту строку на отдельные лексемы, мы сразу сталкиваемся с ключевым словом public. Это - модификатор доступа, который позволяет программисту управлять видимостью любого метода и любой переменной. В данном случае модификатор доступа public означает, что метод main виден и доступен любому классу. Существуют еще 2 указателя уровня доступа - private и protected, с которыми мы более детально познакомимся в главе 8.


    QED



    QED

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


    Random



    Random

    Класс Random - это генератор псевдослучайных чисел. Используемый в нем алгоритм был взят из раздела 3.2.1 "Искусства программирования" Дональда Кнута. Обычно в качестве начального значения используется текущее время, что снижает вероятность получения повторяющихся последовательностей случайных чисел.
    Из объекта класса Random можно извлекать 5 типов случайных чисел. Метод nextInt возвращает целое число, равномерно распределенное по всему диапазону этого типа. Аналогично, метод nextLong возвращает случайное число типа long. Методы nextFloat и nextDouble возвращают случайные числа соответственно типов float и double, равномерно распределенные на интервале 0.0..1.0. И, наконец, метод nextGaussian возвращает нормально распределенное случайное число со средним значением 0.0 и дисперсией 1.0.


    Распределение памяти



    Распределение памяти

    В строю опасных качеств C++ рука об руку с указателями идет распределение памяти. Распределение памяти в С, а значит и в C++, опирается на инь и янь ненадежного кода - на вызовы библиотечных функций malloc() и free().Если вы вызовете free() с указателем на блок памяти, который вы уже освободили ранее, или с указателем, память для которого никогда не выделялась - готовьтесь к худшему. Обратная проблема, когда вы просто забываете вызвать free(), чтобы освободить ненужный больше блок памяти, гораздо более коварна. "Утечка памяти" (memory leak) приводит к постепенному замедлению работы программы по мере того, как системе виртуальной памяти приходится сбрасывать на диск неиспользуемые страницы с мусором. И, наконец, когда все системные ресурсы исчерпаны, программа неожиданно аварийно завершается, а вы начинаете ломать голову над этой проблемой. В C++ добавлены два оператора - new и delete, которые используются во многом аналогично функциям malloc() и free(). Программист по-прежнему отвечает за то, чтобы каждый неиспользуемый объект, созданный с помощью оператора new, был уничтожен оператором delete.
    в Java нет функций ьфддщс() , free(). Поскольку в ней каждая сложная структура данных - это объект, память под такие структуры резервируется в куче (heap) с помощью оператора new. Реальные адреса памяти, выделенные этому объекту, могут изменяться во время работы программы, но вам не нужно об этом беспокоиться. Вам даже не придется вызывать free () или delete, поскольку Java - система с так называемым сборщиком мусора. Сборщик мусора запускается каждый раз, когда система простаивает, либо когда Java не может удовлетворить запрос на выделение памяти.


    Равенство Метод equals и оператор



    Равенство Метод equals и оператор == выполняют две совершенно различных проверки. Если метод equal сравнивает символы внутри строк, то опе-ратор == сравнивает две переменные-ссылки на объекты и проверяет, указывают ли они на разные объекты или на один и тот же. В очеред-ном нашем примере это хорошо видно - содержимое двух строк оди-наково, но, тем не менее, это - различные объекты, так что equals и == дают разные результаты. class EqualsNotEqualTo { public static void main(String args[]) { String s1="Hello"; String s2=new String(s1); System.out.println(s1+"equals"+s2+"->"+s1.equals(s2)); System.out.println(s1+"=="+s2+",->"+(s1==s2)); } }
    Вот результат запуска этого примера: C:\> java EqualsNotEqualTo Hello equals Hello -> true Hello == Hello -> false
    Упорядочение


    Зачастую бывает недостаточно просто знать, являются ли две строки идентичными. Для приложений, в которых требуется сортировка, нужно знать, какая из двух строк меньше другой. Для ответа на этот вопрос нужно воспользоваться методом compareTo класса String. Если целое значение, возвращенное методом, отрицательно, то строка, с которой был вызван метод, меньше строки-параметра, если положительно - больше. Если же метод compareTo вернул значение 0, строки идентичны. Ниже приведена программа, в которой выполняется пузырьковая сорти-ровка массива строк, а для сравнения строк используется метод compareTo. Эта программа выдает отсортированный в алфавитном порядке список строк. class SortString { static String arr[] = {"Now", "is", "the", "time", "for", "all", "good", "men", "to", "come", "to", "the", "aid", "of", "their", "country" }; public static void main(String args[]) { for (int j = 0; i < arr.length; j++) { for (int i = j + 1; i < arr.length; i++) { if (arr[i].compareTo(arr[j]) < 0) { String t = arr[j]; arr[j] = arr[i]; arr[i] = t; } } System.out.println(arr[j]); } } }


    Разделители



    Разделители

    Лишь несколько групп символов, которые могут появляться в синтаксически правильной Java-программе, все еще остались неназваннами. Это - простые разделители, которые влияют на внешний вид и функциональность программного кода.
    СимволыНазваниеДля чего применяются
    ( )круглые скобкиВыделяют списки параметров в объявлении и вызове метода, также используются для задания приоритета операций в выражениях, выделения выражений в операторах управления выполнением программы, и в операторах приведения типов.
    { }фигурные скобкиСодержат значения автоматически инициализируемых массивов, также используются для ограничения блока кода в классах, методах и локальных областях видимости.
    [ ]квадратные скобкиИспользуются в объявлениях массивов и при доступе к отдельным элементам массива.
    ; точка с запятой Разделяет операторы.
    ,запятаяРазделяет идентификаторы в объявлениях переменных, также используется для связи операторов в заголовке цикла for.
    .точкаОтделяет имена пакетов от имен подпакетов и классов, также используется для отделения имени переменной или метода от имени переменной.


    Раздельные файлы заголовков



    Раздельные файлы заголовков

    Когда-то великим достижением считались файлы заголовков, в которые можно было поместить прототипы классов и распространять их вместе с оттранслированными двоичными файлами, содержащими реальные реализации этих классов. Поддержка этих файлов заголовков (ведь они должны соответствовать реализации, их версия должна совпадать с версией классов, хранящихся в оттранслированных двоичных файлах) становилась непосильной задачей по мере роста размеров библиотек классов.
    В Java такое невозможно, поскольку в ней отсутствуют файлы заголовков. Тип и видимость членов класса при трансляции встраиваются внутрь файла *.class (файла с байт-кодом). Интерпретатор Java пользуется этой информацией в процессе выполнения кода, так что не существует способа получить доступ к закрытым переменным класса извне.


    Repaint



    repaint

    Метод repaint используется для принудительного перерисовывания апплета. Этот метод, в свою очередь, вызывает метод update. Однако, если ваша система медленная или сильно загружена, метод update может и не вызваться. Близкие по времени запросы на перерисовку могут объединяться AWT, так что метод update может вызываться спорадически. Если вы хотите добиться ритмичной смены кадров изображения, воспользуйтесь методом repaint(time) - это позволит уменьшить количество кадров, нарисованных не вовремя. repaint(time)
    Вы можете вызывать метод repaint, устанавливая крайний срок для перерисовки (этот период задается в миллисекундах относительно времени вызова repaint). repaint(x, y, w, h)
    Эта версия ограничивает обновление экрана заданным прямоугольником, изменены будут только те части экрана, которые в нем находятся. repaint(time, x, у, w, h)
    Этот метод - комбинация двух предыдущих.


    Replace



    replace

    Методу replace в качестве параметров задаются два символа. Все сим-волы, совпадающие с первым, заменяются в новой копии строки на вто-рой символ. "Hello".replace('l' , 'w') -> "Hewwo"


    Resume



    resume

    Метод resume используется для активизации подпроцесса, приостановленного вызовом suspend. При этом не гарантируется, что после вызова resume подпроцесс немедленно начнет выполняться, поскольку в этот момент может выполняться другой более высокоприоритетный процесс. Вызов resume лишь делает подпроцесс способным выполняться, а то, когда ему будет передано управление, решит планировщик. setPriority(int p)
    Метод setPriority устанавливает приоритет подпроцесса, задаваемый целым значением передаваемого методу параметра. В классе Thread есть несколько предопределенных приоритетов-констант: MIN_PRIORITY, NORM_PRIORITY и MAX_PRIORITY, соответствующих соответственно значениям 1, 5 и 10. Большинство пользовательских приложений должно выполняться на уровне NORM_PRIORITY плюс-минус 1. Приоритет фоновых заданий, например, сетевого ввода-вывода или перерисовки экрана, следует устанавливать в MIN_PRIORITY. Запуск подпроцессов на уровне MAX_PRIORITY требует осторожности. Если в подпроцессах с таким уровнем приоритета отсутствуют вызовы sleep или yield, может оказаться, что вся исполняющая система Java перестанет реагировать на внешние раздражители. SetPriority
    Этот метод возвращает текущий приоритет подпроцесса - целое значение в диапазоне от 1 до 10. setName(String name)
    Метод setName присваивает подпроцессу указанное в параметре имя. Это помогает при отладке программ с параллельными подпроцессами. Присвоенное с помощью setName имя будет появляться во всех трассировках стека, которые выводятся при получении интерпретатором неперехваченного исключения. getName
    Метод getName возвращает строку с именем подпроцесса, установленным с помощью вызова setName.
    Есть еще множество функций и несколько классов, например, ThreadGroup и SecurityManager, которые имеют отношение к подпроцессам, но эти области в Java проработаны еще не до конца. Скажем лишь, что при необходимости можно получить информацию об этих интерфейсах из документации по JDK API.


    Return



    return

    В следующей главе вы узнаете, что в Java для реализации процедурного интерфейса к объектам классов используется разновидность подпрограмм, называемых методами. Подпрограмма main, которую мы использовали до сих пор - это статический метод соответствующего класса-примера. В любом месте программного кода метода можно поставить оператор return, который приведет к немедленному завершению работы и передаче управления коду, вызвавшему этот метод. Ниже приведен пример, иллюстрирующий использование оператора return для немедленного возврата управления, в данном случае - исполняющей среде Java. class ReturnDemo { public static void main(String args[]) { boolean t = true; System.out.println("Before the return"); //Перед оператором return if (t) return; System.out.println("This won't execute"); //Это не будет выполнено } } Замечание
    Замечание


    Зачем в этом примере использован оператор if (t)? Дело в том, не будь этого оператора, транслятор Java догадался бы, что последний оператор println никогда не будет выполнен. Такие случаи в Java считаются ошибками, поэтому без оператора if оттранслировать этот пример нам бы не удалось.


    Революция по имени Java



    Революция по имени Java

    Вообще опасно объявлять каждую новую технологию программирования революционной. Если вы поторопитесь подать свой голос за признание технологии, подобной той, которая реализована в языке Java, революционной — вас могут закидать тухлыми яйцами или занести в разряд пустозвонов, падких на модные новинки. Что же в таком случае делает тот или иной продукт революционным ? Он не может быть только лишь компактней, быстрее и дешевле. Такой продукт должен изменить весь стиль работы, радикально упростив решение сложных проблем.
    Создание языка Java — это действительно один из самых значительных шагов вперед в области разработки сред программирования за последние 20 лет. Язык HTML (Hypertext Markup Language — язык разметки гипертекста) был необходим для статического размещения страниц во “Всемирной паутине” WWW (World Wide Web). Язык Java потребовался для качественного скачка в создании интерактивных продуктов для сети Internet.
    Три ключевых элемента объединились в технологии языка Java и сделали ее в корне отличной от всего, существующего на сегодняшний день.
  • Java предоставляет для широкого использования свои апплеты (applets) — небольшие, надежные, динамичные, не зависящие от платформы активные сетевые приложения, встраиваемые в страницы Web. Апплеты Java могут настраиваться и распространяться потребителям с такой же легкостью, как любые документы HTML.

  • Java высвобождает мощь объектно-ориентированной разработки приложений, сочетая простой и знакомый синтаксис с надежной и удобной в работе средой разработки. Это позволяет широкому кругу программистов быстро создавать новые программы и новые апплеты.

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

  • Давайте поближе познакомимся со всеми этими тремя аспектами, но сначала – история создания.


    Революционный язык программирования



    Революционный язык программирования

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


    Результат запуска этого примера :



    Результат запуска этого примера :

    С:\> java equalsDemo Hello equals Hello -> true Hello equals Good-bye -> false Hello equals HELLO -> false Hello equalsIgnoreCase HELLO -> true В классе String реализована группа сервисных методов, являющихся специализированными версиями метода equals. Метод regionMatches используется для сравнения подстроки в исходной строке с подстрокой в строке-параметре. Метод startsWith проверяет, начинается ли данная подстрока фрагментом, переданным методу в качестве параметра. Метод endsWith проверяет совпадает ли с параметром конец строки.


    RGBImageFilter



    RGBImageFilter

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


    Рисование "каракулей" с использованием встроенных классов



    Рисование "каракулей" с использованием встроенных классов

    Модель обработки событий Java 1.1 разработана с учетом того, чтобы хорошо сочетаться с другой новой особенностью Java 1.1: встроенными классами (глава, посвященная им, еще не написана ;-(). В следующем примере показано, как изменится данный апплет, если слушатели событий будут реализованы в виде анонимных встроенных классов. Обратите внимание на компактность данного варианта программы. Новая особенность, добавленная в апплет - кнопка Clear. Для этой кнопки зарегистрирован объект ActionListener, а сама она выполняет очистку экрана при наступлении соответствующего события. /* */ import java.applet.*; import java.awt.*; import java.awt.event.*; public class Scribble3 extends Applet { int last_x, last_y; public void init() { // Определяет, создает и регистрирует объект MouseListener. this.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { last_x = e.getX(); last_y = e.getY(); } } ); // Определяет, создает и регистрирует объект MouseMotionListener. this.addMouseMotionListener(new MouseMotionAdapter() { public void mouseDragged(MouseEvent e) { Graphics g = getGraphics(); int x = e.getX(), y= e.getY(); g.setColor(Color.black); g.drawLine(last_x, last_y, x, y); last_x = x; last_y = y; } }); // Создает кнопку Clear. Button b = new Button("Clear"); // Определяет, создает и регистрирует объект слушателя // для обработки события, связанного с нажатием кнопки. b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { // стирание каракулей Graphics g = getGraphics(); g.setColor(getBackground()); g.fillRect(0, 0, getSize().width, getSize().height); } }); // Добавляет кнопку в апплет. this.add(b); } }


    в котором используется модель обработки



    Рисование "каракулей" в Java 1.0

    Классический апплет, в котором используется модель обработки событий Java 1.0. В нем методы mouseDown() и mouseDragO переопределены таким образом, чтобы пользователь имел возможность рисовать "каракули" с помощью мыши. Также переопределен метод keyDown(), чтобы при нажатии клавиши [С] экран очищался, и метод action(), чтобы экран очищался после щелчка на кнопке Clear. /* */ import java.applet.*; import java.awt.*; /** Простой апплет, в котором используется модель обработки событий 1.0 */ public class Scribble1 extends Applet { private int lastx, lasty; // Хранят координаты курсора мыши. Button clear_button; // Кнопка Clear. Graphics g; // Объект Graphics,который необходимо нарисовать. /** Инициализация кнопки и объекта Graphics */ public void init() { clear_button = new Button("Clear"); this.add(clear_button); g = this.getGraphics(); } /** Реакция на нажатие кнопки мыши */ public boolean mouseDown(Event e, int x, int y) { lastx = x; lasty = y; return true; } /** Реакция на перетаскивание с помощью мыши */ public boolean mouseDrag(Event e, int x, int y) { g.setColor(Color.black) ; g.drawLine(lastx, lasty, x, y); lastx = x; lasty = y; return true; } /** Реакция на нажатие клавиши [С] */ public boolean keyDown(Event e, int key) { if ((e.id == Event.KEY_PRESS) && (key == 'с' ) ) { clear() ; return true; } else return false; } /** Реакция на нажатие кнопки Clear */ public boolean action(Event e, Object arg) { if (e.target == clear_button) { clear(); return true; } else return false; } /** Метод для стирания каракулей */ public void clear() { g.setColor(this.getBackground()); g.fillRect(0, 0, bounds().width, bounds().height); } }


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



    Рисование "каракулей" в Java 1.1

    Модель обработки событий Java 1.1 является достаточно гибкой и предоставляет пользователю ряд возможностей для структуризации программы обработки событий. Первый из этих способов продемонстрирован в примере. В апплете данной версии реализованы интерфейсы MouseListener и MouseMotionListener, регистрирующие себя с помощью своих же методов addMouseListener() и addMouseMotionListener(). /* */ import java.applet.*; import java.awt.*; import java.awt.event.*; public class Scribble2 extends Applet implements MouseListener, MouseMotionListener { private int last_x, last_y; public void init() { // Сообщает данному апплету о том, какие объекты // классов MouseListener и MouseMotionListener он должен оповещать // о событиях, связанных с мышью и ее перемещением. // Поскольку интерфейс реализуется в самом апплете, // при этом будут вызываться методы апплета. this.addMouseListener(this) ; this.addMouseMotionListener(this); } // Метод интерфейса MouseListener. Вызывается при нажатии // пользователем кнопки мыши. public void mousePressed(MouseEvent e) { last_x = e.getX(); last_y = e.getY(); } // Метод интерфейса MouseMotionListener. Вызывается при // перемещении мыши с нажатой кнопкой. public void mouseDragged(MouseEvent e) { Graphics g = this.getGraphics(); int x = e.getX(), y = e.getY(); g.drawLine(last_x, last_y, x, y); last_x = x; last_y = y; } // Другие, не используемые методы интерфейса MouseListener. public void mouseReleased(MouseEvent e) {;} public void mouseClicked(MouseEvent e) {;} public void mouseEntered(MouseEvent e) {;} public void mouseExited(MouseEvent e) {;} // Другой метод интерфейса MouseMotionListener. public void mouseMoved(MouseEvent e) {;} }


    Run



    run

    Метод run - это тело выполняющегося подпроцесса. Это - единственный метод интерфейса Runnable. Он вызывается из метода start после того, как исполняющая среда выполнит необходимые операции по инициализации нового подпроцесса. Если происходит возврат из метода run, текущий подпроцесс останавливается.


    Runnable



    Runnable

    Не очень интересно работать только с одним подпроцессом, а как можно создать еще один? Для этого нам понадобится другой экземпляр класса Thread. При создании нового объекта Thread ему нужно указать, какой программный код он должен выполнять. Вы можете запустить подпроцесс с помощью любого объекта, реализующего интерфейс Runnable. Для того, чтобы реализовать этот интерфейс, класс должен предоставить определение метода run. Ниже приведен пример, в котором создается новый подпроцесс. class ThreadDemo implements Runnable { ThreadDemo() { Thread ct = Thread.currentThread(); System.out.println("currentThread: " + ct); Thread t = new Thread(this, "Demo Thread"); System.out.println("Thread created: " + t); t.start(); try { Thread.sleep(3000); } catch (InterruptedException e) { System.out.println("interrupted"); } System.out.println("exiting main thread"); } public void run() { try { for (int i = 5; i > 0; i--) { System.out.println("" + i); Thread.sleep(1000); } } catch (InterruptedException e) { System.out.println("child interrupted"); } System.out.println("exiting child thread"); } public static void main(String args[]) { new ThreadDemo(); } }
    Обратите внимание на то, что цикл внутри метода run выглядит точно так же, как и в предыдущем примере, только на этот раз он выполняется в другом подпроцессе. Подпроцесс main с помощью оператора new Thread(this, "Demo Thread") создает новый объект класса Thread, причем первый параметр конструктора — this — указывает, что нам хочется вызвать метод run текущего объекта. Затем мы вызываем метод start, который запускает подпроцесс, выполняющий метод run. После этого основной подпроцесс (main) переводится в состояние ожидания на три секунды, затем выводит сообщение и завершает работу. Второй подпроцесс — “Demo Thread” — при этом по-прежнему выполняет итерации в цикле метода run до тех пор пока значение счетчика цикла не уменьшится до нуля. Ниже показано, как выглядит результат работы этой программы этой программы после того, как она отработает 5 секунд. С:\> java ThreadDemo Thread created: Thread[Demo Thread,5,main] 5 4 3 exiting main thread 2 1 exiting child thread
    Приоритеты подпроцессов
    Если вы хотите добиться от Java предсказуемого независимого от платформы поведения, вам следует проектировать свои подпроцессы таким образом, чтобы они по своей воле освобождали процессор. Ниже приведен пример с двумя подпроцессами с различными приоритетами, которые не ведут себя одинаково на различных платформах. Приоритет одного из подпроцессов с помощью вызова setPriority устанавливается на два уровня выше Thread. NORM_PRIORITY, то есть, умалчиваемого приоритета. У другого подпроцесса приоритет, наоборот, на два уровня ниже. Оба этих подпроцесса запускаются и работают в течение 10 секунд. Каждый из них выполняет цикл, в котором увеличивается значение переменной-счетчика. Через десять секунд после их запуска основной подпроцесс останавливает их работу, присваивая условию завершения цикла while значение true и выводит значения счетчиков, показывающих, сколько итераций цикла успел выполнить каждый из подпроцессов. class Clicker implements Runnable { int click = 0; private Thread t; private boolean running = true; public clicker(int p) { t = new Thread(this); t.setPriority(p); } public void run() { while (running) { click++; } } public void stop() { running = false; } public void start() { t.start(); } } class HiLoPri { public static void main(String args[]) { Thread.currentThread().setPriority(Thread.MAX_PRIORITY); clicker hi = new clicker(Thread.NORM_PRIORITY + 2); clicker lo = new clicker(Thread.NORM_PRIORITY - 2); lo.start(); hi.start(); try Thread.sleep(-10000) { } catch (Exception e) { } lo.stop(); hi.stop(); System.out.println(lo.click + " vs. " + hi.click); } }
    По значениям, фигурирующим в распечатке, можно заключить, что подпроцессу с низким приоритетом достается меньше на 25 процентов времени процессора: C:\>java HiLoPri 304300 vs. 4066666


    Runtime Класс Runtime инкапсулирует



    Runtime Класс Runtime инкапсулирует интерпретатор Java. Вы не можете создать нового представителя этого класса, но можете, вызвав его статический метод, получить ссылку на работающий в данный момент объект Runtime. Обычно апплеты и другие непривелигированные программы не могут вызвать ни один из методов этого класса, не возбудив при этом исключения SecurityException. Одна из простых вещей, которую вы можете проделать с объектом Runtime - его останов, для этого достаточно вызвать метод exit(int code).
    Управление памятью


    Хотя Java и представляет собой систему с автоматической сборкой мусора, вы для проверки эффективности своего кода можете захотеть узнать, каков размер "кучи" и как много в ней осталось свободной памяти. Для получения этой информации нужно воспользоваться методами totalMemory и freeMemory.


    Счет за услуги



    Счет за услуги

    В пакете java.util есть еще несколько классов по работе с битами, различными форматами дат и архивами (подкаталог zip). Структуры данных и системные интерфейсы, которые вы изучили в этой главе, окажут вам неоценимую помощь, когда вы начнете писать на Java более сложные программы. В следующих двух главах мы будем знакомиться с потоками ввода-вывода и сетевыми средствами.


    Scrollbar



    Scrollbar

    Объекты Scrollbar (линейки прокрутки) используются для выбора подмножества значений между заданными минимумом и максимумом. Визуально у линейки прокрутки есть несколько органов управления, ориентированных либо вертикально, либо горизонтально. Стрелки на каждом из ее концов показывают, что, нажав на них, вы можете продвинуться на один шаг в соответствующем направлении. Текущее положение отображается с помощью движка линейки прокрутки, которым пользователь также может управлять, устанавливая требуемое положение линейки.
    Конструктор класса Scrollbar позволяет задавать ориентацию линейки прокрутки - для этого предусмотрены константы VERTICAL и HORIZONTAL. Кроме того с помощью конструктора можно задать начальное положение и размер движка, а так же минимальное и максимальное значения, в пределах которых линейка прокрутки может изменять параметр. Для получения и установки текущего состояния линейки прокрутки используются методы getValue и setValue. Кроме того воспользовавшись методами getMinimum и getMaximum, вы можете получить рабочий диапазон объекта. Ниже приведен пример, в котором создается и вертикальная, и горизонтальная линейки прокрутки. /* */ import java.awt.*; import java.applet.*; public class ScrollbarDemo extends Applet { public void init() { setLayout(null); int width=Integer.parseInt(getParameter("width")); int height=Integer. parseInt(getParameter("height")); Scrollbar hs=new Scrollbar(Scrollbar.HORIZONTAL,50,width/10,0,100); Scrollbar vs=new Scrollbar(Scrollbar.VERTICAL,50,height/2,0,100); add(hs); add(vs); int thickness = 16; hs.reshape(0, height-thickness,width-thickness,thickness); vs.reshape(width-thickness,0,thickness,height-thickness); } }
    В этом примере скроллируется, конечно, пустая область - ScrollbarDemo.html.


    Сдвиги влево и вправо



    Сдвиги влево и вправо

    Оператор Оператор >> означает в языке Java сдвиг вправо. Он перемещает все биты своего левого операнда вправо на число позиций, заданное правым операндом. Когда биты левого операнда выдвигаются за самую правую позицию слова, они теряются. При сдвиге вправо освобождающиеся старшие (левые) разряды сдви-гаемого числа заполняются предыдущим содержимым знакового разряда. Такое поведение называют расширением знакового разряда.
    В следующей программе байтовое значение преобразуется в строку, содержащую его шестнадцатиричное представление. Обратите внимание - сдвинутое значение приходится маскировать, то есть логически умножать на значение 0х0f, для того, чтобы очистить заполняемые в результате расширения знака биты и по-низить значение до пределов, допустимых при индексировании массива шестнадцатиричных цифр. class HexByte { static public void main(String args[]) { char hex[] = { '0', '1, '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f }; byte b = (byte) 0xf1; System.out.println("b = 0x" + hex[(b >> 4) & 0x0f] + hex[b & 0x0f]); } }
    Ниже приведен результат работы этой программы: С:\> java HexByte b = 0xf1


    Сериализация объектов



    Сериализация объектов

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


    Сеть и только сеть



    Сеть и только сеть

    Сетевые классы Java предоставляют ясный и простой в использовании интерфейс для работы в Internet. Фундамент, заложенный в пакете java.net - хорошая база для дальнейшего развития, которая позволит Java эволюционировать вместе с Internet.


    SetLength



    setLength

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


    SetPaintMode() и setXORMode(Color)



    setPaintMode() и setXORMode(Color)

    Режим отрисовки paint - используемый по умолчанию метод заполнения графических изображений, при котором цвет пикселей изменяется на заданный. XOR устанавливает режим рисования, когда результирующий цвет получается выполнением операции XOR (исключающее или) для текущего и указанного цветов (особенно полезно для анимации).


    за шагом



    Шаг за шагом

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


    Short



    short

    short - это знаковый 16-битовый тип. Его диапазон - от -32768 до 32767. Это, вероятно, наиболее редко используемый в Java тип, поскольку он определен, как тип, в котором старший байт стоит первым. short s; short t = Ox55aa; Замечание
    ЗАМЕЧАНИЕ


    Случилось так, что на ЭВМ различных архитектур порядок байтов в слове различается, например, старший байт в двухбайтовом целом short может храниться первым, а может и последним. Первый случай имеет место в архитектурах SPARC и Power PC, второй - для микропроцессоров Intel x86. Переносимость программ Java требует, чтобы целые значения одинаково были представлены на ЭВМ разных архитектур.


    Шрифты



    Шрифты

    Библиотека AWT обеспечивает большую гибкость при работе со шрифтами благодаря предоставлению соответствующих абстракций и возможности динамического выбора шрифтов. Вот очень короткая программа, которая печатает на консоли Java имена всех имеющихся в системе шрифтов. /* * <applet code="WhatFontsAreHere" width=100 height=40> * </applet> * */ import java.applet.*; import java.awt.*; public class WhatFontsAreHere extends Applet { public void init() { String FontList[]; FontList = getToolkit().getFontList(); for (int i=0; i < FontList.length; i++) { System.out.println(i + ": " + FontList[i]); } } }


    Символьные литералы



    Символьные литералы

    Символы в Java - это индексы в таблице символов UNICODE. Они представляют собой 16-битовые значения, которые можно преобразовать в целые числа и к которым можно применять операторы целочисленной арифметики, например, операторы сложения и вычитания. Символьные литералы помещаются внутри пары апострофов (' '). Все видимые символы таблицы ASCII можно прямо вставлять внутрь пары апострофов: - 'a', 'z', '@'. Для символов, которые невозможно ввести непосредственно, предусмотрено несколько управляющих последовательностей.


    Символы



    Символы

    Поскольку в Java для представления символов в строках используется кодировка Unicode, разрядность типа char в этом языке - 16 бит. В нем можно хранить десятки тысяч символов интернационального набора символов Unicode. Диапазон типа char - 0..65536. Unicode - это объединение десятков кодировок символов, он включает в себя латинский, греческий, арабский алфавиты, кириллицу и многие другие наборы символов. char c; char c2 = Oxf132; char c3 = ' a'; char c4 = '\n';
    Хотя величины типа char и не используются, как целые числа, вы можете оперировать с ними так, как если бы они были целыми. Это дает вам возможность сложить два символа вместе, или инкрементировать значение символьной переменной. В приведенном ниже фрагменте кода мы, располагая базовым символом, прибавляем к нему целое число, чтобы получить символьное представление нужной нам цифры. int three = 3; char one = '1'; char four = (char) (three+ one);
    В результате выполнения этого кода в переменную four заносится символьное представление нужной нам цифры - '4'. Обратите внимание - тип переменной one в приведенном выше выражении повышается до типа int, так что перед занесением результата в переменную four приходится использовать оператор явного приведения типа.


    Синхронизация



    Синхронизация

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


    Синхронизация



    Синхронизация

    Когда двум или более подпроцессам требуется параллельный доступ к одним и тем же данным (иначе говоря, к совместно используемому ресурсу), нужно позаботиться о том, чтобы в каждый конкретный момент времени доступ к этим данным предоставлялся только одному из подпроцессов. Java для такой синхронизации предоставляет уникальную, встроенную в язык программирования поддержку. В других системах с параллельными подпроцессами существует понятие монитора. Монитор - это объект, используемый как защелка. Только один из подпроцессов может в данный момент времени владеть монитором. Когда под-процесс получает эту защелку, говорят, что он вошел в монитор. Все остальные подпроцессы, пытающиеся войти в тот же монитор, будут заморожены до тех пор пока подпроцесс-владелец не выйдет из монитора.
    У каждого Java-объекта есть связанный с ним неявный монитор, а для того, чтобы войти в него, надо вызвать метод этого объекта, отмеченный ключевым словом synchronized. Для того, чтобы выйти из монитора и тем самым передать управление объектом другому подпроцессу, владелец монитора должен всего лишь вернуться из синхронизованного метода. class Callme { void call(String msg) { System.out.println("[" + msg); try Thread.sleep(-1000) {} catch(Exception e) {} System.out.println("]"); } } class Caller implements Runnable { String msg; Callme target; public Caller(Callme t, String s) { target = t; msg = s; new Thread(this).start(); } public void run() { target.call(msg); } } class Synch { public static void main(String args[]) { Callme target = new Callme(); new Caller(target, "Hello."); new Caller(target, "Synchronized"); new Caller(target, "World"); } }
    Вы можете видеть из приведенного ниже результата работы программы, что sleep в методе call приводит к переключению контекста между подпроцессами, так что вывод наших 3 строк-сообщений перемешивается: Hello. Synchronized World
    Это происходит потому, что в нашем примере нет ничего, способного помешать разным подпроцессам вызывать одновременно один и тот же метод одного и того же объекта. Для такой ситуации есть даже специальный термин - race condition (состояние гонки), означающий, что различные подпроцессы пытаются опередить друг друга, чтобы завершить выполнение одного и того же метода. В этом примере для того, чтобы это состояние было очевидным и повторяемым, использован вызов sleep. В реальных же ситуациях это состояние, как правило, трудноуловимо, поскольку непонятно, где именно происходит переключение контекста, и этот эффект менее заметен и не всегда воспроизводятся от запуска к запуску программы. Так что если у вас есть метод (или целая группа методов), который манипулирует внутренним состоянием объекта, используемого в программе с параллельными подпроцессами, во избежание состояния гонки вам следует использовать в его заголовке ключевое слово synchronized.


    Скрытие переменных представителей



    Скрытие переменных представителей

    В языке Java не допускается использование в одной или во вложенных областях видимости двух локальных переменных с одинаковыми именами. Интересно отметить, что при этом не запрещается объявлять формальные параметры методов, чьи имена совпадают с именами переменных представителей. Давайте рассмотрим в качестве примера иную версию метода init, в которой формальным параметрам даны имена х и у, а для доступа к одноименным переменным текущего объекта используется ссылка this. class Point { int х, у; void init(int х, int у) { this.x = х; this.у = у } } class TwoPointsInit { public static void main(String args[]) { Point p1 = new Point(); Point p2 = new Point(); p1.init(10,20); p2.init(42,99); System.out.println("x = " + p1.x + " у = " + p-l.y); System.out.printlnC'x = " + p2.x + " у = " + p2.y); } }


    Слияние строк



    Слияние строк

    Строку String s = + age + " years old."; в которой с помощью оператора + три строки объединяются в одну, про-честь и понять безусловно легче, чем ее эквивалент, записанный с яв-ными вызовами тех самых методов, которые неявно были использованы в первом примере: String s = new StringBuffer("He is ").append(age); s.append(" years old.").toString();
    По определению каждый объект класса String не может изменять-ся. Нельзя ни вставить новые символы в уже существующую строку, ни поменять в ней одни символы на другие. И добавить одну строку в конец другой тоже нельзя. Поэтому транслятор Java преобразует опера-ции, выглядящие, как модификация объектов String, в операции с род-ственным классом StringBuffer. Замечание
    Замечание


    Все это может показаться вам необоснованно сложным. А почему нельзя обойтись одним классом String, позволив ему вести себя при-мерно так же, как StringBuffer? Все дело в производительности. Тот факт, что объекты типа String в Java неизменны, позволяет транслято-ру применять к операциям с ними различные способы оптимизации.


    Сокеты "для клиентов"



    Сокеты "для клиентов"

    TCP/IP-сокеты используются для реализации надежных двунаправленных, ориентированных на работу с потоками соединений точка-точка между узлами Internet. Сокеты можно использовать для соединения системы ввода-вывода Java с программами, которые могут выполняться либо на локальной машине, либо на любом другом узле Internet. В отличие от класса DatagramSocket, объекты класса Socket реализуют высоконадежные устойчивые соединения между клиентом и сервером.
    В пакете java.net классы Socket и ServerSocket сильно отличаются друг от друга. Первое отличие в том, что ServerSocket ждет, пока клиент не установит с ним соединение, в то время, как обычный Socket трактует недоступность чего-либо, с чем он хочет соединиться, как ошибку. Одновременно с созданием объекта Socket устанавливается соединение между узлами Internet. Для создания сокетов вы можете использовать два конструктора:
    Socket(String host, int port) устанавливает соединение между локальной машиной и указанным портом узла Internet, имя которого было передано конструктору. Этот конструктор может возбуждать исключения UnknownHostException и IOException.
    Socket(InetAddress address, int port) выполняет ту же работу, что и первый конструктор, но узел, с которым требуется установить соединение, задается не строкой, а объектом InetAddress. Этот конструктор может возбуждать только IOException.
    Из объекта Socket в любое время можно извлечь информацию об адресе Internet и номере порта, с которым он соединен. Для этого служат следующие методы:
  • getInetAddressQ возвращает объект InetAddress, связанный с данным объектом Socket.
  • getPort() возвращает номер порта на удаленном узле, с которым установлено соединение.
  • getLocalPort() возвращает номер локального порта, к которому присоединен данный объект.

  • После того, как объект Socket создан, им можно воспользоваться для того, чтобы получить доступ к связанным с ним входному и выходному потокам. Эти потоки используются для приема и передачи данных точно так же, как и обычные потоки ввода-вывода, которые мы видели в предыдущей главе:
  • getInputStream() возвращает InputStream, связанный с данным объектом.
  • getOutputStream() возвращает OutputStream, связанный с данным объектом.
  • close() закрывает входной и выходной потоки объекта Socket.

  • Приведенный ниже очень простой пример открывает соединение с портом 880 сервера "timehost" и выводит полученные от него данные. import java.net.*; import java.io.*; class TimeHost { public static void main(String args[]) throws Exception { int c; Socket s = new Socket("timehost.starwave.com",880); InputStream in = s.getInputStream(); while ((c = in.read()) != -1) { System.out.print( (char) c); } s.close(); } }


    Сокеты "для серверов"



    Сокеты "для серверов"

    Как уже упоминалось ранее, Java поддерживает сокеты серверов. Для создания серверов Internet надо использовать объекты класса ServerSocket. Когда вы создаете объект ServerSocket, он регистрирует себя в системе, говоря о том, что он готов обслуживать соединения клиентов. У этого класса есть один дополнительный метод accept(), вызов которого блокирует подпроцесс до тех пор, пока какой-нибудь клиент не установит соединение по соответствующему порту. После того, как соединение установлено, метод accept() возвращает вызвавшему его подпроцессу обычный объект Socket.
    Два конструктора класса ServerSocket позволяют задать, по какому порту вы хотите соединяться с клиентами, и (необязательный параметр) как долго вы готовы ждать, пока этот порт не освободится.
    ServerSocket(int port) создает сокет сервера для заданного порта.
    ServerSocket(int port, int count) создает сокет сервера для заданного порта. Если этот порт занят, метод будет ждать его освобождения максимум count миллисекунд.


    Сообщения



    Сообщения

    Коль скоро вы разделили свою программу на логические части - подпроцессы, вам нужно аккуратно определить, как эти части будут общаться друг с другом. Java предоставляет для этого удобное средство — два подпроцесса могут “общаться” друг с другом, используя методы wait и notify. Работать с параллельными подпроцессами в Java несложно. Язык предоставляет явный, тонко настраиваемый механизм управления созданием подпроцессов, переключения контекстов, приоритетов, синхронизации и обмена сообщениями между подпроцессами.


    Совмещение методов



    Совмещение методов

    Язык Java позволяет создавать несколько методов с одинаковыми именами, но с разными списками параметров. Такая техника называется совмещением методов (method overloading). В качестве примера приведена версия класса Point, в которой совмещение методов использовано для определения альтернативного конструктора, который инициализирует координаты х и у значениями по умолчанию (-1). class Point { int х, у; Point(int х, int у) { this.x = х; this.у = у; } Point() { х = -1; у = -1; } } class PointCreateAlt { public static void main(String args[]) { Point p = new Point(); System.out.println("x = " + p.x + " у = " + p.y); } }
    В этом примере объект класса Point создается не при вызове первого конструктора, как это было раньше, а с помощью второго конструктора без параметров. Вот результат работы этой программы: С:\> java PointCreateAlt х = -1 у = -1 Замечание
    Замечание


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


    Создание строк



    Создание строк

    Java включает в себя стандартное сокращение для этой опера-ции - запись в виде литерала, в которой содержимое строки заключа-ется в пару двойных кавычек. Приводимый ниже фрагмент кода экви-валентен одному из предыдущих, в котором строка инициализировалась массивом типа char. String s = "abc"; System.out.println(s);
    Один из общих методов, используемых с объектами String - метод length, возвращающий число символов в строке. Очередной фрагмент вы-водит число 3, поскольку в используемой в нем строке - 3 символа. String s = "abc"; System.out.println(s.length);
    В Java интересно то, что для каждой строки-литерала создается свой представитель класса String, так что вы можете вызывать методы этого класса непосредственно со строками-литералами, а не только со ссылоч-ными переменными. Очередной пример также выводит число 3. System.out.println("abc".Length());


    Специальный синтаксис для работы со строками



    Специальный синтаксис для работы со строками

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


    Сравнение 3 Если у вас есть два



    Сравнение 3 Если у вас есть два объекта типа Date, и вы хотите их сравнить, то можете преобразовать хранящиеся в них даты в значения типа long, и сравнить полученные даты, выраженные в миллисекундах. Класс Date включает в себя три метода, которые можно использовать для прямого сравнения дат: - before, after и equals. Например, вызов new Date(96, 2, 18).before(new Date(96, 2, 12)
    возвращает значение true, поскольку 12-й день месяца предшествует 18-му.
    Строки и часовые пояса


    Объекты Date можно конвертировать в текстовые строки различных форматов. Прежде всего, обычный метод toString преобразует объект Date в строку, которая выглядит, как "Thu Feb 15 22:42:04 1996". Метод toLocaleString преобразует дату в более короткую строку, выглядящую примерно так: "02/15/96 22:42:04". И, наконец, метод toGMTString возвращает дату в формате среднего времени по Гринвичу: "16 Feb 1996 06:42:04 GMT".


    Сравнение



    Сравнение

    Если вы хотите узнать, одинаковы ли две строки, вам следует воспользоваться методом equals класса String. Альтернативная форма этого метода называется equalsIgnoreCase, при ее использовании различие ре-гистров букв в сравнении не учитывается. Ниже приведен пример, иллюстрирующий использование обоих методов: class equalDemo { public static void main(String args[]) { String s1="Hello"; String s2="Hello"; String s3="Good-bye"; String s4="HELLO"; System.out.println(s1+"equals"+s2+"->"+s1.equals(s2)); System.out.println(s1+"equals"+s3+"->"+s1.equals(s3)); System.out.println(s1+"equals"+s4+"->"+s1.equals(s4)); System.out.println(s1+"equalsIgnoreCase"+s4+"->"+ s1.equalsIgnoreCase(s4)); } }


    Stack



    Stack

    Stack - подкласс класса Vector, который реализует простой механизм типа "первым вошел - первым вышел" (FIFO). В дополнение к стандартным методам своего родительского класса, Stack предлагает метод push для помещения элемента в вершину стека и pop для извлечения из него верхнего элемента. С помощью метода peek вы можете получить верхний элемент, не удаляя его из стека. Метод empty служит для проверки стека на наличие элементов - он возвращает true, если стек пуст. Метод search ищет заданный элемент в стеке, возвращая количество операция pop, которые требуются для того чтобы перевести искомый элемент в вершину стека. Если заданный элемент в стеке отсутствует, этот метод возвращает -1.
    Ниже приведен пример программы, которая создает стек, заносит в него несколько объектов типа Integer, а затем извлекает их. import java.util.Stack; import java.util.EmptyStackException; class StackDemo { static void showpush(Stack st, int a) { st.push(new Integer(a)); System.out.println("push(" + a + ")"); System.out.println("stack: " + st); } static void showpop(Stack st) { System.out.print("pop -> "); Integer a = (Integer) st.pop(); System.out.println(a); System.out.println("stack: " + st); } public static void main(String args[]) { Stack st = new Stack(); System.out.println("stack: " + st); showpush(st, 42); showpush(st, 66); showpush(st, 99); showpop(st); showpop(st); showpop(st); try { showpop(st); } catch (EmptyStackException e) { System.out.println("empty stack"); } } }
    Ниже приведен результат, полученный при запуске этой программы. Обратите внимание на то, что обработчик исключений реагирует на попытку извлечь данные из пустого стека. Благодаря этому мы можем аккуратно обрабатывать ошибки такого рода. C:\> java StackDemo stack: [] push(42) stack: [42] push(66) stack: [42, 66] push(99) stack: [42, 66, 99] pop -> 99 stack: [42, 66] pop -> 66 stack: [42] pop -> 42 stack: [] pop -> empty stack


    Start



    start

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


    Start



    start

    Метод start вызывается сразу же после метода init. Он также используется в качестве стартовой точки для возобновления работы после того, как апплет был остановлен. В то время, как метод init вызывается только однажды - при загрузке апплета, start вызывается каждый раз при выводе HTML-документа, содержащего апплет, на экран. Так, например, если пользователь перейдет к новой WWW-странице, а затем вернется назад к странице с апплетом, апплет продолжит работу с метода start.


    Static



    static

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


    Static



    static

    Иногда требуется создать метод, который можно было бы использовать вне контекста какого-либо объекта его класса. Так же, как в случае main, все, что требуется для создания такого метода - указать при его объявлении модификатор типа static. Статические методы могут непосредственно обращаться только к другим статическим методам, в них ни в каком виде не допускается использование ссылок this и super. Переменные также могут иметь тип static, они подобны глобальным переменным, то есть доступны из любого места кода. Внутри статических методов недопустимы ссылки на переменные представителей. Ниже приведен пример класса, у которого есть статические переменные, статический метод и статический блок инициализации. class Static { static int a = 3; static int b; static void method(int x) { System.out.println("x = " + x); System.out.println("a = " + a); System.out.println("b = " + b); } static { System.out.println("static block initialized"); b = a * 4; } public static void main(String args[]) { method(42); } }
    Ниже приведен результат запуска этой программы. С:\> java Static static block initialized Х = 42 А = 3 B = 12
    В следующем примере мы создали класс со статическим методом и несколькими статическими переменными. Второй класс может вызывать статический метод по имени и ссылаться на статические переменные непосредственно через имя класса. class StaticClass { static int a = 42; static int b = 99; static void callme() { System.out.println("a = " + a); } } class StaticByName { public static void main(String args[]) { StaticClass.callme(); System.out.println("b = " + StaticClass.b); } }
    А вот и результат запуска этой программы: С:\> Java StaticByName а = 42 b = 99


    Степенные, показательные и логарифмические функции



    Степенные, показательные и логарифмические функции

  • pow(double у, double x) возвращает у, возведенное в степень х. Так, например, pow(2.0, 3.0) равно 8.0.
  • exp(double х) возвращает е в степени х.
  • log(double х) возвращает натуральный логарифм х.
  • sqrt(double х) возвращает квадратный корень х.








  • Stop



    stop

    Вызов метода stop приводит к немедленной остановке подпроцесса. Это - способ мгновенно прекратить выполнение текущего подпроцесса, особенно если метод выполняется в текущем подпроцессе. В таком случае строка, следующая за вызовом метода stop, никогда не выполняется, поскольку контекст подпроцесса "умирает" до того, как метод stop возвратит управление. Более аккуратный способ остановить выполнение подпроцесса - установить значение какой-либо переменной-флага, предусмотрев в методе run код, который, проверив состояние флага, завершил бы выполнение подпроцесса.


    Stop



    stop

    Метод stop вызывается в тот момент, когда браузер покидает HTML-документ, содержащий апплет. При вызове метода stop апплет еще работает. Вы должны использовать этот метод для приостановки тех подпроцессов, работа которых необязательна при невидимом апплете. После того, как пользователь снова обратится к этой странице, вы должны будете возобновить их работу в методе start.


    StringBuffer



    StringBuffer

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


    StringWidth



    stringWidth

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


    StrinsTokenizer



    StrinsTokenizer

    Обработка текста часто подразумевает разбиение текста на последовательность лексем - слов (tokens). Класс StringTokenizer предназначен для такого разбиения, часто называемого лексическим анализом или сканированием. Для работы StringTokenizer требует входную строку и строку символов-разделителей. По умолчанию в качестве набора разделителей используются обычные символы-разделители: пробел, табуляция, перевод строки и возврат каретки. После того, как объект StringTokenizer создан, для последовательного извлечения лексем из входной строки используется его метод nextToken. Другой метод - hasMoreTokens - возвращает true в том случае, если в строке еще остались неизвлеченные лексемы. StringTokenizer также реализует интерфейс Enumeration, а это значит, что вместо методов hasMoreTokens и nextToken вы можете использовать методы hasMoreElements и nextElement, соответственно.
    Ниже приведен пример, в котором для разбора строки вида "ключ=значение" создается и используется объект StringTokenizer. Пары "ключ=значение" разделяются во входной строке двоеточиями. import java.util.StringTokenizer; class STDemo { static String in = "title=The Java Handbook:" + "author=Patrick Naughton:" + "isbn=0-07-882199-1:" + "ean=9 780078 821998:" + "email=naughton@starwave. corn"; public static void main(String args[]) { StringTokenizer st = new StringTokenizer(in, "=:"); while (st.hasMoreTokens()) { String key = st.nextToken(); String val = st.nextToken(); System.out.println(key + "\t" + val); } } }


    Строчные литералы



    Строчные литералы

    Строчные литералы в Java выглядят точно также, как и во многих других языках - это произвольный текст, заключенный в пару двойных кавычек (""). Хотя строчные литералы в Java реализованы весьма своеобразно (Java создает объект для каждой строки), внешне это никак не проявляется. Примеры строчных литералов: "Hello World!"; "две\строки; \ А это в кавычках\"". Все управляющие последовательности и восьмеричные / шестнадцатиричные формы записи, которые определены для символьных литералов, работают точно так же и в строках. Строчные литералы в Java должны начинаться и заканчиваться в одной и той же строке исходного кода. В этом языке, в отличие от многих других, нет управляющей последовательности для продолжения строкового литерала на новой строке.


    В этой строке использовано зарезервированное



    Строка 1

    class HelloWorld { В этой строке использовано зарезервированное слово class. Оно говорит транслятору, что мы собираемся описать новый класс. Полное описание класса располагается между открывающей фигурной скобкой в первой строке и парной ей закрывающей фигурной скобкой в строке 5. Фигурные скобки в Java используются точно так же, как в языках С и С++.


    на первый взгляд, чрезмерно сложная



    Строка 2

    public static void main (String args []) { Такая, на первый взгляд, чрезмерно сложная строка примера является следствием важного требования, заложенного при разработке языка Java. Дело в том, что в Java отсутствуют глобальные функции. Поскольку подобные строки будут встречаться в большинстве примеров первой части книги, давайте пристальнее рассмотрим каждый элемент второй строки.


    В этой строке выполняется метод



    Строка 3

    System. out. prlntln("Hello World!"); В этой строке выполняется метод println объекта out. Объект out объявлен в классе OutputStream и статически инициализируется в классе System. В главах 9 и 13 у вас будет шанс познакомиться с нюансами работы классов String и OutputStream.

    Закрывающей фигурной скобкой в строке 4 заканчивается объявление метода main, а такая же скобка в строке 5 завершает объявление класса HelloWorld.


    Substring Вы можете извлечь подстроку



    substring Вы можете извлечь подстроку из объекта String, используя метод sub-string. Этот метод создает новую копию символов из того диапазона ин-дексов оригинальной строки, который вы указали при вызове. Можно указать только индекс первого символа нужной подстроки - тогда будут скопированы все символы, начиная с указанного и до конца строки. Также можно указать и начальный, и конечный индексы - при этом в новую строку будут скопированы все символы, начиная с первого ука-занного, и до (но не включая его) символа, заданного конечным индек-сом. "Hello World".substring(6) -> "World" "Hello World".substring(3,8) -> "lo Wo"
    concat


    Слияние, или конкатенация строк выполняется с помощью метода concat. Этот метод создает новый объект String, копируя в него содер-жимое исходной строки и добавляя в ее конец строку, указанную в параметре метода. "Hello".concat(" World") -> "Hello World"


    Super



    super

    В примере с классом Point3D частично повторялся код, уже имевшийся в суперклассе. Вспомните, как во втором конструкторе мы использовали this для вызова первого конструктора того же класса. Аналогичным образом ключевое слово super позволяет обратиться непосредственно к конструктору суперкласса (в Delphi / С++ для этого используется ключевое слово inherited). class Point3D extends Point { int z; Point3D(int x, int у, int z) { super(x, y); // Здесь мы вызываем конструктор // суперкласса this.z=z; public static void main(String args[]) { Point3D p = new Point3D(10, 20, 30); System.out.println( " x = " + p.x + " y = " + p.y + " z = " + p.z); } }
    Вот результат работы этой программы: С:\> java Point3D x = 10 у = 20 z = 30


    Suspend



    suspend

    Метод suspend отличается от метода stop тем, что метод приостанавливает выполнение подпроцесса, не разрушая при этом его системный контекст. Если выполнение подпроцесса приостановлено вызовом suspend, вы можете снова активизировать этот подпроцесс, вызвав метод resume.


    Свойства окружения



    Свойства окружения

    Исполняющая среда Java предоставляет доступ к переменным окружения через представителя класса Properties (описанного ранее в этой главе), с которым можно работать с помощью метода System.getProperty. Для получения полного списка свойств можно вызвать метод System.getProperties().


    Switch



    switch

    Оператор switch обеспечивает ясный способ переключения между различными частями программного кода в зависимости от значения одной переменной или выражения. Общая форма этого оператора такова: switch ( выражение ) { case значение1: break; case значение2: break; case значением: break; default: }
    Результатом вычисления выражения может быть значение любого простого типа, при этом каждое из значений, указанных в операторах case, должно быть совместимо по типу с выражением в операторе switch. Все эти значения должны быть уникальными литералами. Если же вы укажете в двух операторах case одинаковые значения, транслятор выдаст сообщение об ошибке.
    Если же значению выражения не соответствует ни один из операторов case, управление передается коду, расположенному после ключевого слова default. Отметим, что оператор default необязателен. В случае, когда ни один из операторов case не соответствует значению выражения и в switch отсутствует оператор default выполнение программы продолжается с оператора, следующего за оператором switch.
    Внутри оператора switch (а также внутри циклических конструкций, но об этом - позже) break без метки приводит к передаче управления на код, стоящий после оператора switch. Если break отсутствует, после текущего раздела case будет выполняться следующий. Иногда бывает удобно иметь в операторе switch несколько смежных разделов case, не разделенных оператором break. class SwitchSeason { public static void main(String args[]) { int month = 4; String season; switch (month) { case 12: // FALLSTHROUGH case 1: // FALLSTHROUGH case 2: season = "Winter"; break; case 3: // FALLSTHROUGH case 4: // FALLSTHROUGH case 5: season = "Spring"; break; case 6: // FALLSTHROUGH case 7: // FALLSTHROUGH case 8: season = "Summer"; break; case 9: // FALLSTHROUGH case 10: // FALLSTHROUGH case 11: season = "Autumn"; break; default: season = "Bogus Month"; } System.out.println("April is in the " + season + "."); } }
    Ниже приведен еще более полезный пример, где оператор switch используется для передачи управления в соответствии с различными кодами символов во входной строке. Программа подсчитывает число строк, слов и символов в текстовой строке. class WordCount { static String text = "Now is the tifne\n" + "for all good men\n" + "to come to the aid\n" + "of their country\n"+ "and pay their due taxes\n"; static int len = text.length(); public static void main(String args[]) { boolean inWord = false; int numChars = 0; int numWords = 0; int numLines = 0; for (int i=0; i < len; i++) { char с = text.charAt(i); numChars++; switch (с) { case '\n': numLines++; // FALLSTHROUGH case '\t': // FALLSTHROUGH case ' ' : if (inWord) { numWords++; inWord = false; } break; default: inWord = true; } } System.out.println("\t" + numLines +"\t" + numWords + "\t" + numChars); } }
    В этой программе для подсчета слов использовано несколько концепций, относящихся к обработке строк. Подробно эти вопросы будут рассмотрены в главе 9.


    System



    System

    Класс System содержит любопытную коллекцию глобальных функций и переменных. В большинстве примеров этой книге для операций вывода мы использовали метод System.out.println(). В следующей главе будут детально рассмотрены потоки InputStream и OutputStream.
    Метод currentTimeMillis возвращает текущее системное время в виде миллисекунд, прошедших с 1 января 1970 года.
    Метод arraycopy можно использовать для быстрого копирования массива любого типа из одного места в памяти в другое. Ниже приведен пример копирования двух массивов с помощью этого метода. class ACDemo { static byte a[] = { 65, 66, 67, 68, 69, 70, 71, 72, 73, 74 }; static byte b[] = { 77, 77, 77, 77, 77, 77, 77, 77, 77, 77 }; public static void main( String args[]) { System.out.println("a = " + new String(a, 0)); System.out.println("b = " + new String(b, 0)); System.arraycopy(a, 0, b, 0, a.length); System.out.println("a = " + new String(a, 0)); System.out.println("b = " + new String(b, 0)); System.arraycopy(a, 0, a, 1, a.length - 1); System.arraycopy(b, 1, b, 0, b.length - 1); System.out.println("a = " + new String(a, 0)); System.out.println("b = " + new String(b, 0)); } }
    Как вы можете заключить из результата работы этой программы, копирование можно выполнять в любом направлении, используя в качестве источника и приемника один и тот же объект. С:\> java ACDemo а = ABCDEFGHIJ b = ММММММММММ а = ABCDEFGHIJ b = ABCDEFGHIJ а = AABCDEFGHI b = BCDEFGHIJJ


    Пакеты Java API



    Таблица 1 - Пакеты Java API

    Имя пакетаСодержимое
    java.appletКлассы для реализации апплетов
    java.awtКлассы для работы с графикой, текстом, окнами и GUI
    java.awt.datatransferКлассы для обеспечения передачи информации (Copy/Paste)
    java.awt.eventКлассы и интерфейсы для обработки событий
    java.awt.imageКлассы для обработки изображений
    java.awt.peerGUI для обеспечения независимости от платформы
    java.beansAPI для модели компонентов JavaBeans
    java.ioКлассы для различных типов ввода-вывода
    java.langКлассы ядра языка (типы, работа со строками, тригонометрические функции, обработка исключений, легковесные процессы)
    java.lang.reflectКлассы Reflection API
    java.mathКлассы для арифметических операций произвольной точности
    java.netКлассы для работы в сети Интернет (сокеты, протоколы, URL)
    java.rmiКлассы, связанные с RMI (удаленный вызов процедур)
    java.rmi.dgcКлассы, связанные с RMI
    java.rmi.registryКлассы, связанные с RMI
    java.rmi.serverКлассы, связанные с RMI
    java.securityКлассы для обеспечения безопасности
    java.security.aclКлассы для обеспечения безопасности
    java.security.interfacesКлассы для обеспечения безопасности
    java.sql
    java.textКлассы для обеспечения многоязыковой поддержки
    java.text.resourcesКлассы для обеспечения многоязыковой поддержки
    java.utilРазноообразные полезные типы данных (стеки, сдовари, хэш-таблицы, даты, генератор случайных чисел)
    java.util.zipКлассы для обеспечения архивации
    Часть этих пакетов мы будем рассматривать очень подробно (это видно из оглавления), другая пойдет на самостоятельную проработку.


    Зарезервированные слова Java



    Таблица 2 - Зарезервированные слова Java

    abstractbooleanbreakbytebyvalue
    casecastcatchcharclass
    constcontinuedefaultdodouble
    elseextendsfalse final finally
    floatforfuturegenericgoto
    ifimplementsimportinnerinstanceof
    intinterfacelongnativenew
    nulloperatorouterpackageprivate
    protectedpublicrestreturnshort
    staticsuperswitchsyncronizedthis
    throwthrowstransienttruetry
    varvoidvolatilewhile
    Отметим, что слова byvalue, cast, const, future, generic, goto, inner, operator, outer, rest, var зарезервированы в Java, но пока не используются Кроме этого, в Java есть зарезервированные имена методов (эти методы наследуются каждым классом, их нельзя использовать, за исключением случаев явного переопределения методов класса Object).


    Зарезервированные имена методов Java



    Таблица 3.1 - Зарезервированные имена методов Java

    cloneequalsfinalizegetClasshashCode
    notifynotifyAlltoStringwait


    Управляющие последовательности символов



    Таблица 3.2 - Управляющие последовательности символов

    Управляющая последовательностьОписание
    \dddВосьмеричный символ (ddd)
    \uxxxxШестнадцатиричный символ UNICODE (xxxx)
    \'Апостроф
    \"Кавычка
    \\Обратная косая черта
    \rВозврат каретки (carriage return)
    \nПеревод строки (line feed, new line)
    \fПеревод страницы (form feed)
    \tГоризонтальная табуляция (tab)
    \bВозврат на шаг (backspace)


    Операторы языка Java



    Таблица 3.3 - Операторы языка Java

    ++=--=
    **=//=
    ||=^^=
    &&=%%=
    >>=<<=
    !!=++--
    >>>>=<<<<=
    >>>>>>=&&| |
    ===~?:
    instanceof[ ]


    Элементы AWT и события Java 1.0, которые порождаются ими



    Таблица 5. Элементы AWT и события Java 1.0, которые порождаются ими

    ЭлементТип события (id)w
    h
    e
    r
    e
    xyk
    e
    y
    m
    o
    d
    s
    Смысл событияТип и значение переменной arg
    ButtonACTION_EVENT Пользователь нажал кнопкуString: обозначение кнопки
    CheckboxACTION_EVENT Пользователь активизировал флажокBoolean: новое состояние флажка
    Choice (список выбора)ACTION_EVENT Пользователь выбрал элемент спискаString: обозначение выбранного элемента
    Element (элемент)GOT_FOCUS Получение фокуса вводане используется
    Element (элемент)KEY_ACTION*****Пользователь нажал функциональную клавишуне используется, поскольку key содержит константу клавиши
    Element (элемент)KEY_ACTION_ RELEASE*****Пользователь отпустил функциональную клавишуне используется, поскольку key содержит константу клавиши
    Element (элемент)KEY_PRESS*****Пользователь нажал клавишуне используется, поскольку key содержит ASCII-код клавиши
    Element (элемент)KEY_RELEASE*****Пользователь отпустил клавишуне используется, поскольку key содержит ASCII-код клавиши
    Element (элемент)LOST_FOCUS Потеря фокуса вводане используется
    Element (элемент)MOUSE_ENTER>*** Курсор мыши попал в область объекта класса Componentне используется
    Element (элемент)MOUSE_EXIT*** Курсор мыши вышел из области объекта класса Componentне используется
    Element (элемент)MOUSE_DOWN*** *Пользователь нажал кнопку мышине используется
    Element (элемент)MOUSE_UP*** *Пользователь отпустил кнопку мышине используется
    Element (элемент)MOUSE_MOVE*** *Пользователь переместил мышьне используется
    Element (элемент)MOUSE_DRAG*** *Пользователь переместил мышь при нажатой кнопке мышине используется
    List (список)ACTION_EVENT Пользователь выполнил двойной щелчок мыши на элементе спискаString: обозначение выбранного элемента
    List (список)LIST_SELECT Пользователь выбрал элемент спискаInteger: индекс выбранного элемента
    List (список)LIST_DESELECT Пользователь убрал выделение с определенного элементаInteger: индекс элемента
    Menu Item (меню)ACTION_EVENT Пользователь выбрал пункт менюString: обозначение выбранного пункта
    Scrollbar (полоса прокрутки)SCROLL_LINE_UP Пользователь осуществил прокрутку вверх на строкуInteger: позиция, до которой осуществляется прокрутка
    Scrollbar (полоса прокрутки)SCROLL_LINE_DOWN Пользователь осуществил прокрутку вниз на строкуInteger: позиция, до которой осуществляется прокрутка
    Scrollbar (полоса прокрутки)SCROLL_PAGE_UP Пользователь осуществил прокрутку вверх на страницуInteger: позиция, до которой осуществляется прокрутка
    Scrollbar (полоса прокрутки)SCROLL_PAGE_DOWN Пользователь осуществил прокрутку вниз на страницуInteger: позиция, до которой осуществляется прокрутка
    Scrollbar (полоса прокрутки)SCROLL_ABSOLUTE Пользователь переместил ползунок полосы прокруткиInteger: позиция, до которой осуществляется прокрутка
    Text Field (текст)ACTION_EVENT Пользователь ввел текст и нажал [Enter].String: введенный текст
    Window (окно)WINDOW_DESTROY Окно закрытоне используется
    Window (окно)WINDOW_ICONIFY Окно представлено в виде пиктограммыне используется
    Window (окно)WINDOW_DEICONIFY Окно восстановленоне используется
    Window (окно)WINDOW_MOVED ** Окно перемещеноне используется


    Таблица 6. Типы событий, слушатели



    Таблица 6. Типы событий, слушатели и методы слушателей в Java 1.1

    Класс событияИнтерфейс слушателяМетоды слушателя
    ActionEventActionListeneractionPerformed()
    AdjustmentEventAdjustmentListeneradjustmentValueChanged()
    ComponentEventComponentListenercomponentHidden()
    componentMoved()
    componentResized()
    componentShown()
    ContainerEventContainerListenercomponentAdded()
    componentRemoved()
    FocusEventFocusListenerfocusGained()
    focusLost()
    ItemEventItemListeneritemStateChanged()
    KeyEventKeyListenerkeyPressed()
    keyReleased()
    keyTyped()
    MouseEventMouseListenermouseClicked()
    mouseEntered()
    mouseExited()
    mousePressed()
    mouseReleased()
    MouseMotionListenermouseDragged()
    mouseMoved()
    TextEventTextListenertextValueChanged()
    WindowEventWindowListenerwindowActivated()
    windowClosed()
    windowClosing()
    windowDeactivated()
    windowDeiconified()
    windowlconified()
    windowOpened()
    Для каждого интерфейса слушателей событий, содержащего несколько методов, в пакете java.awt.event определен простой класс-адаптер, который обеспечивает пустое тело для каждого из методов соответствующего интерфейса. Когда нужен только один или два таких метода, иногда проще получить подкласс класса-адаптера, чем реализовать интерфейс самостоятельно. При получении подкласса адаптера требуется лишь переопределить те методы, которые нужны, а при прямой реализации интерфейса необходимо определить все методы, в том числе и ненужные в данной программе. Заранее определенные классы-адаптеры называются так же, как и интерфейсы, которые они реализуют, но в этих названиях Listener заменяется на Adapter: MouseAdapter, WindowAdapter и т.д.

    Как только реализован интерфейс слушателя или получены подклассы класса-адаптера, необходимо создать экземпляр нового класса, чтобы определить конкретный объект слушателя событий. Затем этот слушатель должен быть зарегистрирован соответствующим источником событий. В программах пакета AWT источником событий всегда является какой-нибудь элемент пакета. В методах регистрации слушателей событий используются стандартные соглашения об именах: если источник событий порождает события типа X, в нем существует метод addXListener () для добавления слушателя и метод removeXListener() для его удаления. Одной из приятных особенностей модели обработки событий Java 1.1 является возможность легко определять типы событий, которые могут порождаться данным элементом. Для этого следует просто просмотреть, какие методы зарегистрированы для его слушателя событий. Например, из описания API для объекта класса Button следует, что он порождает события ActionEvent. В таблице 7 приведен список элементов пакета AWT и событий, которые они порождают.


    Таблица 7. Элементы пакета AWT



    Таблица 7. Элементы пакета AWT и порождаемые ими события в Java1.1

    ЭлементПорождаемое событиеЗначение
    ButtonActionEventПользователь нажал кнопку
    CheckBoxItemEventПользователь установил или сбросил флажок
    CheckBoxMenuItemItemEventПользователь установил или сбросил флажок рядом с пунктом меню
    ChoiceItemEventПользователь выбрал элемент списка или отменил его выбор
    ComponentComponentEventЭлемент либо перемещен, либо он стал скрытым,либо видимым
    FocusEventЭлемент получил или потерял фокус ввода
    KeyEventПользователь нажал или отпустил клавишу
    MouseEventПользователь нажал или отпустил кнопку мыши, либо курсор мыши вошел или покинул область, занимаемую элементом, либо пользователь просто переместил мышь или переместил мышь при нажатой кнопке мыши
    ContainerContainerEventЭлемент добавлен в контейнер или удален из него
    ListActionEventПользователь выполнил двойной щелчок мыши на элементе списка
    ItemEventПользователь выбрал элемент списка или отменил выбор
    MenuItemActionEventПользователь выбрал пункт меню
    ScrollbarAdjustmentEventПользователь осуществил прокрутку
    TextComponentTextEventПользователь внес изменения в текст элемента
    TextFieldActionEventПользователь закончил редактирование текста элемента
    WindowWindowEventОкно было открыто, закрыто, представлено в виде пиктограммы, восстановлено или требует восстановления


    Тег HTML

    Тег HTML

    Тег <applet> используется для запуска апплета как из HTML-документа, так и из программы appletviewer. Программа appletviewer выполняет каждый найденный ей тег в отдельном окне, в то время как браузеры позволяют разместить на одной странице несколько апплетов. Синтаксис тэга в настоящее время таков : [< PARAM NAME = AttributeNamel VALUE = AttributeValuel >] [< PARAM NAME = AttributeName2 VALUE = AttributeValue2 >] [HTML-текст, отображаемый при отсутствии поддержки Java]


    Тернарный оператор if-then-else



    Тернарный оператор if-then-else

    Общая форма оператора if-then-use такова: выражение1? выражение2: выражениеЗ
    В качестве первого операнда - - может быть исполь-зовано любое выражение, результатом которого является значение типа boolean. Если результат равен true, то выполняется оператор, заданный вторым операндом, то есть, . Если же первый операнд paвен false, то выполняется третий операнд - . Второй и третий операнды, то есть и , должны воз-вращать значения одного типа и не должны иметь тип void.
    В приведенной ниже программе этот оператор используется для про-верки делителя перед выполнением операции деления. В случае нулевого делителя возвращается значение 0. class Ternary { public static void main(String args[]) { int a = 42; int b = 2; int c = 99; int d = 0; int e = (b == 0) ? 0 : (a / b); int f = (d == 0) ? 0 : (c / d); System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("c = " + c); System.out.println("d = " + d); System.out.println("a / b = " + e); System.out.println("c / d = " + f); } }
    При выполнении этой программы исключительной ситуации деления на нуль не возникает и выводятся следующие результаты: С: \>java Ternary а = 42 b = 2 с = 99 d = 0 a / b = 21 с / d = 0


    TextArea



    TextArea

    Порой одной строки текста оказывается недостаточно для конкретной задачи. AWT включает в себя очень простой многострочный редактор обычного текста, называемый TextArea. Конструктор класса TextArea воспринимает значение типа String в качестве начального текста объекта. Кроме того, в конструкторе указывается число колонок и строк текста, которые нужно выводить. Есть три метода, которые позволяют программе модифицировать содержимое объекта TextArea: appendText добавляет параметр типа String в конец буфера; insertText вставляет строку в заданное отсчитываемым от нуля индексом место в буфере; rеplaceText копирует строку-параметр в буфер, замещая ею текст, хранящийся в буфере между первым и вторым параметрами-смещениями. Ниже приведена программа, создающая объект TextArea и вставляющая в него строку. /* */ import java.awt.*; import java.applet.*; public class TextAreaDemo extends Applet { public void init() { setLayout(null); int width = Integer.parseInt(getParameter("width")); int height = Integer.parseInt(getParameter("height")); String val = "There are two ways of constructing " + "a software design.\n" + "One way is to make it so simple\n" + "that there are obviously no deficiencies.\n" + "And the other way is to make it so complicated\n" + "that there are no obvious deficiencies.\n\n" + "C.A.R. Hoare\n\n" + "There's an old story about the person who wished\n" + "his computer were as easy to use as his telephone. \n" + "That wish has come true,\n" + "since I no longer know how to use my telephone. \n\n" + "Bjarne Stroustrup, AT&T (inventor of C++)"; TextArea text = new TextArea(val, 80, 40); add(text); text.setBounds(0, 0, width, height); } }


    TextField



    TextField

    Класс TextField представляет собой реализацию однострочной области для ввода текста. Такие области часто используются в формах для пользовательского ввода. Вы можете "заморозить" содержимое объекта TextField с помощью метода setEditable, а метод isEditable сообщит вам, можно ли редактировать текст в данном объекте. Текущее значение объекта можно получить методом getText и установить методом setText. С помощью метода select можно выбрать фрагмент строки, задавая его начало и конец, отсчитываемые с нуля. Для выбора всей строки используется метод selectAll.
    Метод setEchoChar задает символ, который будет выводиться вместо любых вводимых символов. Вы можете проверить, находится ли объект TextField в этом режиме, с помощью метода echoCharIsSet, и узнать, какой именно символ задан для эхо-печати, с помощью метода getEchoChar. Вот пример, в котором создаются классические поля для имени пользователя и пароля. /* */ import java.awt.*; import java.applet.*; public class TextFieldDemo extends Applet { public void init() { setLayout(null); int width = Integer.parseInt(getParameter("width")); int height = Integer.parseInt(getParameter("height")); Label namep = new Label("Name : ", Label.RIGHT); Label passp = new Label("Password : ", Label.RIGHT); TextField name = new Text Field(8); TextField pass = new TextField(8); pass.setEchoChar('*'); add(namep); add(name); add(passp); add(pass); int space = 25; int w1 = width / 3; namep.setBounds(0, (height - space) / 2, w1, space); name.setBounds(w1, (height - space) / 2, w1, space); passp.setBounds(0, (height + space) / 2, w1, space); pass.setBounds(w1, (height + space) / 2, w1, space); } }
    Обратите внимание, что в этом примере мы заменили устаревший в JDK 1.1 reshape на setBounds - TextFieldDemo.html. Вообще, в примерах могут встречаться вызовы Deprecated API, за что автор приносит извинения (после выхода Java 1.2, возможно, некоторые устаревшие функции будут действительно удалены, и тогда все примеры будут пересмотрены).


    This в конструкторах



    this в конструкторах

    Очередной вариант класса Point показывает, как, используя this и совмещение методов, можно строить одни конструкторы на основе других. class Point { int х, у; Point(int х, int у) { this.x = х; this.у = у; } Point() { this(-1, -1); } }
    В этом примере второй конструктор для завершения инициализации объекта обращается к первому конструктору.
    Методы, использующие совмещение имен, не обязательно должны быть конструкторами. В следующем примере в класс Point добавлены два метода distance. Функция distance возвращает расстояние между двумя точками. Одному из совмещенных методов в качестве параметров передаются координаты точки х и у, другому же эта информация передается в виде параметра-объекта Point. class Point { int х, у; Point(int х, int у) { this.x = х; this. y = y; } double distance(int х, int у) { int dx = this.x - х; int dy = this.у - у; return Math.sqrt(dx*dx + dy*dy); } double distance(Point p) { return distance(p.x, p.y); } } class PointDist { public static void main(String args[]) { Point p1 = new Point(0, 0); Point p2 = new Point(30, 40); System.out.println("p1 = " + pi.x + ", " + p1.y); System.out.println("p2 = " + p2.x + ", " + p2.y); System.out.println("p1.distance(p2) = " + p1.distance(p2)); System.out.println("p1.distance(60, 80) = " + p1.distance(60, 80)); } }
    Обратите внимание на то как во второй фороме метода distance для получения результата вызывается его первая форма. Ниже приведен результат работы этой программы: С:\> java PointDist р1 = 0, 0 р2 = 30, 40 р1.distance(p2) = 50.0 p1.distance(60, 80) = 100.0


    Throw ОбъектТипаThrowable;



    throw ОбъектТипаThrowable;

    При достижении этого оператора нормальное выполнение кода немед-ленно прекращается, так что следующий за ним оператор не выполня-ется. Ближайший окружающий блок try проверяется на наличие соот-ветствующего возбужденному исключению обработчика catch. Если такой отыщется, управление передается ему. Если нет, проверяется следующий из вложенных операторов try, и так до тех пор пока либо не будет най-ден подходящий раздел catch, либо обработчик исключений исполняю-щей системы Java не остановит программу, выведя при этом состояние стека вызовов. Ниже приведен пример, в котором сначала создается объект-исключение, затем оператор throw возбуждает исключительную ситуацию, после чего то же исключение возбуждается повторно - на этот раз уже кодом перехватившего его в первый раз раздела catch. class ThrowDemo { static void demoproc() { try { throw new NullPointerException("demo"); } catch (NullPointerException e) { System.out.println("caught inside demoproc"); throw e; } } public static void main(String args[]) { try { demoproc(); } catch(NulPointerException e) { System.out.println("recaught: " + e); } } }
    В этом примере обработка исключения проводится в два приема. Метод main создает контекст для исключения и вызывает demoproc. Метод demoproc также устанавливает контекст для обработки исключе-ния, создает новый объект класса NullPointerException и с помощью опе-ратора throw возбуждает это исключение. Исключение перехватывается в следующей строке внутри метода demoproc, причем объект-исключение доступен коду обработчика через параметр e. Код обработчика выводит сообщение о том, что возбуждено исключение, а затем снова возбуждает его с помощью оператора throw, в результате чего оно передается обра-ботчику исключений в методе main. Ниже приведен результат, получен-ный при запуске этого примера. С:\> java ThrowDemo caught inside demoproc recaught: java.lang.NullPointerException: demo


    Throw



    throw

    Оператор throw используется для возбуждения исключения . Для того, чтобы сделать это, нужно иметь объект подкласса клас-са Throwable, который можно либо получить как параметр оператора catch, либо создать с помощью оператора new. Ниже приведена общая форма оператора throw.


    Throws



    throws

    Если метод способен возбуждать исключения, которые он сам не об-рабатывает, он должен объявить о таком поведении, чтобы вызывающие методы могли защитить себя от этих исключений. Для задания списка исключений, которые могут возбуждаться методом, используется ключе-вое слово throws. Если метод в явном виде (т.е. с помощью оператора throw) возбуждает исключе-ние соответствующего класса, тип класса исключений должен быть ука-зан в операторе throws в объявлении этого метода. С учетом этого наш прежний синтаксис определения метода должен быть расширен следую-щим образом: тип имя_метода(список аргументов) throws список_исключений {}
    Ниже приведен пример программы, в которой метод procedure пыта-ется возбудить исключение, не обеспечивая ни программного кода для его перехвата, ни объявления этого исключения в заголовке метода. Такой программный код не будет оттранслирован. class ThrowsDemo1 { static void procedure() { System.out.println("inside procedure"); throw new IllegalAccessException("demo"); } public static void main(String args[]) { procedure(); } }
    Для того, чтобы мы смогли оттранслировать этот пример, нам при-дется сообщить транслятору, что procedure может возбуждать исключе-ния типа IllegalAccessException и в методе main добавить код для обработки этого типа исключений : class ThrowsDemo { static void procedure() throws IllegalAccessException { System.out.println(" inside procedure"); throw new IllegalAccessException("demo"); } public static void main(String args[]) { try { procedure(); } catch (IllegalAccessException e) { System.out.println("caught " + e); } } }
    Ниже приведен результат выполнения этой программы. С:\> java ThrowsDemo inside procedure caught java.lang.IllegalAccessException: demo


    Тип boolean



    Тип boolean

    В языке Java имеется простой тип boolean, используемый для хранения логических значений. Переменные этого типа могут принимать всего два значения - true (истина) и false (ложь). Значения типа boolean возвращаются в качестве результата всеми операторами сравнения, например (а < b) - об этом разговор пойдет в следующей главе. Кроме того, в главе 6 вы узнаете, что boolean - это тип, требуемый всеми условными операторами управления - такими, как if, while, do. boolean done = false;
    Завершая разговор о простых типах...
    Теперь, когда мы познакомились со всеми простыми типами, включая целые и вещественные числа, символы и логические переменные, давайте попробуем собрать всю информацию вместе. В приведенном ниже примере создаются переменные каждого из простых типов и выводятся значения этих переменных. class SimpleTypes { public static void main(String args []) { byte b = 0х55; short s = 0x55ff; int i = 1000000; long l = 0xffffffffL; char с = ' a' ; float f = .25f; double d = .00001234; boolean bool = true; System.out.println("byte b = " + b); System.out.println("short s = " +s); System.out.println("int i = " + i); System.out.println("long l = " + l); System.out.println("char с = " + с); System.out.println("float f = " + f); System.out.println("double d = " + d); System.out.println("boolean bool = " + bool); } }
    Запустив эту программу, вы должны получить результат, показанный ниже: С: \> java SimpleTypes byte b = 85 short s = 22015 int i = 1000000 long l = 4294967295 char с = а float f = 0.25 double d = 1.234e-005 boolean bool = true
    Обратите внимание на то, что целые числа печатаются в десятичном представлении, хотя мы задавали значения некоторых из них в шестнадцатиричном формате. В главе 12 вы узнаете, как можно форматировать выводимые числовые значения.


    Типы исключений



    Типы исключений

    В вершине иерархии исключений стоит класс Throwable. Каждый из типов исключений является подклассом класса Throwable. Два непосредственных наследника класса Throwable делят иерархию подклассов исключений на две различные ветви. Один из них - класс Ехception - используется для описания исключительных ситуации, кото-рые должны перехватываться программным кодом пользователя. Другая ветвь дерева подклассов Throwable - класс Error, который предназначен для описания исклю-чительных ситуаций, которые при обычных условиях не должны перехватываться в пользовательской программе.


    ToLowerCase и toUpperCase



    toLowerCase и toUpperCase

    Эта пара методов преобразует все символы исходной строки в нижний и верхний регистр, соответственно. "Hello".toLowerCase() -> "hello" "Hello".toUpperCase() -> "HELLO"


    Трансляция классов в пакетах



    Трансляция классов в пакетах

    При попытке поместить класс в пакет, вы сразу натолкнетесь на жесткое требование точного совпадения иерархии каталогов с иерархией пакетов. Вы не можете переименовать пакет, не переименовав каталог, в котором хранятся его классы. Эта трудность видна сразу, но есть и менее очевидная проблема.
    Представьте себе, что вы написали класс с именем PackTest в пакете test. Вы создаете каталог test, помещаете в этот каталог файл PackTest.Java и транслируете. Пока - все в порядке. Однако при попытке запустить его вы получаете от интерпретатора сообщение (). Ваш новый класс теперь хранится в пакете с именем test, так что теперь надо указывать всю иерархию пакетов, разделяя их имена точками - test.PackTest. Кроме того Вам надо либо подняться на уровень выше в иерархии каталогов и снова набрать , либо внести в переменную CLASSPATH каталог, который является вершиной иерархии разрабатываемых вами классов.


    Тригонометрические функции



    Тригонометрические функции

    Приведенные ниже три функции имеют один параметр типа double, представляющий собой угол в радианах, и возвращают значение соответствующей тригонометрической функции.
  • sin(double а) возвращает синус угла а, заданного в радианах.
  • cos(double а) возвращает косинус угла а, заданного в радианах.
  • tan(double а) возвращает тангенс угла а, заданного в радианах.

  • Следующие четыре функции возвращают угол в радианах, соответствующий значению, переданному им в качестве параметра.
  • asin(double r) возвращает угол, синус которого равен г.
  • acos(double r) возвращает угол, косинус которого равен г.
  • atan(double r) возвращает угол, тангенс которого равен г.
  • atan2(double a, double b) возвращает угол, тангенс которого равен отношению а/b.



  • Trim



    trim

    И, наконец, метод trim убирает из исходной строки все ведущие и замыкающие пробелы. "Hello World ".trim() -> "Hello World"


    Try и catch



    try и catch

    Для задания блока программного кода, который требуется защитить от исключений, исполь-зуется ключевое слово try. Сразу же после try-блока помещается блок catch, задающий тип исключения которое вы хотите обрабатывать. class Exc2 { public static void main(String args[]) { try { int d = 0; int a = 42 / d; } catch (ArithmeticException e) { System.out.println("division by zero"); } } }
    Целью большинства хорошо сконструированных catch-разделов долж-на быть обработка возникшей исключительной ситуации и приведение переменных программы в некоторое разумное состояние - такое, чтобы программу можно было продолжить так, будто никакой ошибки и не было (в нашем примере выводится предупреждение - division by zero).


    Удаленный вызов методов



    Удаленный вызов методов

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


    Указатели



    Указатели

    Указатели или адреса в памяти - наиболее мощная и наиболее опасная черта C++. Причиной большинства ошибок в сегодняшнем коде является именно неправильная работа с указателями. Например, одна из типичных ошибок - просчитаться на единицу в размере массива и испортить содержимое ячейки памяти, расположенной вслед за ним.
    Хотя в Java дескрипторы объектов и реализованы в виде указателей, в ней отсутствуют возможности работать непосредственно с указателями. Вы не можете преобразовать целое число в указатель, а также обратиться к произвольному адресу памяти.


    Update



    update

    Используемый по умолчанию метод update класса Applet сначала закрашивает апплет цветом фона по умолчанию, после чего вызывает метод paint. Если вы в методе paint заполняете фон другим цветом, пользователь будет видеть вспышку цвета по умолчанию при каждом вызове метода update - то есть, всякий раз, когда вы перерисовываете апплет. Чтобы избежать этого, нужно заместить метод update. В общем случае нужно выполнять операции рисования в методе update, а в методе paint, к которому будет обращаться AWT, просто вызвать update.


    URL(String spec)



    URL(String spec)

    Две следующих разновидности конструкторов позволяют задать URL, указав его отдельные компоненты:
    URL(String protocol, String host, int port, String file)
    URL(String protocol, String host, String file)
    Четвертая, и последняя форма конструктора позволяет использовать существующий URL в качестве ссылочного контекста, и создать на основе этого контекста новый URL.


    URL(URL context, String spec)



    URL(URL context, String spec)

    В приведенном ниже примере создается URL, адресующий www-страницу (поставьте туда свой адрес), после чего программа печатает свойства этого объекта. import java.net.URL; class myURL { public static void main(String args[]) throws Exception { URL hp = new URL("http://coop.chuvashia.edu"); System.out. println("Protocol: " + hp.getProtocol()); System.out.printin("Port: " + hp.getPort()); System.out.println("Host: " + hp.getHost()); System.out.println("File: " + hp.getFile()); System.out.println("Ext: " + hp.toExternaLForm()); } }
    Для того, чтобы извлечь реальную информацию, адресуемую данным URL, необходимо на основе URL создать объект URLConnection, воспользовавшись для этого методом openConnection().


    URL



    URL

    URL (Uniform Resource Locators - однородные указатели ресурсов) - являются наиболее фундаментальным компонентом "Всемирной паутины". Класс URL предоставляет простой и лаконичный программный интерфейс для доступа к информации в Internet с помощью URL.
    У класса URL из библиотеки Java - четыре конструктора. В наиболее часто используемой форме конструктора URL адрес ресурса задается в строке, идентичной той, которую вы используете при работе с браузером:


    URLConnection



    URLConnection

    URLConnection - объект, который мы используем либо для проверки свойств удаленного ресурса, адресуемого URL, либо для получения его содержимого. В приведенном ниже примере мы создаем URLConnection с помощью метода openConnection, вызванного с объектом URL. После этого мы используем import java.net.*; import java.io.*; class localURL { public static void main(String args[]) throws Exception { int c; URL hp = new URL("http", "127.0.0.1", 80, "/"); URLConnection hpCon = hp.openConnection(); System.out.println("Date: " + hpCon.getDate()); System.out.println("Type: " + hpCon.getContentType()); System.out.println("Exp: " + hpCon.getExpiration()); System.out.println( "Last M: " + hpCon.getLastModified()); System.out.println("Length: " + hpCon.getContentLength()); if (hpCon.getContentLength() > 0) { System.out.println("=== Content ==="); InputStream input = hpCon.getInputStream(); int i=hpCon.getContentLength(); while (((c = input. read()) != -1) && (--i > 0)) { System.out.print((char) c); } input.close(); } else { System.out.println("No Content Available"); } } }
    Эта программа устанавливает HTTP-соединение с локальным узлом по порту 80 (у вас на машине должен быть и установлен Web-сервер) запрашивает документ по умолчанию, обычно это - index.html. После этого программа выводит значения заголовка, запрашивает и выводит содержимое документа.


    Условные операторы



    Условные операторы

    Они хорошо Вам знакомы, давайте познакомимся с каждым из них в Java. if-else
    В обобщенной форме этот оператор записывается следующим образом: if (логическое выражение) оператор1; [ else оператор2;]
    Раздел else необязателен. На месте любого из операторов может стоять составной оператор, заключенный в фигурные скобки. Логическое выражение - это любое выражение, возвращающее значение типа boolean. int bytesAvailable; // ... if (bytesAvailable > 0) { ProcessData(); bytesAvailable -= n; } else waitForMoreData();
    А вот полная программа, в которой для определения, к какому времени года относится тот или иной месяц, используются операторы if-else. class IfElse { public static void main(String args[]) { int month = 4; String season; if (month == 12 || month == 1 || month == 2) { season = "Winter"; } else if (month ==3 || month == 4 || month == 5) { season = "Spring"; } else if (month == 6 || month == 7 || month == 8) { season = "Summer"; } else if (month == 9 || month == 10 || month == 11) { season = "Autumn"; } else {season = "Bogus Month";} System.out.println( "April is in the " + season + "."); } }
    После выполнения программы вы должны получить следующий результат: С: \> java IfElse April is in the Spring.


    ValueOf



    valueOf

    Если вы имеете дело с каким-либо типом данных и хотите вывести значение этого типа в удобочитаемом виде, сначала придется преобразо-вать это значение в текстовую строку. Для этого существует метод val-ueOf. Такой статический метод определен для любого существующего в Java типа данных (все эти методы совмещены, то есть используют одно и то же имя). Благодаря этому не составляет труда преобразовать в стро-ку значение любого типа.


    Ваш первый шаг



    Ваш первый шаг

    Мы уже многого достигли: сначала написали небольшую программу на языке Java и подробно рассмотрели, из чего она состоит (блоки кода, комментарии). Мы познакомились со списком ключевых слов и операторов, чье назначение будет подробно объяснено в дальнейших главах. Теперь вы в состоянии самостоятельно различать основные части любой Java-программы и готовы к тому, чтобы приступить к чтению главы 4, в которой подробно рассматриваются простые типы данных.


    Вложенные операторы try



    Вложенные операторы try

    Операторы try можно вкладывать друг в друга аналогично тому, как можно создавать вложенные области видимости переменных. Если у оператора try низкого уровня нет раздела catch, соответствующего возбужденному исключению, стек будет развернут на одну ступень выше, и в поисках подходящего обработчика будут прове-рены разделы catch внешнего оператора try. Вот пример, в котором два оператора try вложены друг в друга посредством вызова метода. class MultiNest { static void procedure() { try { int c[] = { 1 }; c[42] = 99; } catch(ArrayIndexOutOfBoundsException e) { System.out.println("array index oob: " + e); } } public static void main(String args[]) { try { int a = args.length(); System.out.println("a = " + a); int b = 42 / a; procedure(); } catch (ArithmeticException e) { System.out.println("div by 0: " + e); } } }


    Вы можете использовать оператор break



    Внимание

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

    очевидно ожидают, что сейчас мы



    Внимание

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

    и StringBuffer объявлены final, что



    Внимание

    И String, и StringBuffer объявлены final, что означает, что ни от одного из этих классов нельзя производить подклассы. Это было сделано для того, чтобы можно было применить некоторые виды оптимизации по-зволяющие увеличить производительность при выполнении операций обработки строк.

    запустить сборщик мусора, вызвав метод



    ВНИМАНИЕ!

    При необходимости вы можете "вручную" запустить сборщик мусора, вызвав метод gc. Если вы хотите оценить, сколько памяти требуется для работы вашему коду, лучше всего сначала вызвать gc, затем free-Memory, получив тем самым оценку свободной памяти, доступной в системе. Запустив после этого свою программу и вызвав freeMemory внутри нее, вы увидите, сколько памяти использует ваша программа.

    Вниз по течению



    Вниз по течению

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


    Void



    void

    У вас нередко будет возникать потребность в методах, которые возвращают значение того или иного типа: например, int для целых значений, float - для вещественных или имя класса для типов данных, определенных программистом. В нашем случае нужно просто вывести на экран строку, а возвращать значение из метода main не требуется. Именно поэтому и был использован модификатор void. Более детально этот вопрос обсуждается в главе 4.


    VSPACE = pixels



    VSPACE = pixels

    HSPACE = PIXELS
    Эти необязательные атрибуты задают ширину свободного пространства в пикселях сверху и снизу апплета (VSPACE), и слева и справа от него (HSPACE). Они трактуются точно так же, как одноименные атрибуты тега IMG.


    Встроенные классы



    Встроенные классы

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


    Выполнение других программ



    Выполнение других программ

    В безопасных средах вы можете использовать Java для выполнения других полновесных процессов в своей многозадачной операционной системе. Несколько форм метода ехес позволяют задавать имя программы и ее параметры.
    В очередном примере используется специфичный для Windows вызов ехес, запускающий процесс notepad - простой текстовый редактор. В качестве параметра редактору передается имя одного из исходных файлов Java. Обратите внимание - ехес автоматически преобразует в строке-пути символы "/" в разделители пути в Windows - "\". class ExecDemo { public static void main(String args[]) { Runtime r = Runtime. getRuntime(); Process p = null; String cmd[] = { "notepad", "/java/src/java/lang/Runtime.java" }; try { p = r.exec(cmd); } catch (Exception e) { System.out.println("error executing " + cmd[0]); } } }


    Вызов метода



    Вызов метода

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


    Взаимодействие подпроцессов



    Взаимодействие подпроцессов

    В Java имеется элегантный механизм общения между подпроцессами, основанный на методах wait, notify и notifyAll. Эти методы реализованы, как final-методы класса Object, так что они имеются в любом Java-классе. Все эти методы должны вызываться только из синхронизованных методов. Правила использования этих методов очень просты:
  • wait - приводит к тому, что текущий подпроцесс отдает управление и переходит в режим ожидания - до тех пор пока другой под-процесс не вызовет метод notify с тем же объектом.
  • notify - выводит из состояния ожидания первый из подпроцессов, вызвавших wait с данным объектом.
  • notifyAll - выводит из состояния ожидания все подпроцессы, вызвавшие wait с данным объектом.

  • Ниже приведен пример программы с наивной реализацией проблемы поставщик-потребитель. Эта программа состоит из четырех простых классов: класса Q, представляющего собой нашу реализацию очереди, доступ к которой мы пытаемся синхронизовать; поставщика (класс Producer), выполняющегося в отдельном подпроцессе и помещающего данные в очередь; потребителя (класс Consumer), тоже представляющего собой подпроцесс и извлекающего данные из очереди; и, наконец, крохотного класса PC, который создает по одному объекту каждого из перечисленных классов. class Q { int n; synchronized int get() { System.out.println("Got: " + n); return n; } synchronized void put(int n) { this.n = n; System.out. println("Put: " + n); } } class Producer implements Runnable { Q q; Producer(Q q) { this.q = q; new Thread(this, "Producer").start(); } public void run() { int i = 0; while (true) { q.put(i++); } } } class Consumer implements Runnable { Q q; Consumer(Q q) { this.q = q; new Thread(this, "Consumer").start(); } public void run() { while (true) { q.get(); } } } class PC { public static void main(String args[]) { Q q = new Q(); new Producer(q); new Consumer(q); } }
    Хотя методы put и get класса Q синхронизованы, в нашем примере нет ничего, что бы могло помешать поставщику переписывать данные по того, как их получит потребитель, и наоборот, потребителю ничего не мешает многократно считывать одни и те же данные. Так что вывод программы содержит вовсе не ту последовательность сообщений, которую нам бы хотелось иметь: С:\> java PC Put: 1 Got: 1 Got: 1 Got: 1 Got: 1 Got: 1 Put: 2 Put: 3 Put: 4 Put: 5 Put: 6 Put: 7 Got: 7
    Как видите, после того, как поставщик помещает в переменную n значение 1, потребитель начинает работать и извлекает это значение 5 раз подряд. Положение можно исправить, если поставщик будет при занесении нового значения устанавливать флаг, например, заносить в логическую переменную значение true, после чего будет в цикле проверять ее значение до тех пор пока поставщик не обработает данные и не сбросит флаг в false.
    Правильным путем для получения того же результата в Java является использование вызовов wait и notify для передачи сигналов в обоих направлениях. Внутри метода get мы ждем (вызов wait), пока Producer не известит нас (notify), что для нас готова очередная порция данных. После того, как мы обработаем эти данные в методе get, мы извещаем объект класса Producer (снова вызов notify) о том, что он может передавать следующую порцию данных. Соответственно, внутри метода put, мы ждем (wait), пока Consumer не обработает данные, затем мы передаем новые данные и извещаем (notify) об этом объект-потребитель. Ниже приведен переписанный указанным образом класс Q. class Q { int n; boolean valueSet = false; synchronized int get() { if (!valueSet) try wait(); catch(InterruptedException e): System.out.println("Got: " + n); valueSet = false; notify(); return n; } synchronized void put(int n) { if (valueSet) try wait(); catch(InterruptedException e); this.n = n; valueSet = true; System.out.println("Put: " + n); notify(); } }
    А вот и результат работы этой программы, ясно показывающий, что синхронизация достигнута. С:\> java Pcsynch Put: 1 Got: 1 Put: 2 Got: 2 Put: 3 Got: 3 Put: 4 Got: 4 Put: 5 Got: 5


    While



    while

    Этот цикл многократно выполняется до тех пор, пока значение логического выражения равно true. Ниже приведена общая форма оператора while: [ инициализация; ] while ( завершение ) { тело; [итерация;] }
    Инициализация и итерация необязательны. Ниже приведен пример цикла while для печати десяти строк . class WhileDemo { public static void main(String args[]) { int n = 10; while (n > 0) { System.out.println("tick " + n); n--; } } }


    WIDTH = pixels



    WIDTH = pixels









    Window



    Window

    Класс Window во многом напоминает Panel за тем исключением, что он создает свое собственное окно верхнего уровня. Большая часть программистов скорее всего будет использовать не непосредственно класс Window, а его подкласс Frame.


    Yield



    yield

    Вызов метода yield приводит к тому, что исполняющая система переключает контекст с текущего на следующий доступный подпроцесс. Это один из способов гарантировать, что низкоприоритетные подпроцессы когда-нибудь получат управление. sleep(int n)
    При вызове метода sleep исполняющая система блокирует текущий подпроцесс на n миллисекунд. После того, как этот интервал времени закончится, подпроцесс снова будет способен выполняться. В большинстве исполняющих систем Java системные часы не позволяют точно выдерживать паузы короче, чем 10 миллисекунд.


    Задание размеров графических изображений.



    Задание размеров графических изображений.

    Графические изображения вычерчиваются в стандартной для компьютерной графики системе координат, в которой координаты могут принимать только целые значения, а оси направлены слева направо и сверху вниз. У апплетов и изображений есть метод size, который возвращает объект Dimension. Получив объект Dimension, вы можете получить и значения его переменных width и height: Dimension d = size(); System.out.println(d. width + "," + d.height);
    Простые методы класса Graphics
    У объектов класса Graphics есть несколько простых функций рисования. Каждую из фигур можно нарисовать заполненной, либо прорисовать только ее границы. Каждый из методов drawRect, drawOval, fillRect и fillOval вызывается с четырьмя параметрами: int x, int y, int width и int height. Координаты х и у задают положение верхнего левого угла фигуры, параметры width и height определяют ее границы.


    Замещение методов



    Замещение методов

    Новый подкласс Point3D класса Point наследует реализацию метода distance своего суперкласса (пример PointDist.java). Проблема заключается в том, что в классе Point уже определена версия метода distance(mt х, int у), которая возвращает обычное расстояние между точками на плоскости. Мы должны заместить (override) это определение метода новым, пригодным для случая трехмерного пространства. В следующем примере проиллюстрировано и совмещение (overloading), и замещение (overriding) метода distance. class Point { int х, у; Point(int х, int у) { this.x = х; this.у = у; } double distance(int х, int у) { int dx = this.x - х; int dy = this.у - у: return Math,sqrt(dx*dx + dy*dy); } double distance(Point p) { return distance(p.х, p.y); } } class Point3D extends Point { int z; Point3D(int х, int y, int z) { super(x, y); this.z = z; } double distance(int х, int y, int z) { int dx = this.x - х; int dy = this.y - y; int dz = this.z - z; return Math.sqrt(dx*dx + dy*dy + dz*dz); } double distance(Point3D other) { return distance(other.х, other.y, other.z); } double distance(int х, int y) { double dx = (this.x / z) - х; double dy = (this.у / z) - y; return Math.sqrt(dx*dx + dy*dy); } } class Point3DDist { public static void main(String args[]) { Point3D p1 = new Point3D(30, 40, 10); Point3D p2 = new Point3D(0, 0, 0); Point p = new Point(4, 6); System.out.println("p1="+p1.x+","+p1.y+","+p1.z); System.out.println("p2="+p2.x+","+p2.y+","+p2.z); System.out.println("p="+p.x+","+p.y); System.out.println("p1.distance(p2)="+p1.distance(p2)); System.out.println("p1.distance(4,6)="+ p1.distance(4,6)); System.out.println("p1.distance(p)="+p1.distance(p)); } }
    Ниже приводится результат работы этой программы: С:\> Java Point3DDist p1 = 30, 40, 10 р2 = 0, 0, 0 р = 4, 6 p1.distance(p2) = 50.9902 p1.distance(4, 6) = 2.23607 p1.distance(p) = 2.23607
    Обратите внимание - мы получили ожидаемое расстояние между трехмерными точками и между парой двумерных точек. В примере используется механизм, который называется динамическим назначением методов (dynamic method dispatch).


    Зарезервированные ключевые слова



    Зарезервированные ключевые слова

    Зарезервированные ключевые слова - это специальные идентификаторы, которые в языке Java используются для того, чтобы идентифицировать встроенные типы, модификаторы и средства управления выполнением программы. На сегодняшний день в языке Java имеется 59 зарезервированных слов (см. таблицу 2). Эти ключевые слова совместно с синтаксисом операторов и разделителей входят в описание языка Java. Они могут применяться только по назначению, их нельзя использовать в качестве идентификаторов для имен переменных, классов или методов.


    Знай свои типы



    Знай свои типы

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


    

        Бизнес: Предпринимательство - Малый бизнес - Управление