Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Секреты программирования для Internet на Java

.pdf
Скачиваний:
181
Добавлен:
02.05.2014
Размер:
3.59 Mб
Скачать

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

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

СОВЕТ Если вам понадобится узнать подробнее о стандарте Unicode, загляните на страницу по адресу http://unicode.org. Там вы найдете информацию о стандарте, сведения о том, как заказать бумажную копию стандарта Unicode, и узнаете, что нужно для того, чтобы стать членом Консорциума Unicode.

Комментарии

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

Комментарии в стиле C/C++ можно оформлять одним из следующих способов: // текст

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

// текст Весь текст, следующий после // до конца строки, игнорируется.

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

/** текст */

Текст в этом комментарии относится к переменной или методу, расположенному сразу после комментария.

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

Комментарии не могут вкладываться друг в друга.

Комментарии не могут быть частью строк или символьных констант.

Сочетания символов /* и */ не имеют никакого специального значения в комментариях, отбитых символами //.

Сочетание символов // не имеет никакого специального значения в комментариях, заключенных между /* и */.

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

/* Это обычный комментарий, содержащий сколько угодно //, /*, /**. Чтобы закончить его, нужно написать */

Ⱦɚɧɧɚɹ ɜɟɪɫɢɹ ɤɧɢɝɢ ɜɵɩɭɳɟɧɚ ɷɥɟɤɬɪɨɧɧɵɦ ɢɡɞɚɬɟɥɶɫɬɜɨɦ %RRNV VKRS Ɋɚɫɩɪɨɫɬɪɚɧɟɧɢɟ ɩɪɨɞɚɠɚ ɩɟɪɟɡɚɩɢɫɶ ɞɚɧɧɨɣ ɤɧɢɝɢ ɢɥɢ ɟɟ ɱɚɫɬɟɣ ɁȺɉɊȿɓȿɇɕ Ɉ ɜɫɟɯ ɧɚɪɭɲɟɧɢɹɯ ɩɪɨɫɶɛɚ ɫɨɨɛɳɚɬɶ ɩɨ ɚɞɪɟɫɭ piracy@books-shop.com

Ключевые слова

В любом языке есть группа особых идентификаторов, зарезервированных для использования самим компилятором. Эти идентификаторы, обычно называемые ключевыми словами (keywords), не могут поэтому служить именами для каких-либо объектов вашей программы. Ключевые слова, зарезервированные компилятором Java, перечислены в табл. 4-1.

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

Ключевые слова Java

+

+

+

+

abstract

do

implements

package

throw

boolean

double

import

private

throws

break

else

*inner

protected

transient

byte

extends

instanceof

public

try

case

final

int

*rest

*var

*cast

finally

interface

return

void

catch

float

long

short

volatile

char

for

native

static

while

class

*future

new

super

 

*const

*generic

null

switch

 

continue

*goto

operator

synchronized

 

default

if

*outer

this

 

Звездочками в этой таблице отмечены те ключевые слова, которые в текущей реализации языка, хоть и являются зарезервированными, не имеют никакого значения. Некоторые из них, например const и goto, зарезервированы с единственной целью сделать сообщения об ошибках, связанные с использованием этих конструкций, более осмысленными; другие относятся к тем механизмам, которые фирма Sun, вероятно, реализует в будущих версиях языка.

Типы данных

Тип данных, к которому принадлежит какая-либо переменная, может относиться к одному из четырех видов: классы, интерфейсы, массивы либо примитивные типы. На этапе компиляции каждая переменная воспринимается компилятором как принадлежащая либо к примитивному, либо к ссылочному типу данных. Слово "ссылочный" в словосочетании "ссылочный тип" говорит о том, что элементы таких типов (к которым относятся классы, интерфейсы и массивы) являются лишь указателями на некий объект. К примитивным типам относятся целые числа, числа с плавающей точкой, символы и булевские значения. Примитивные типы данных не являются ссылками на что-либо; их размер всегда известен заранее и никогда не меняется.

СОВЕТ Примитивные типы рассматриваются в следующем разделе "Примитивные типы данных", а информацию о ссылочных типах вы найдете в разделах "Классы", "Интерфейсы" и "Массивы".

Примитивные типы данных

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

СОВЕТ В языке Java любой примитивный тип имеет заранее известный и никогда не меняющийся размер. Ничего похожего на машинозависимые размеры типов, от которых страдают

www.books-shop.com

программисты на С/С++, в Java нет, как нет и никакой нужды использовать функцию sizeof. Наконец-то сделан решительный шаг в сторону истинной переносимости!

Целые числа

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

Таблица 4-2. Целые типы

Тип Размер в битах Минимальное значение Максимальное значение

byte

8

-128

127

short

16

-32768

32767

int

32

-2147483648

2147483647

long

64

-922372036854775808

922372036854775807

Целочисленные константы могут задаваться в программе одним из трех способов: в виде десятичных, шестнадцатеричных и восьмеричных значений. По умолчанию все числа интерпретируются как десятичные и относятся к типу int, если только вы не припишете в конце числа букву "l", что означает "long".

Шестандатеричная цифра может иметь значение от 0 до 15, причем для значений от 0 до 9 используются обычные десятичные цифры, а для значений от 10 до 15 - первые буквы латинского алфавита с A до F. Числа в шестнадцатеричной записи часто используются для записи больших чисел или для ввода значений, для которых более естественно двоичное представление. Поскольку каждая цифра представляет не 10, а 16 возможных значений, большое число в шестнадцатеричной записи занимает меньше места, чем в десятичной.

Возьмем для примера число 32767, записанное десятичными цифрами. Это число - наибольшее значение, которое может принимать тип short. В шестнадцатеричной записи оно имеет вид 0x7FFF. Всегда, когда вам нужно указать на то, что число записано в шестнадцатеричной системе, вы должны приписать к нему спереди пару символов "0x". Регистр букв в шестнадцатеричных числах значения не имеет.

Восьмеричная цифра принимает значения от 0 до 7. Число в восьмеричной записи должно начинаться с нуля, за которым следует одна или несколько восьмеричных цифр. Например, десятичное число 32767 в восьмеричной записи выглядит как 077777. Иначе говоря, если число начинается с нуля, для компилятора это служит сигналом к тому, что цифры этого числа должны интерпретироваться как восьмеричные.

Все целочисленные значения обладают свойством возврата к началу диапазона (wrapping). Это значит, что если вы попытаетесь увеличить или уменьшить целое число, уже находящееся на самой границе диапазона возможных значений, это число перескочит в противоположный конец своего диапазона. К примеру, возьмем переменную типа byte, имеющую значение 127. Если прибавить к этой переменной единицу, то ее значение станет -128. Никакой ошибки здесь нет - целые переменные в таких ситуациях всегда меняют свое значение с наибольшего положительного на наименьшее отрицательное значение. И наоборот: если от -128 отнять 1, мы получим 127. Мораль проста: чтобы не столкнуться с подобной неприятностью, вы должны заранее оценивать, какой диапазон целых значений вам понадобится, и выбирать для своих переменных соответствующий тип.

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

Язык Java поддерживает числа с плавающей точкой обычной и двойной разрядности в соответствии со стандартом IEEE на двоичную арифметику с плавающей точкой (IEEE Standard for Binary Floating-Point Arithmetic). Соответствующие типы называются float и double. Тип float

представляет собой 32-битное число с плавающей точкой обычной разрядности, а тип double - 64-битное число с плавающей точкой двойной разрядности.

www.books-shop.com

Переменные с плавающей точкой могут хранить не только численные значения, но и любой из особо определенных флагов (состояний): отрицательная бесконечность, отрицательный нуль, положительная бесконечность, положительный нуль и "отсутствие числа" (not-a-number, NaN). Поскольку все эти флаги определены в языке Java, вы можете предусматривать в своем коде соответствующие проверки. Как правило, эти особые состояния являются результатом ошибочных действий; например, если 0 поделить на 0, результатом будет NaN, и вы сможете в программе явным образом выяснить это. Таким образом, поддержка языком этих особых состояний существенно облегчает поиск ошибок.

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

Например, следующая строка кода приведет к ошибке при компиляции из-за несоответствия типов:

float num = 1.0;

Все константы с плавающей точкой по умолчанию относятся компилятором к типу double, поэтому, чтобы явным образом указать, что данная константа имеет тип float, припишите к цифровой записи этого числа букву "f":

float num = 1.0f;

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

Символы

Символы в Java реализованы с использованием стандарта Unicode (см. раздел "Идентификаторы и использование стандарта Unicode" выше). Это означает, что для хранения каждого символа отводится по 16 бит. Кодировка Unicode позволяет специфицировать множество самых экзотических непечатаемых символов и букв иностранных алфавитов. Чтобы задать константу-символ в программе, вы можете использовать как обычный символ, так и escapeпоследовательность для прямого указания кода в Unicode. В любом из этих случаев вы должны заключить символьное значение в пару апострофов.

Escape-последовательности в Unicode могут задаваться одним из двух способов. Первый из них должен показаться знакомым программистам на C/C++. Этот способ заключается в указании после обратной косой черты (\) некоторой буквы или символа, как показано в первом столбце табл. 4-3.

Таблица 4-3. Escape-последовательности в Unicode

 

Escape-последовательность

Функция

Значение в Unicode

\b

Забой (backspace)

\u0008

\t

Горизонтальная табуляция (horizontal tab) \u0009

\n

Перевод строки (linefeed)

\u000a

\f

Перевод страницы (form feed)

\u000c

\r

Возврат каретки (carriage return)

\u000d

\"

Двойная кавычка (double quote)

\u0022

\'

Апостроф (single quote)

\u0027

\\

Обратная косая черта (backslash)

\u005c

Вы можете также пользоваться другим способом записи escape-последовательностей: парой символов "\u", за которой следует четырехзначное шестнадцатеричное число, представляющее собой код нужного вам символа в Unicode. Число это может принимать значения от 0000 до 00FF. Вот несколько примеров симольных констант:

www.books-shop.com

'a' - символ "a".

'\n' - escape-последовательность для символа новой строки.

'\\' - escape-последовательность для символа обратной косой черты.

'\u0042' - escape-последовательность для символа с Unicode-кодом 0042.

Тип boolean

Переменные булевского типа могут иметь лишь одно из двух значений - true или false. Единственный способ присвоить значение переменной булевского типа - использование констант true и false. В отличие от C вы не можете присваивать булевским переменным целочисленные значения.

Однако чтобы как-то приблизиться к автоматическому преобразованию типов языка C, вы можете прибегнуть к сравнению целочисленного значения с нулем. Как известно, в языке C целочисленное значение 0 соответствует булевскому значению false, а все другие целочисленные значения - булевскому true. Чтобы преобразовать в соответствии с этими правилами целую переменную i к булевскому значению, вы можете использовать такую запись:

int i; boolean b; b = (i != 0);

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

СОВЕТ Тип boolean играет в языке Java важную роль. Многие конструкции этого языка, такие как операторы цикла и условные операторы, могут пользоваться только выражениями, имеющими тип boolean. Ничего сложного в правилах работы с этим типом нет, однако если вы привыкли к тому, как в таких случаях вынуждает вас поступать C/C++, концепция булевских типов языка Java может потребовать некоторых усилий для овладения.

Преобразование примитивных типов данных

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

Язык Java требует обязательного соответствия типов. Это значит, что компилятор не будет автоматически преобразовывать вам данные из одного типа в другой. Вы должны преобразовывать типы явным образом с помощью механизма приведения типа (type cast), который позволяет указать компилятору, к какому типу следует преобразовать те или иные данные.

В Java приведение типа осуществляется так же, как и в C/C++. Для этого достаточно указать идентификатор требуемого типа в круглых скобках перед приводимым выражением. Если затребованное преобразование типа возможно, оно будет осуществлено, и вы получите значение нужного типа. Допустим, у нас есть две переменные shortVar и intVar, первая из которых принадлежит к типу short, а вторая - к типу int. Между этими типами существуют два возможных преобразования:

short shortVar = 0; int intVar = 0; intVar = shortVar;

shortVar = intVar; // несовместимые типы в операторе присваивания

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

www.books-shop.com

плавающей точкой) уменьшив разрядность и тем самым точность представления.

Язык Java заставляет вас расписаться в том, что вы отдаете себе отчет, что происходит при таком преобразовании: при любых сужающих преобразованиях вы должны прибегать к явному приведению типа. Это еще один пример того, как Java пытается почти насильственными методами внедрить хороший стиль программирования. Каждый раз, когда вы преобразуете, к примеру, значение типа long (64 бита) в значение типа int (32 бита), вы должны предусмотреть, что именно должна будет делать программа при возможности потери информации. Если вы абсолютно уверены, что значение приводимого целого типа long будет всегда попадать в диапазон типа int, то смело прибегайте к приведению типа; в противном случае вам нужно будет предусмотреть какие-то дополнительные действия (например, выдачу предупреждения пользователю о возможной потере данных).

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

short shortVar = 0; int intVar = 0; intVar = shortVar;

shortVar = (short) intVar;

Теперь ничто не мешает компьютеру произвести требуемое присваивание. Значение intVar будет при этом преобразовано к типу short, в результате чего старшие биты числа будут отброшены, но знак числа при этом сохранится. В нашем случае это приведет к тому, что 32битное целое число превратится в 16-битное.

В табл. 4-4 перечислены все преобразования примитивных типов, допустимые в языке Java. Буква "C" в клетке таблицы означает, что для данного преобразования требуется явное приведение к типу, иначе компилятор выдаст сообщение об ошибке. Буква "L" означает, что при данном преобразовании может измениться величина или уменьшиться разрядность числа из-за частичной потери информации. Буква "X" обозначает, что данное преобразование типов в Java запрещено.

 

Таблица 4-4. Преобразование примитивных типов

 

 

 

Исходный

Тип, к которому происходит

+

+

+

+

+

+

+

тип

преобразование

 

 

 

 

 

 

 

^

byte

short

int

long float double char Boolean

byte

 

 

 

 

 

 

C

X

short

C, L

 

 

 

 

 

C

X

int

C, L

C, L

 

 

 

 

C, L

X

long

C, L

C, L

C,

 

C, L

C

C, L

X

 

 

 

L

 

 

 

 

 

float

C, L

C, L

C,

C, L

 

 

C, L

X

 

 

 

L

 

 

 

 

 

double

C, L

C, L

C,

C, L C, L

 

C, L

X

 

 

 

L

 

 

 

 

 

char

C, L

C

C

C

C

C

 

X

boolean

X

X

X

X

X

X

X

 

Буква "C" означает, что для данного преобразования требуется явное приведение типа; буква "L" означает, что при данном преобразовании может измениться величина или уменьшиться разрядность числа из-за частичной потери информации; буква "X" обозначает, что данное преобразование типов в Java запрещено.

Преобразование значений с плавающей точкой в целочисленные значения

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

www.books-shop.com

Преобразование числа с плавающей точкой двойной разрядности к обычной разрядности

Преобразование числа типа double к числу типа float происходит в соответствии с требованиями режима "округления к ближайшему" (round-to-nearest) стандарта IEEE 754. Если преобразуемое значение слишком велико и выходит за пределы диапазона типа float, результатом преобразования будет положительная или отрицательная бесконечность. Преобразование значения NaN дает в результате также NaN.

Преобразования типа boolean

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

boolean bool; int i = 15; String st = null;

if (i == 0) bool = false; else bool = true; if (bool) st = "true"; else st = "false";

СОВЕТ Информацию о преобразованиях ссылочных типов данных (классов, интерфейсов и массивов) вы найдете в соответствующем разделе этой главы.

Объявление переменных

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

Мы уже не раз создавали новые переменные в рассматриваемых примерах. Вот еще несколько примеров объявления и инициализации переменных в Java:

int i = 42;

String st = "Hello World"; float pi = 3.14f;

boolean cont;

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

Область действия

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

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

www.books-shop.com

может быть отложено.

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

class foo {

int cnt;

public void test1 { int num;

}

public void test2;

for(int cnt=0; cnt < 5; cnt++) { System.out.println(cnt);

}

}

}

На рис. 4-1 показано дерево уровней группирования для приведенного выше фрагмента программы.

Рис. 4.1.

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

Для тех, кто незнаком с языком C, синтаксис цикла for может показаться странным. Мы будем подробно говорить о циклах с for и о других типах циклов в разделе "Передача управления" данной главы.

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

www.books-shop.com

классу, а не к методу. Вот как это делается: this.cnt = 4;

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

Правила именования переменных

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

меток;

других переменных на данном уровне группирования;

параметров текущего метода.

Если вы в своей программе пользуетесь расширенной кодировкой Unicode, чтобы работать с символами иностранных алфавитов, то вы должны знать, как Java осуществляет сравнение символов. Один идентификатор признается равным другому только в том случае, если Unicodeкоды всех символов в этих двух идентификаторов совпадают. Это означает, что латинская заглавная "A" (код \u0041) отличается от греческой заглавной "А" (код \u0391) и от всех других букв "А", имеющихся в алфавитах мира. Отсюда также следует, что язык Java чувствителен к регистру, то есть что заглавное "А" и строчное "а" с точки зрения Java являются разными символами.

Знаки операций

Язык Java поддерживает большое количество знаков операций (operators). Знак операции представляет собой специальный символ и предназначен для выполнения какого-то действия над одной, двумя или более переменными. К самым распространенным знакам операций относятся плюс (+), минус (-) и знак равенства (=).

Знаки операций подразделяются по количеству своих аргументов (операндов). Некоторые знаки операций, например минус, имеют разный смысл в зависимости от того, относятся они к одному или двум операндам.

Таблица 4-5. Приоритет знаков операций

.

[ ]

( )

 

++

-

!

~ instanceof

*

/

%

 

++

-

 

 

<<< >>> >>>>

 

<

>

<=

>=

== !=

&

^^

&&

||

?:

=op=

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

www.books-shop.com

СОВЕТ Знак операции op= является сокращенной записью целого класса комбинированных знаков операций, примером которых может служить +=.

Выражением (expression) называется конструкция, построенная из знаков операций и их операндов. Вычисление выражений определяется набором правил приоритета. Когда говорят, что одна операция имеет приоритет над другой, это означает, что в выражении она будет выполнена раньше. Пример, который должен быть известен вам еще с начальной школы, - разница между сложением и умножением. Поскольку в выражении x=2+4*3 умножение выполняется раньше сложения, значением x будет 14, а не 18.

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

Знаки операций, расположенные в этой таблице в одной строке, имеют равный приоритет, и выражения выполняются слева направо.

Знаки операций с числовыми аргументами

Знаки операций, аргументами которых являются числа, разделяются на две категории: унарные (unary) знаки операций с одним аргументом и бинарные (binary) - с двумя аргументами. Бинарные знаки операций подразделяются далее на операции с числовым результатом и операции сравнения, результатом которых является булевское значение.

Результат операции будет всегда принадлежать в тому же типу, что и больший из операндов. Например, если мы складываем два целых числа, одно из которых типа short, а другое типа long, результат будет иметь тип long. Правила выбора типа результата обобщены в табл. 4-6, из которой также следует, что наименьшим результатом, возвращаемым при операциях с целыми числами, является тип int и что при сложении любого числа с числом с плавающей точкой результат будет иметь тип float или double. Теперь перейдем к рассмотрению унарных операций.

Таблица 4-6. Выбор типа результата операции

Тип 1 Тип 2 Тип результата

byte

byte

int

byte

short

int

byte

int

int

byte

long

long

short

short

int

short

int

int

short

long

long

int

int

int

int

long

long

int

float

float

int

double

double

float

float

float

float

double

double

Унарные знаки операций

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

Таблица 4-7. Унарные знаки операций

Знак операции Описание

- унарный минус

+унарный плюс

~ побитовое дополнение

++инкремент

www.books-shop.com