Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Конспект лекций по курсу Web-программирование.doc
Скачиваний:
11
Добавлен:
13.11.2019
Размер:
931.84 Кб
Скачать

Лекция №3.

Переменные.

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

[модификаторы] тип имя_переменной;

В данном случае тип — это либо один из простых типов (int, char, Boolean и т. д.), либо имя класса.

Простые типы используются так же, как и в языке C. После объявления переменной в неё можно записывать различные значения, включать её в состав выражения и т. д.

На первый взгляд кажется, что имена классов одинаково используются в качест­ве типов переменных как в Java, так и в C. Однако сходство это чисто внешнее.

Предположим, что в программе на языке C определён класс с именем ClassC. При­ведённое ниже выражение создает экземпляр класса ClassC и размещает его в пере­менной с именем objC.

Посредством objC мы можем обращаться к переменным и функциям-членам клас­са ClassC.

Рассмотрим подобную ситуацию в программе на языке Java. Предположим, что в ней определён класс с именем ClassJava и что в тексте программы присутствует такое выражение

ClassJava objJava;

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

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

С другой стороны, работать с объектами без указателей крайне сложно, поэтому в Java был реализован механизм ссылок. Упрощённо ссылку можно представить себе как указатель, который может указывать лишь на существующий объект определён­ного типа.

Для создания объекта и связывания с этим объектом переменной определенного типа служит оператор new. Вернёмся к рассмотренному выше примеру. После того как в программе определена переменная objJava типа ClassJava, мы можем включить в программу следующее выражение:

objJava = new ClassJava ();

Очевидно, что ClassJava () — это один из конструкторов данного класса. Он созда­ёт экземпляр класса ClassJava и возвращает ссылку на этот объект. Ссылка помещает­ся в переменную objJava.

После выполнения данной команды обращение к переменным и методам класса ClassJava производится так, как будто в переменной objJava содержится не ссылка, а экземпляр класса.

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

  • Модификатор типа доступа определяет, из каких классов может производить­ся обращение к объявляемой переменной. Доступ к переменным и методам в Javaорганизован несколько сложнее, чем в языке C, поэтому на первых эта­пах изучения языка руководствуйтесь простым правилом: чтобы разрешить обращение к переменной из-за пределов пакета, которому принадлежит класс, следует указать в описании этой переменной модификатор public.

  • Модификатор static превращает переменную экземпляра в переменную класса. Этот вид переменных хорошо знаком вам из языка C. В отличие от переменной экземпляра, переменная класса, или статическая переменная, с конкретным именем создаётся одна для всех объектов данного класса. Изменение значения этой переменной проявляется во всех экземплярах класса.

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

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

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

Массивы.

Работа с массивами в Java существенно отличается от C/C++. Основное отличие со­стоит в том, что массив по сути представляет собой объект. Поэтому, для того чтобы создать массив, надо не только объявить переменную, но и выполнить оператор new.

Переменная, содержащая ссылку на массив, объявляется следующим образом:

тип имя_переменной [];

Как и при объявлении обычной переменной, перед определением типа могут быть указаны модификаторы static, final, public и т. д.

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

имя_переменной=new тип [размер];

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

Методы.

Методы Java почти не отличаются от функций-членов C. Объявление метода вы­глядит следующим образом:

[модификаторы] возвращаемое_значение имя_метода ([список_параметров]) [throws список_исключений]

{

тело_метода

}

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

  • Модификатор типа доступа определяет, из каких классов может производиться обращение к методу. Как и в случае переменных, на первых этапах изучения языка вам достаточно запомнить модификатор public, допускающий вызов ме­тода из-за пределов пакета.

  • Модификатор static определяет метод класса, или статический метод. В отли­чие от метода экземпляра, метод класса можно вызвать, даже если ни один эк­земпляр данного класса не был создан.

  • Модификатор abstract определяет абстрактный метод. Абстрактный метод дол­жен обязательно быть переопределен в подклассе данного класса. Класс, со­держащий хотя бы один абстрактный метод, является абстрактным классом; эк­земпляр такого класса не может быть создан.

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

Исключительные ситуации.

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

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

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

Фрагменты кода, которые могут генерировать исключительные ситуации, следует поместить в блок try следующего формата:

try

{

Последовательность команд

}

Непосредственно за блоком try должен размещаться как минимум один блок catch, который выглядит так:

catch (описание_исключения)

{

Команды обработки исключительной ситуации

}

При нормальной работе программы наличие блока try никак не сказывается на её выполнении. По завершении фрагмента, предшествующего блоку try, управление пе­редается внутрь блока, а после того как все команды внутри блока будут выполнены, управление перейдет к первой команде, следующей после блока catch.

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

Классы, которые описывают интересующие нас исключительные ситуации, явля­ются подклассами класса Exception. Класс Exception, в свою очередь, является под­классом класса Throwable.

Иерархическая структура, включающая некоторые (очень немногие) классы, опи­сывающие исключительные ситуации, представлена ниже.

Exception

!

!-- IOException

! !

! !-- MalformedURLException

! !

! !-- UnknownHostException

! …

!

!-- RuntimeException

!

!-- ArithmeticException

!

Рассмотрим блок try, содержащий несколько команд, и блоки catch, предназна­ченные для обработки исключительных ситуаций.

try

{

sock=new Socket (www.myserver.com, 80};

a=b/d;

}

catch (UnknownHostException ex)

{

Обработка исключительной ситуации UnknownHostException

}

catch (IOException ex)

{

Обработка исключительной ситуации IOException

}

catch (ArithmeticException ex)

{

Обработка исключительной ситуации ArithmeticException

}

За блоком try следуют три блока catch. Конструктор класса Socket, вызываемый в блоке try, может генерировать исключения UnknownHostException и IOException, а при делении b/d, если значение d будет равно нулю, возникнет исключительная ситуация ArithmeticException. Каждое из этих исключений обрабатывается отдельным блоком catch.

Однако код программы можно существенно сократить. Три блока catch можно за­менить одним блоком, представленным ниже.

catch (Exception ex)

{

Обработка исключительных ситуаций всех типов

}

Если при выполнении метода может возникнуть исключительная ситуация, кото­рая не обрабатывается в теле метода, необходимо специально оговорить это в тексте программы. При объявлении такого метода следует указать ключевое слово throws, со­провождаемое перечнем имён классов, описывающих исключительные ситуации, ко­торые могут возникнуть при работе метода.

Простейшее Java-приложение.

Сейчас мы рассмотрим исходный код и процедуру построения простейшего Java-приложения. Текст программы, действия которой ограничиваются выводом крат­кого сообщения, приведён ниже.

import java.lang.*;

class FirstApplication

{

public static void main (String args [])

{

System.out.println (“Моё первое Java-приложение”);

}

}

Рассмотрим исходный текст приложения. Первая строка исходного кода импортирует пакет java.lang, кото­рому принадлежит класс System, используемый в работе приложения.

Рассмотрим метод main (). В его объявлении указаны модификаторы public и static. Модификатор public позволяет вызывать метод из-за пределов текущего па­кета. Модификатор static объявляет main () как статический метод. Это необходимо, так как при вызове main () ни одного экземпляра класса FirstApplication ещё не су­ществует.

При вызове метода main () ему передастся массив строковых значений, в котором содержатся параметры, заданные в командной строке. В нашем примере обработка параметров не предусмотрена.

Единственная команда, содержащаяся в теле метода, выводит на экран строку тек­ста. Последовательность имен System.out.println означает следующее. В классе System определена переменная класса, или статическая переменная out. Она ссылается на эк­земпляр класса PrintStream, реализующий выходной поток. В классе PrintStream определён метод println (), который выводит на экран строку символов, переданную ему в качестве параметра, и дополнительно выводит символ перевода строки.

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

В настоящее время разработчику предлагаются самые разнообразные инструмен­тальные пакеты, в том числе визуальные средства разработки программ. Выбор кон­кретного пакета — дело вкуса каждого специалиста. Однако среди всего набора дос­тупных средств разработки есть пакет JDK (Java Development Kit — инструментальный пакет разработки Java-программ), выполняющий роль стандарта. Байтовый код Java-программы подготав­ливается с помощью компилятора, а выполняется под управлением интерпретатора.

Компилятор, входящий в состав JDK, называется javac. Он вызывается из команд­ной строки, а в качестве параметра ему передается имя файла, содержащего исходный код Java-программы. Если приведенный выше исходный текст хранится в файле FirstApplication.java, то команда вызова компилятора будет выглядеть следующим образом:

javac FirstApplication.java

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

По окончании работы компилятор создаст байтовый код программы и поместит его в файл с именем FirstApplication.class. При выборе имени для файла с байтовым кодом учитывается не имя исходного файла, а имя класса. Если вы поместите исход­ный код в файл с другим именем, в результате компиляции все равно будет создан файл с именем FirstApplication.class.

После завершения работы компилятора байтовый код готов к выполнению. Для запуска Java-программы необходим интерпретатор, реализующий виртуальную маши­ну Java (JVM). Средства поддержки JVM имеются в любом современном Web-браузере, однако для запуска приложения вам придется воспользоваться интерпретатором из пакета JDK и именем java. Как и javac, интерпретатор запускается из ко­мандной строки, а в качестве параметра задается имя класса, содержащего метод main (). В данном случае это класс FirstApplication.

Как и следует ожидать, в результате выполнения данного приложения на экране отобразится строка символов «Моё первое Java-приложение».

Интерфейсы.

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

Выполнение некоторых типов про­грамм начинается по инициативе другого приложения, которое обращается не к main (), а к иному методу.

Пакеты.

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

import java.lang. *;

class Display

{

public static void main (String args [])

{

Calculations calc = new Calculations ();

System.out.println (calc.factorial (10));

}

}

class Calculations

{

int factorial (int a)

{

if (a ==1)

return 1;

else

return (a * factorial (a-1));

}

}

В отли­чие от предыдущего примера, данное приложение содержит два класса. Метод main (), определенный в классе Display, отображает данные, а factorial () — единственный метод, принадлежащий классу Calculations, вычисляет факториал целого числа.

Скомпилировав приложение и запустив его на выполнение, вы не увидите ничего особенного. Однако обратите внимание на содержимое текущего каталога. Если перед началом компиляции в нём был лишь файл Display.java, то те­перь в нем находятся также файлы Display.class и Calculations.class.

Итак, в языке Java каждый класс располагается в отдельном файле.

После запуска приложения виртуальная машина Java сама находит файл Calculations.class и использует содер­жащийся в нём байтовый код для проведения вычислений. Это позволяет обойтись без этапа компоновки различных модулей.

Вспомните, как компилируются программы, написанные на языке C++. Код, ко­торый поддерживает объекты, используемые в программе, включается в состав испол­няемого файла. Чтобы перенести C++-приложение на другой компьютер, необходимо скопировать весь исполняемый код, включая статически связанные библиотеки, — в противном случае приложение не будет работать. При использовании локальной сети такое копирование не вызывает затруднений, однако передать по Internet приложение объёмом в несколько мегабайт иногда бывает сложно.

Чтобы перенести на другой компьютер приложение, написанное на языке Java, надо передать значительно меньший объём кода. Необходимо скопировать лишь клас­сы, отсутствующие на удаленной машине; обычно это именно те классы, которые оп­ределяют специфику написанного вами приложения. Малая загрузка линий связи при копировании программ — одна из особенностей, благодаря которым Java стал при­знанным «сетевым» языком.

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

Первая строка каждого из приведенных выше исходных текстов содержала выражение

package math;

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

package stat;

Теперь полное имя класса, созданного вами, — math.Calculations, а имя класса, разработанного вашим сотрудником, — stat.Calculations.

Java поддерживает иерархию пакетов.