Java. Полное руководство. 8-е издание. С. Н. Тригуб Перевод с английского и редакция
Скачать 25.04 Mb.
|
ГЛАВА Типы данных переменные и массивы В этой главе рассмотрены три наиболее важных элемента типы данных, переменные и массивы. Как и все современные языки программирования поддерживает несколько типов данных. Эти типы можно применять для объявления переменных и создания массивов. Как будет показано, подход к использованию этих компонентов, примененный в Java, прост, эффективен и целостен — строго типизированный язык Прежде всего, важно уяснить, что Java — строго типизированный язык. Действительно, в определенной степени безопасность и надежность программ Java обусловлены именно этим обстоятельством. Давайте разберемся, что это означает. Во-первых, каждая переменная обладает типом, каждое выражение имеет тип и каждый тип строго определен. Во-вторых, все присваивания, как явные, таки за счет передачи параметров в вызовах методов, проверяются на соответствие типов. В Java отсутствуют какие-либо средства автоматического приведения или преобразования конфликтующих типов, как это имеет место в некоторых языках. Компилятор Java проверяет все выражения и параметры на предмет совместимости типов. Любые несоответствия типов являются ошибками, которые должны быть исправлены до завершения компиляции класса. Элементарные типы Язык Java определяет восемь элементарных типов данных b y t e , s h o r t , i n t , lo n g , c h a r , f l o a t , d o u b le и b o o le a n Элементарные типы называют также простыми, ив этой книге мы будем использовать оба эти термина. Элементарные типы можно разделить на четыре группы. • Целые числа. Эта группа включает в себя типы b y t e , s h o r t , i n t и lo n g , которые представляют точные целые числа со знаком. • Числа с плавающей точкой. Эта группа включает в себя типы f l o a t и d o u b l e , которые представляют числа, определенные с точностью до определенного десятичного знака 7 Часть I. Язык Символы. Эта группа включает в себя тип char, которая представляет символы символьного набора, такие как буквы и цифры. • Булевы значения. Эта группа включает в себя тип boolean — специальный тип, предназначенный для представления значений типа истинно ложно Эти типы можно использовать в том виде, как они определены, или же для создания собственных типов классов. Таким образом, они служат основой для всех других типов данных, которые могут быть созданы. Элементарные типы представляют одиночные значения, а несложные объекты. Хотя во всех других отношениях полностью объектно-ориентированный язык, элементарные типы данных таковыми не являются. Они аналогичны простым типам, которые можно встретить в большинстве других не объектно- ориентированных языков. Эта особенность обусловлена стремлением обеспечить максимальную эффективность. Превращение элементарных типов в объекты привело бык слишком большому снижению производительности. Элементарные типы определены так, чтобы они обладали явным диапазоном допустимых значений и математически строгим поведением. Языки вроде Си+ допускают варьирование размеров целочисленных переменных в зависимости от требований среды исполнения. Однако Java отличается в этом отношении. В связи с требованием переносимости, предъявляемым к программам Java, все типы данных обладают строго определенным диапазоном допустимых значений. Например, независимо от конкретной платформы, значения типа int всегда являются битовыми. Это позволяет создавать программы, которые гарантированно будут выполняться на любой машинной архитектуре без специального переноса Хотя в некоторых средах строгое указание размера целых чисел может приводить к незначительному снижению производительности, оно абсолютно необходимо для обеспечения переносимости программ. Рассмотрим каждый из типов данных. Целочисленные значения Язык Java определяет четыре целочисленных типа byte, short, int и long. Все эти типы представляют значения со знаком — положительные и отрицательные не поддерживает только положительные целочисленные значения без знака. Многие другие языки программирования поддерживают целочисленные значения как со знаком, таки без знака. Однако разработчики Java посчитали целочисленные значения без знака ненужными. В частности, они решили, что концепция значений без знака использовалась, в основном, для указания поведения старшего бита, который определяет знак целочисленного значения. Как будет показано в главе 4, в Java управление значением старшего бита осуществляется иначе — за счет применения специальной операции сдвига вправо без учета знака. Тем самым потребность в целочисленном типе без знака была исключена. Ширина целочисленного типа представляет не занимаемый объем памяти, а, скорее, поведение, определяемое им для переменных и выражений этого типа. Среда времени выполнения Java может использовать любой размер до тех пор, пока типы ведут себя объявленным образом. Как показано в табл. 3.1, ширина и диапазон допустимых значений этих целочисленных типов изменяются в широких пределах Глава 3. Типы данных, переменные и массивы Таблица 3.1. Ширина и диапазон допустимых значений целочисленных типов Имя Ширина Диапазон допустимых значений long 64 от -9223372036854775808 до от -2147483648 до от -32768 до от -128 до Теперь рассмотрим каждый из типов целочисленных значений. Тип b y t Наименьший по размеру целочисленный тип — byte. Это битовый тип со знаком и диапазоном допустимых значений от -128 до 127. Переменные типа byte особенно полезны при работе с потоком данных, поступающих из сети или файла. Они полезны также при манипулировании необработанными двоичными данными, которые могут не быть непосредственно совместимыми с другими встроенными типами Для объявления переменных типа byte служит ключевое слово byte. Например, в следующей строке объявлены две переменные типа by te — b и с b, с; Тип s h o r Тип short — битовый тип со знаком. Он имеет диапазон допустимых значений от -32768 до 32767. Вероятно, этот тип используется в Java наименее часто. Ниже приведено несколько примеров объявления переменных типа short. short s ;short t Тип i n Наиболее часто используемым целочисленным типом является int. Это битовый тип со знаком, который имеет диапазон допустимых значений от -2147483648 до 2147483647. Кроме других способов применения, переменные типа int зачастую используются для управления циклами и индексирования массивов. Хотя на первый взгляд может показаться, что использование типов byte или short эффективнее использования типа int в ситуациях, когда не требуется более широкий диапазон допустимых значений, предоставляемый последним, в действительности это не всегда так. Это обусловлено тем, что при указании значений типа byte ив выражениях их тип повышается до типа int при вычислении выражения. (Повышение типа описано в этой главе позже) Поэтому тип int зачастую наиболее подходит для работы с целочисленными значениями. Тип l o n Это битовый тип со знаком, удобный в тех ситуациях, когда длина типа int недостаточна для хранения требуемого значения. Диапазон допустимых значений Часть I. Язык типа long достаточно велик. Это делает его удобным для работы с большими целыми числами. Например, ниже приведен пример программы, которая вычисляет количество миль, проходимых лучом света за указанное число дней Вычисление расстояния, проходимого светом с применением переменных типа long, class Light { public static void main(String args[]) { int lightspeed; long days; long seconds; long distance; // приблизительная скорость света в милях за секунду lightspeed = 186000; days = 1000; // указание количества дней = days * 24 * 60 * 60; // преобразование в секунды = lightspeed * seconds; // вычисление расстояния System.out.print("За " + days); System.out.print(" дней свет пройдет около "); System.out.println(distance + " миль."); } } Эта программа создает следующий вывод. За 1000 дней свет пройдет около 16070400000000 миль. Очевидно, что результат не поместился бы в переменной типа Типы с плавающей точкой Числа с плавающей точкой, называемые также действительными числами, используются при вычислении выражений, которые требуют результата с точностью до десятичного знака. Например, вычисление квадратного корня или трансцендентных функций вроде синуса или косинуса приводит к результату, который требует применения типа с плавающей точкой. В Java реализован стандартный (в соответствии с IEEE-754) набор типов и операций с плавающей точкой. Существует два типа с плавающей точкой float и double, которые соответственно представляют числа одинарной и двойной точности. Их ширина и области допустимых значений описаны в табл. Таблица 3.2. Ширина и диапазон допустимых значений типов с плавающей точкой Щ1фта ш бтах :, * Приблизительныйдиапазон допустимых значений L d o u b от е до е l o a от е до 3.4е+038 Рассмотрим каждый из этих типов с плавающей точкой Глава 3. Типы данных, переменные и массивы Тип f l o a Этот тип определяет значение одинарной точности, которое при хранении занимает 32 бит. В некоторых процессорах обработка значений одинарной точности выполняется быстрее и требует в два раза меньше памяти, чем обработка значений двойной точности, нов тех случаях, когда значения либо очень велики, либо очень малы, точность вычислений оказывается недостаточной. Переменные типа f l o a t удобны в тех случаях, когда требуется дробная часть значения без особой точности. Например, значение типа f l o a t может быть удобно для представления денежных сумм в долларах и центах. Ниже приведен пример объявлений переменных типа f l o a t . float hightemp, Тип d o u b l Двойная точность, как следует из ключевого слова d o u b le (двойная, требует использования 64 бит для хранения значений. В действительности в некоторых современных процессорах, которые оптимизированы для выполнения математических вычислений с высокой скоростью, обработка значений двойной точности осуществляется быстрее, чем обработка значений одинарной точности. Все трансцендентные математические функции, такие как s i n ( ) , c o s () и s q r t ( ), возвращают значения типа d o u b le . Применение типа d o u b le наиболее рационально, когда требуется сохранение точности множества последовательных вычислений или манипулирование большими числами. Ниже приведен пример короткой программы, в которой переменные типа d o u b le используются для вычисления площади круга Вычисление площади круга class Area { public static void main(String a r g s []) { double pi, r, a; r = 10.8; // радиус окружности = 3.1416; / / p i , приблизительное значение = pi * г * г // вычисление площади System.out.println("Площадь круга составляет " + a); } } Символы В Java для хранения символов используется тип данных c h a r. Однако программистам наследует помнить, что тип c h a r вне эквивалентен тйпу c h a r в С или C++. В C/C++ c h a r — это целочисленный тип, имеющий ширину 8 бит. В Java это не так. Вместо этого в нем для представления символов используется кодировка Unicode, определяющая международный набор символов, который может представлять все символы известных языках. Кодировка Unicode представляет собой унифицированный набор из десятков наборов символов, таких как латиница, греческий алфавит, арабский алфавит, кириллица, иврит, японские и тайские иероглифы, атак же множество других. Поэтому для хранения этих символов требуется 16 бит. Таким образом, в Java тип c h a r является битовым. Диапазон допустимых значений этого типа—от 0 до 65536. Не существует отрицательных значений типа c h a r. Стандартный 7 6 Часть I. Язык набор символов, известный как ASCII, содержит значения от 0 до 127, а расширенный битовый набор символов, ISO-Latin-1, — значения от 0 до 255. Поскольку язык Java предназначен для обеспечения возможности создания программ, применимых во всем мире, использование кодировки Unicode для представления символов вполне обоснованно. Конечно, применение Unicode несколько неэффективно для таких языков, как английский, немецкий, испанский или французский, для представления символов которых вполне достаточно 8 бит. Но это та цена, которую приходится платить за переносимость программ во всемирном масштабе. На заметку Более подробно о кодировке Unicode см. на веб-сайте http://www. U n i c o d e .o r g Использование переменных типа char демонстрирует следующая программа Демонстрация использования типа данных char, class CharDemo { public static void main(String args[]) { char c h i , c h 2 ; chi = 88; // код переменной X ch2 = 'Y '; System.out.print("chi и c h 2 : "); System.out.println(chi + " " + ch2) Эта программа отображает следующий выводи Обратите внимание на то, что переменной c h i присвоено значение 88, являющееся значением ASCII (и Unicode), которое соответствует букве X. Как уже было сказано, набор символов ASCII занимает первые 127 значений набора символов Unicode. Поэтому все старые трюки, применяемые при работе с символами в других языках, будут работать ив среде Хотя тип char был разработан для хранения символов Unicode, его можно также использовать как целочисленный тип, пригодный для выполнения арифметических операций. Например, он позволяет выполнять сложение символов или уменьшать значение символьной переменной. Рассмотрим следующую программу Символьные переменные ведут себя подобно целочисленным значениям class CharDemo2 { public static void main(String a r g s []) { char chi; chi = 'X '; System.out.println("chi содержит " + chi); chl++; // увеличение значения chi на единицу System.out.println("chi теперь " + Эта программа создает следующий вывод содержит X chi теперь Y } Глава 3. Типы данных, переменные и массивы Вначале программа присваивает переменной chi значение X. Затем она увеличивает значение переменной chi на единицу. В результате хранящееся в переменной значение становится буквой Y — следующим символом в последовательности ASCII (и На заметку В формальной спецификации Java тип char упоминается как целочисленный это значит, что он находится в той же общей категории, что и типы int, short, long и byte. Однако поскольку основное назначение типа char — представлять символы Unicode, он находится в собственной категории. Булевы значения Язык Java содержит элементарный тип, названный boolean, который предназначен для хранения логических значений. Переменные этого типа могут принимать только одно из двух возможных значений true истинно) или false ложно. Этот тип возвращается всеми операторами сравнения, подобными а<Ь. Тип boolean обязателен для использования также в условных выражениях, которые управляют такими управляющими операторами, как if и Следующая программа служит примером использования типа boolean. // Демострация использования значений типа boolean, class BoolTest { public static void main(String a r g s []) { boolean b; b = false; System.out.println("b равна " + b ) ; b = true; System.out.println("b равна " + b ) ; // значение типа boolean может управлять оператором if if(b) Это выполняется b = false; if(b) Это не выполняется результат сравнения - значение типа boolean System.out.println("10 > 9 равно " + (10 > Эта программа создает следующий вывод равна false b равна true Это выполняется > 9 равно В приведенной программе особый интерес представляют три момента. Во- первых, как видите, при выводе значения типа boolean методом println () на экране отображается строка "true" или "false". Во-вторых, самого по себе значения переменной типа boolean достаточно для управления оператором if. Вовсе необязательно записывать оператор i f так, как показано ниже == true) ... В-третьих, результат выполнения оператора сравнения, такого как с, — значение типа boo 1 еап. Именно поэтому выражение 10 > 9 приводит к отображению строки " true" . Более того, выражение 10 > 9 должно быть заключено в допол 7 8 Часть I. Язык Java нительный набор круглых скобок, поскольку оператор + обладает более высоким приоритетом, чем оператор Более подробное рассмотрение литералов Литералы были вскользь упомянуты в главе 2. Теперь, когда встроенные типы формально описаны, рассмотрим их подробнее. Целочисленные литералы Целочисленные значения — вероятно, наиболее часто используемый тип в типичной программе. Любое целочисленное значение является числовым литералом. Примерами могут служить значения 1, 2, 3 и 42. Все они — десятичные значения, описывающие числа с основанием 10. В числовых литералах могут использоваться еще два вида представления — восьмеричное (с основанием 8) и шестнадцатеричное (с основанием 16). В Java восьмеричные значения обозначаются ведущим нулем. Обычные десятичные числа не могут содержать ведущий нуль. Таким образом, внешне вполне допустимое значение 09 приведет к ошибке компиляции, поскольку 9 выходит за пределы диапазона от 0 до 7 допустимых восьмеричных значений. Чаще программисты используют шестнадцатеричное представление чисел, которое явно соответствует словам, размер которых равен 8, 16, 32 и 64 бит, составленным из битовых блоков. Значения шестнадцатеричных констант обозначают ведущим нулем и символом х (Ох или ОХ. Диапазон допустимых шестнадцатеричных цифр — от 0 до 15, поэтому цифры от 10 до 15 заменяют буквами от А доили от а до Целочисленные литералы создают значение типа int, которое в Java является битовым целочисленным значением. Поскольку Java — строго типизированный язык, может возникать вопрос, каким образом можно присваивать целочисленный литерал одному из других целочисленных типов Java, такому как byte или long, не вызывая при этом ошибку несоответствия типа. К счастью, с подобными ситуациями легко справиться. Когда значение литерала присваивается переменной типа byte или short, ошибка не происходит, если значение литерала находится в диапазоне допустимых значений этого типа. Кроме того, целочисленный литерал всегда можно присваивать переменной типа long. Однако чтобы указать литерал типа long, придется явно указать компилятору, что значение литерала имеет этот тип. Для этого к литералу дописывают строчную или прописную букву L. Например, 0x7ffffffffffffffL,^H 922 337203 685477 наибольший литерал типа long. Целочисленное значение можно присваивать типу char, если оно лежит в пределах допустимого диапазона этого типа. Начиная с JDK 7 вы можете также определить целочисленные литералы, используя двоичную форму. Для этого перед значением используется префикс Ь или В. Например, Следующий код определяет десятичное значение 10 с использованием двоичного литералах Ы 0 1 0 Наличие двоичных литералов облегчает также ввод значений, используемых как битовые маски. В таком случае десятичное (или шестнадцатеричное) представление значения числа не отображает визуально способ его использования, а двоичный литерал отображает Глава 3. Типы данных, переменные и массивы |