Циклы, операции и тип данных Currency

В

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

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

Теперь пора приступить к рассмотрению всего этого материала. Программы-при­меры MathOpsSimple, BigDecimalTest И HhileLoops, приведенные B ЭТОЙ Главе, можно в сопровождающих книгу материалах и на сайте Www. eivenware. com. В этих материалах находится еще одна программа, fioatops, к которой прилагается об­ширный HTML-документ, немного расширяющий материал, приведенный в дан­ной главе.

Циклы

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

И циклы for, и циклы while дают возможность программисту повторить не­сколько раз определенный блок кода. Короче говоря, циклы предназначены для по­вторений.

Для большинства людей "повторение" — слово неприятное. Обычно нам не хо­чется принимать участие в повторениях. Например, многие виды повторяющихся работ считаются непривлекательными, и все просто ненавидят повторение, кото­рое "мать учения".

Но все-таки многие творческие действия являются повторяющимися. Дерево по мере своего роста повторяет одни и те же фазы, постепенно увеличивая свои разме­ры Повторение также широко применяется в музыке: многократно повторяются определенные последовательности аккордов или ритмических структур. Это верно даже для таких относительно сложных форм музыкальных произведений, как джаз или сонаты И. С. Баха.

Компьютеры берут на себя монотонность выполнения повторений, автоматизи­руя их. В частности, автоматизировать многие повторяющиеся действия позволяют операторы for и while.

Циклы For

Циклы for в Java выглядят почти точно так же, как и в С/С++. Совпадают и их синтаксис, и семантическое значение.

Рассмотрим следующий простой фрагмент кода: int j;

For (int i = O; i < 10; i++)

{

J = (i * i) + 1;

}

Здесь объявлены две целых переменных: j и i. Обратите внимание, что перемен­ная i объявлена внутри самого оператора. Это не только вполне допустимо, но и яв­ляется рекомендуемым способом объявления Управляющей переменной {Control Variable) в цикле for.

примечаниеВ этом цикле указано, что он будет повторяться десять раз, увеличивая при каж­дом повторении переменную i на единицу. То есть вначале переменная i равна о, а затем десять раз увеличивается и достигает значения 9. После чего цикл заканчива­ется. Код, увеличивающий переменную i, выглядит так: i++. О смысле унарной операции ++ я расскажу позже в этой же главе.

Переменная i имеет область видимости только в пределах цикла. Вне цикла Java ничего не знает о ее существовании: int j;

For (int i = О; i < 10; i++)

<

J = (i * i) + 1;

}

J = i; ∕∕ Неверно. Здесь переменная i не существует.

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

For (int i = 0; i < 10; i++) j = (i * i) + 1;

А вот описание синтаксиса цикла for на псевдокоде:

For (инициализация; проверка; увеличение) оператор

Возвращаясь к нашему примеру, мы видим, что фрагмент кода int i = о явля­ется инициализацией, i < 10 — проверкой (или условием), а увеличение выглядит так: i++. Название "увеличение" не очень верно, т. к. в этой части кода переменную можно и увеличивать, и уменьшать.

В общей форме оператора For, Показанной здесь, первая строка часто называет­ся заголовком (header), а вторая — телом (body). Итак, тело состоит из части, назы­ваемой Оператор.

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

При выполнении цикла For Сначала обрабатывается выражение инициализации. И обрабатывается оно лишь один раз. Затем выполняется проверка (условия). Если вычисление этого условия дает True, То выполнение цикла продолжается; в против­ном случае происходит выход из цикла. После этого выполняется тело оператора. Выполняется ли элемент увеличения до или после тела цикла, несколько зависит от способа его записи.

Вот пример цикла for, который можно опробовать в приложении JBuiIder:

Void jButtonl_actionPerformed(ActionEvent Е)

{

Int j ;

For (int i = О; I < 10; i++)

(

J = (i * I) + l;

JComboBoxl. addltem(Integer. toString(j));

}

}

Для выполнения этого кода необходимо сначала открыть JBuilder, создать при­ложение, как описано в главе 3, а затем поместить на главную форму кнопку и выпа­дающий список. Если вы оставите имя элемента JComboBox По умолчанию, то вы сможете создать обработчик события, который выглядит точно так же, как и приве­денный здесь. Как вы помните, создать обработчик события можно так: в режиме конструирования выбрать элемент JButton, Перейти на страницу Events инспекто­ра, выбрать событие action Performed и нажать клавишу Enter.

Вообще-то с помощью циклов For Можно делать много всякой ерунды. Это воз­можно в основном благодаря огромной синтаксической гибкости языка Java по от­ношению к архитектуре циклов. Например, следующие два примера полностью верны:

For (;;)

For (Int X=3, Y=10; Х < 100; X++Z У-=3,

Первый пример запускает бесконечный цикл, из которого можно выйти с помо­щью оператора Return:

Int Х = 3; for (;;)

{

Х++;

If (Х > 5)
bre<.k;

Я согласен, что этот код вряд ли практически ценен, но все-таки он верен. Он указывает, что нужно выйти из цикла, когда × станет больше 5. Разумеется, суще­ствуют и более простые способы записать то же самое. И в самом деле, мне очень редко бывают нужны столь замысловатые конструкции. Но все-таки это дело лично­го вкуса, и я видел много великолепных программистов, которые явно наслаждались богатыми возможностями, предоставляемыми оператором for языка Java. Вообще — то я считаю, что эта гибкость предназначена для очень немногих наиболее искус­ных и опытных программистов. Для программистов начального и среднего уровня и просто здравомыслящих людей она почти всегда приводит к излишним проблемам.

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

В оставшейся части этой главы рассыпано еще много дополнительных примеров применения циклов for. Но перед этим я хотел бы еще остановиться на циклах while.

Циклы While

Как и цикл for, цикл while является относительно простой, но в то же время до­вольно мощной синтаксической конструкцией. Общий синтаксис цикла while выг­лядит следующим образом:

While (выражение) оператор

Вот пример оператора while, который вы можете скомпилировать в JBuilder:

Void whileLoopBtn_actionPerformed(ActionEvent Е)

{

Int i = 0; while (i < 10)

{

I++;

JComboBoxl. addɪtem(Integer. toString(i));

}

)

Этот метод начинается с объявления переменной i. Затем выполняется цикл while. Вычисляется выражение в заголовке цикла. Если оно получается равным true, тело цикла выполняется. После выполнения тела цикла вновь вычисляется выражение, и код тела цикла выполняется снова, и так происходит, пока выражение выдает true. Если оно становится равным false, управление передается за пределы цикла while, а тело цикла пропускается. Обратите внимание, что вы должны явно увеличивать значение переменной i. Если не увеличивать ее значение, то програм­ма зациклится.

примечание——"-миша в старые добрые времена Turbo Pascal в документации на этот продукт в указателе поиска была строка »бесконечный цикл: см. цикл, бесконечный". Hy и ко­нечно, если вы обращались к строке "цикл бесконечный", то видели там "см. бесконеч­ный цикл". Это замечательный пример хакерского юмора, а заодно и великолепное объяснение бесконечного цикла: авторы документации нашли способ полностью объяс­нить относительно сложную тему даже без предложения читателю выйти из указателя поиска. Насколько я знаю, это единственный пример, когда индексный указатель книги выполняет ту же задачу, что и текст книги, причем без обращения к самому тексту! (Правда, подобное еще встречалось и у С. Лема, вспомните описание в звездных днев­никах Ийона Тихого, что такое сепульки ("Сепульки — см. сепуление… Сепуление — то Же, что и сепулевание. См. сепульки…").)

В Java также определен цикл do-while, противоположный циклу while.

Do

{

JComboBoxi. addltem(Integer. toString(i)); i—;

}

While (i > O);

Цикл do-while отличается от цикла while тем, что он выполняется хотя бы один раз, независимо от начального значения переменной i. Короче говоря, если вам нужно, чтобы цикл выполнился хотя бы раз, используйте цикл do-while, иначе используйте ЦИКЛ While.

Маньяки оптимизации записали бы предыдущий пример по-другому:

Do

(

JComboBoxl. addɪtem(Integer. toString(i)) ;

}

While (i— > O) ;

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

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

Do

{

JComboBoxl. addltern(Integer. toString(i));

)

While (—i > O) ;

Этот код досчитает до единицы и выйдет из цикла. Код предыдущего примера перед выходом из цикла досчитает до нуля. Отличие между примерами состоит в применении операции —. В первом случае переменная уменьшается После вычисле­ния логического выражения цикла while, а во втором случае уменьшение происхо­дит До вычисления выражения. Я упоминаю все это не для того, чтобы закопаться в несущественных деталях, а чтобы плавно перейти от циклов к операциям и их при­менению в языке Java.

Среди сопровождающих книгу материалов можно найти программу WhileLoops, Демонстрирующую использование большей части кода, о которой до сих пор шла речь в этой главе. Объяснения, как построить подобные программы, приведены в части III, "Основы JBuilder". А пока можно просто запустить программу и немного поэкспериментировать с ней. У вас будет еще много возможностей узнать, как стро­ить подобные программы, в других разделах данной книги.

Математические операции

Вот и пришло время поговорить об операциях.

В данном разделе речь пойдет об основных математических операциях: +,-,*,% и /. Это операции, применяемые для сложения, вычитания, умножения, вычисле­ния остатка от деления и обычного деления.

Название

Операция

Пример

Сложение

+

1 + 1

Вычитание

1-1

Умножение

*

1*1

Деление

/

1/1

Модуль

%

1 % 1

Обратите внимание, что вы, если хотите, можете рассматривать операцию взятия модуля как операцию вычисления остатка. Она возвращает остаток от деления двух чисел. Например, 10 % 3 равно 1. Но тут я забегаю вперед паровоза, поскольку под­робно объясню все это чуть дальше в этой главе.

Использование математических операций

Основные математические операции просты и понятны. Например, вот так можно сложить два числа:

ɪnt а = 10, Ь = 5; с; с = а + Ь;

Это все более или менее интуитивно ясно. В данном случае, возможно, будет бо­лее интересно увидеть, как я отображу этот код внутри приложения JBuilder. Други­ми словами, не сложно понять, как работает операция +, но требуется некоторое время для объяснения, как я продемонстрирую работу математических операций. Это объяснение важно, поскольку оно показывает операцию конкатенации строк.

Пример программы для этого раздела называется MathOpsSimple. Программа выводит следующий текст:

Сложение с = а + Ь 13 = 10 + 3 умножение с = а * Ь 30 = 10 * 3

Вычитание с = а — b 7 = 10 — 3 деление с = а / Ь 3 = 10 / 3

Остаток (модуль) с = а % Ь 1 = 10 % 3

Для создания этой програм­мы сначала создайте новый про­ект с именем MathOpsSinple. За­тем создайте новый класс, выбрав пункт меню File ∣ New Class, как показано на рис. 11.1. Обратите

рис. 11.1. создание главного класса для программы mathopssimpleВнимание, что класс является производным от Java. lang. object И имеет главный метод.

Заполните класс так, чтобы он стал похож на исходный код, приведенный в лис­тинге 11.1. Этот класс зависит от другого класса с именем Adder, который вам также предстоит создать. Таким образом, он опирается на сведения о классах, полученные в главе 8.

Листинг 11.1. Главный класс программы MathOpsSimpIe

Package mathopssimple; Public class MathOpsSimple 1

Public static void main (String [] args)

Int a = 10, b = 3;

Adder adder =

New Adder () ; adder. add(a, b); adder. multiply(a, b); adder. subtract(a, b); adder. divide(a, b); adder. modulus(a, b);

рис. 11.2. создание второго класса adder без главного метода, являющегося производным от java.lang.objectСнова выберите пункт меню File ∣ New Class и со­здайте другой класс, Adder, Как показано на рис. 11.2. Этот класс также является произ­водным ОТ Java. Iang. object, Но у него нет главного ме­тода.

Создайте код для этого второго класса, чтобы он выглядел как класс, показанный в листинге 11.2. Это класс, вызываемый из главного класса, приведенного в листинге 11.1. Листинг 11.2. Код класса Adder, Выполняющего простые математические действия

Package mathops s iɪnple ;

Import j ava. awt.*;

Inport java. awt. event.*;

Import javax. swing.*;

∕**

* <p>Title: <∕p>

* <p>Description: <∕p>

* <p>Copyright: Copyright (c) 2002<∕p>

* <p>Coropany: <∕p>

* Gauthor unascribed

* Gversion 1.0 */

Public class Adder extends JFreune

{

Private void addSpace(String opName)

1

System. out. println ("————————— ‘,) ;

System. out. println(opName);

}

Void add(int a, int b)

{

Int c;

AddSpace("Сложение");

Sys tern. out. println ("c = a + b") ; c = a + b;

System, out. println (c + " = " + a + " + " + b) ;

1

Void multiply (int a, int b)

{

Int c;

AddSpace("умножение");

System. out. println(‘*c = a * b") ; c = a * b;

System, out. println (c + " = " + a + " * " + b) ;

}

Public void divide (int a, int b)

{

Int c;

AddSpace("деление");

System. out. println ("c = a ∕ b") ; c = a∕b;

System, out. println (c + " = " + a + ‘, ∕ " + b) ;

1

Public void modulus (int a, int b)

{

Int c;

AddSpace("остаток (модуль)");

System, ou t. print In ("c = a % b") ; c = a % b;

System. out. println(c + " = " + a + " % " + b) ;

1

Public void subtract(int a, int b)

{

Int c;

AddSpace("вычитание");

System. out. println("c = a — b") ; c = a — b;

System. out. println(c + " ≈ ,, + a + ,, — " + b) ;

Метод add в классе Adder выглядит следующим образом:

Void add (int a, int b)

{

Int c;

AddSpace("сложение");

System. out. printin("c = a + b"); c = a + b;

System. out. println(c + ,, = ” + a + ,, + " + b) ;

}

Код этого метода принимает в качестве параметров две переменные целого типа. Он объявляет локальную переменную С Типа int. Первая выполняемая строка этого метода вызывает метод addSpace:

Private void addSpace(String opName)

{

System. out. println ("———————- ") ;

System. out. println(opName);

}

Я добавил этот метод в программу для вывода разделителей между элементами, которые печатаются в стандартный выводной поток с помощью Java-метода System. out. println.

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

Код данного метода вызывается из различных частей этой программы. Можно было бы просто вписать строки кода вывода данных заголовков в каждом из этих мест. Но я предпочел вызывать этот метод. Теперь мне достаточно изменить работу только этого метода, и все методы, вызывающие его, будут вести себя по-другому, т. е. они будут по-новому выводить данные в окно вывода. Если бы я не сделал так, то, чтобы изменить разделитель, отделяющий вывод данных от предыдущих, мне пришлось бы вносить изменения в каждый метод. Эта тема обсуждается более под­робно в главе 22, "Модульность".

После вызова метода addSpace программа отображает пользователю код, кото­рый будет выполнен следующим:

Systern. out. println("с = а + Ь");

После чего остается только действительно выполнить математическую операцию и показать пользователю операнды и результат операции:

С = а + Ь;

System. out. printIn(с + ,, = " + а + " + "+ Ь) ;

Обратите внимание на последнюю строку кода. Она "связывает" вместе пере­менные и строковые литералы в одну строку с помощью операции +. Этот код начи­нается с вывода значения переменной с, которое в это время равно 13. Затем с этим значением конкатенируется строка " = ". Это приводит к отображению в окне вы­вода строки "13 = ". Затем с помощью операции + к этой строке добавляется значе­ние переменной а и строка " + ". После этого на экране отображается следующий текст: "13 = 10 + ". И, наконец, добавляется значение ь, после чего строка, выве­денная на экран, выглядит так: ”13 = ю + 3". (Автор объясняет так, как проще Для понимания, хотя на самом деле вся эта строка сначала "собирается" в памяти, а затем передается для отображения методу System. out. printin — Прим, перев.) Вы можете посмотреть на рисунках 11.3 и 11.4, а можете сами запустить эту программу, чтобы убедиться, что все происходит именно так.

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

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

На самом деле при этом вызывается еще один класс: StringBuffer. Реально вы­полняемый код выглядит следующим образом-

Х = new StringBufferO .append("15”) .append(" = ") . append("10").append(" + ").append(5).toString();

рис. 11.3. выходные данные программы mathopssimple отображаются в окне сообщении в нижней части ide

Операции умножения и целые числа

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

Void multiply (int a, int Ь)

{

Int С;

AddSpace("умножение");

System. out. println(= А * Ь"); с = А * Ь;

System. out. println+ " = " + А + " * " + Ь) ;

)

Как и в предыдущем примере, этот код начинается с объявления некоторых пе­ременных и инициализации их простыми целыми значениями. Затем этот метод вызывает метод AddSpace, Отображает пользователю, какая операция сейчас будет выполнена, выполняет эту операцию и отображает пользователю ее результат. Опять-таки, единственная сложная часть здесь — это длинная конкатенация строк, отображающая пользователю значение "30 = 10 * 3".

Вот код, демонстрирующий, как происходит деление целых чисел в Java:

Public void divide (int a, int b)

{

Int c;

AddSpace("деление");

System. out. println("c = a ∕ b", ; c = a∕b;

System, out. println (c + " = " + a + " ∕ " + b) ;

)

Этот код делит 10 на 3, что дает в результате 3. Остаток при этом отбрасывается.

А вот код, показывающий, как обращаться с операцией взятия числа по модулю:

Public void modulus (int a, int b)

{

Int С;

AddSpace("остаток (модуль)");

System, out. println (,,c = А % b") ; с = А % b;

System, out. println + " = " + А + " % " + Ь) ;

)

Операция взятия числа по модулю противоположна операции деления (скорее дополнительна, а противоположна операция умножения — Прим, перев.): она воз­вращает остаток от деления. Выражение 10/3 равно 3, а выражение 10 % 3 равно 1, поскольку 10 при делении на 3 дает в результате 3 и в остатке 1. Выражение 10 % 3 обычно читается как "io Mod 3", т. е. "10 по модулю 3". Я предпочитаю первый из этих двух вариантов.

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

рис. 11.4. здесь видны результаты работы методов деления и вычисления остатка в программе mathopssimple

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

Видимо, стоит пояснить, что сложение, вычитание, умножение и деление с пла­вающей точкой на компьютере — это неточные операции. Если вы присвоите пере­менной типа float значение 0.05 и сложите ее с собой три раза, то результат не обязательно будет равен 0.15. На самом деле, вероятность получения такого резуль­тата пренебрежительно мала. Вместо этого вы, скорее всего, получите значение очень близкое, но все-таки не равное ожидаемому результату.

Рассмотрим следующий код:

Double А = 0.05;

Double b = 0;

For = 0; Х < 5; Х++)

{

B = Ь + а;

J CoinboBoxl. add Item (Double. toString (b)) ;

1

На моем компьютере он дает следующие результаты:

0.05

0.1

0.1500000000000002

0.2

0.25

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

Рубли в копейки (туда же и гривни, а левы — в стотинки) и работать с целыми ко­пейками — или же использовать специальный набор инструментов.

Типы с плавающей точкой и денежные расчеты: BigDecimaI

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

Import java. math.*;

Void jButtonl_actionPerformed (ActionEvent e)

{

BigDecimal a = new BigDecimal (0.05) ;

BigDecimal b = new BigDecimal (O. O) ; for (int x = O; x < 25; X++)

{

B = b. add(a) ;

B = b. setScale(2, BigDecimal. ROUND_HALF_EVEN);

Systern. out. println(b. toString());

}

}

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

Тип BigDecimal имеет методы add, divide, multiply, abs, timesTenToThe И compareTo, предназначенные для выполнения операций с переменными этого типа. C этим типом нельзя использовать знаки обычных арифметических опера­ций — вместо этого необходимо вызывать методы, подобные add, как показано в данном фрагменте кода. C помощью метода setScale вы можете задать количество цифр после десятичной точки, которое вы хотите хранить, и способ округления чи­сел. В число констант, задающих способ округления, входят:

round_up
round_down
round_ceiling round_floor round_half_up round_half_down round_half_even — round unnecessary —
Округление в сторону от нуля

Округление в сторону к нулю

Округление в большую сторону округление в меньшую сторону округление до ближайшего или большего округление до ближайшего или меньшего округление до ближайшего или четного округление не должно возникать

Код, показанный в последнем примере, генерирует следующие выходные данные:

0.05

0.10

0.15

0.20

0.25

0.30

0.35

0.40

0.45

0.50

0.55

0.60

0.65

0.70

0.75

0.80

0.85

0.90

0.95

1.00

1.05

1.10

1.15

1.20

1.25

Вот теперь похоже. Дополнительную информацию вы можете почерпнуть в тех­нических советах на сайте компании Sun. На время публикации книги ее можно было найти ПО Адресу Http://developer. java. sun. com/developer/JDCTechTips/ 2002∕tt0409.html*tip2.

B этом совете содержится и описание удобного типа Currency (денежный тип), введенного в JDK 1.4.0.

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

Для точной работы с большими числами можно применять и другой Тип — BigInteger.

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

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

Int Ь, с; // объявление целых чисел int а = Ь + с; // результат также целый

Соответственно, если вы объявите все переменные как double, вы получите и ре­зультат типа double.

Если вы в одном выражении используете и double, и int, то результат какой — либо из базовых математических операций будет типа double:

Int а; double Ь; double с = а + Ь;

Но если вы попробуете сделать наоборот, то получите ошибку:

Int а; double Ь; int с = а + Ь;

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

Int а; double b;

Int с = (int) (а + Ь) ;

Здесь происходит вот что: мы указываем компилятору игнорировать правила и считать, что мы знаем, что делаем. Это не фигуральный оборот — это именно то, что мы требуем от компилятора. В данном коде говорится: "Я знаю, что обычно ты указываешь здесь на ошибку, но поверь мне: я знаю, что делаю!"

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

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

Операции присваивания

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

Рассмотрим код, который уже встречался в данной главе:

Double а = 0.05;

Double b = 0;

For (х = 0; х < 5; х++)

{

Ь = b + а;

JComboBoxl. addItern(Double. toString(b));

}

Без изменения его смысла его можно переписать следующим образом’

Double а = 0.05; double b = 0;

For (int х = O; х < 5; х++)

{

B += а;

JComboBoxl. addItern(Double. toString(b));

}

В операторах в начале этого кода используется стандартная операция присваива­ния, но в середине цикла for применяется операция +=. Операция += является все­го лишь сокращением записи ь = ь + а. Другими словами, нет существенной разни­цы между записью ь = ь + аиь+=а. Существуют и другие операции того же рода: *=, /=, %= и -=.

Нет никаких причин, кроме привычки, предпочитать синтаксис а = а + 1 или а += 1. И то, и другое выражение выполняет одни и те же действия, и вы можете ис­пользовать тот стиль кодирования, который вам больше нравится.

Эти сокращенные операции присваивания унаследованы от языка С/С++. Ког­да-то разработчики компиляторов сочли, что легче оптимизировать код, записан­ный вторым способом, но те времена давным-давно прошли. Код, записанный лю­бым способом, выполняется теперь совершенно одинаково.

Резюме

В данной главе был представлен достаточно обширный материал. В частности, вы увидели, как работать с операторами for, операторами while и операторами do — while.

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

Вы увидели, как использовать операции пре — и постинкремента и декремента (++ и —), с помощью которых можно написать код вроде i++, —j. Также были крат­ко рассмотрены операции присваивания.

К примеру программы fIoatops, входящей в состоав сопровождающих материа­лов, прилагается обширный HTML-документ, который расширяет сведения, приве­денные в данной главе.

12
13
14
15
16
17
18 19

Часть III

Основы JBuiIder

В этой части

Администраторы компоновки Еще о компоновках и меню Обработка событий Возбуждение событий Переключатели и флажки

Визуальное конструирование и повторное использование Искусство работы с кнопками Создание диалоговых окон

марджи и чарли калверт

Глава 12

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *