10

10


В данном случае значение (55% match) сообщает системе тестирования, что ре¬зультаты будут заметно отличаться при разных запусках программы. В боль¬шинстве примеров книги результаты приводятся в комментариях такого вида, чтобы вы могли проверить их на правильность.



Стиль оформления программ



Согласно правилам стиля, описанным в руководстве Code Conventions for the Java Programming Languageимена классов должны записываться с прописной буквы. Если имя состоит из нескольких слов, они объединяются (то есть симво¬лы подчеркивания не используются для разделения), и каждое слово в имени начинается с большой буквы:



class А11TheColorsOfTheRainbow { // ..



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



class AllTheColorsOfTheRainbow {



int anlntegerRepresentingColors; void changeTheHueOfTheColor(int newHue) { II ...



}



// .



}



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



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



Резюме



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




Операторы

Н
а нижнем уровне операции с данными в Java осуществляются посредством операторов.



Язык Java создавался на основе С++, поэтому большинство этих операторов и конструкций знакомы программистам на С и С++. Также в Java были добав¬лены некоторые улучшения и упрощения.



Если вы .знакомы с синтаксисом С или С++, бегло просмотрите эту и сле¬дующую главу, останавливаясь на тех местах, в которых Java отличается от этих языков. Если чтение дается вам с трудом, попробуйте обратиться к мультиме¬дийному семинару Thinking in С, свободно загружаемому с сайтаwww.Mind- View.net. Он содержит аудиолекции, слайды, упражнения и решения, специаль¬но разработанные для быстрого ознакомления с синтаксисом С, необходимым для успешного овладения языком Java.



Простые команды печати



В предыдущей главе была представлена команда печати Java



System.out.println("Какая длинная команда...");



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



В главе 6 представлена концепция статического импорта, появившаяся в Java SE5, а также крошечная библиотека, упрощающая написание команд пе¬чати. Тем не менее для использования библиотеки не обязательно знать все подробности. Программу из предыдущей главы можно переписать в следующем виде:



// operators/HelloDate java import java util *.



import static net mindview util Print.*,



public class HelloDate {



public static void main(String[] args) { print("Привет, сегодня- "); print(new DateO),



}



} /* Output- (55% match)



Привет, сегодня



Wed Oct 05 14-39 36 MDT 2005



*///:-



Результат смотрится гораздо приятнее. Обратите внимание на ключевое слово static во второй команде import.



Чтобы использовать эту библиотеку, необходимо загрузить архив с приме¬рами кода. Распакуйте его и включите корневой каталог дерева в переменную окружения CLASSPATH вашего компьютера. Хотя использование net.mindview. util. Print упрощает программный код, оно оправданно не везде. Если программа содержит небольшое количество команд печати, я отказываюсь от import и за¬писываю полный вызов System.out.println().



Операторы Java



Оператор получает один или несколько аргументов и создает на их основе но¬вое значение. Форма передачи аргументов несколько иная, чем при вызове ме¬тода, но эффект тот же самый. Сложение (+), вычитание и унарный минус (-), умножение (*), деление (/) и присвоение (=) работают одинаково фактически во всех языках программирования.



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



Почти все операторы работают только с примитивами. Исключениями явля¬ются =, = = и !=, которые могут быть применены к объектам (и создают немало затруднений). Кроме того, класс String поддерживает операции + и +=.



Приоритет



Приоритет операций определяет порядок вычисления выражений с нескольки¬ми операторами. В Java существуют конкретные правила для определения оче¬редности вычислений. Легче всего запомнить, что деление и умножение выпол¬няются раньше сложения и вычитания. Программисты часто забывают правила предшествования, поэтому для явного задания порядка вычислений следует ис¬пользовать круглые скобки. Например, взгляните на команды (1) и (2):



// operators/Precedence java



public class Precedence {



public static void main(String[] args) {



int x = 1, у = 2, z = 3; // (1)



int b = x + (y - 2)/(2 + z), // (2) System out.printlnC'a = " + a + " b = " + b;



}



} /* Output a = 5 b = 1 *///.-



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



Обратите внимание на оператор + в команде System.out.println. В данном кон¬тексте + означает конкатенацию строк, а не суммирование. Когда компилятор встречает объект String, за которым следует + и объект, отличный от String, он пытается преобразовать последний объект в String. Как видно из выходных дан¬ных, для а и b тип int был успешно преобразован в String.



Присвоение



Присвоение выполняется оператором =. Трактуется он так: «взять значение из правой части выражения (часто называемое просто значением) и скопировать его в левую часть (часто называемую именующим выражением)». Значением может быть любая константа, переменная или выражение, но в качестве име¬нующего выражения обязательно должна использоваться именованная пере¬менная (то есть для хранения значения должна выделяться физическая па¬мять). Например, вы можете присвоить постоянное значение переменной:



а = 4



но нельзя присвоить что-либо константе — она не может использоваться в каче¬стве именующего выражения (например, запись 4 = а недопустима).



Для примитивов присвоение выполняется тривиально. Так как примитив¬ный тип хранит данные, а не ссылку на объект, то присвоение сводится к про¬стому копированию данных из одного места в другое. Например, если команда а = b выполняется для примитивных типов, то содержимое b просто копируется в а. Естественно, последующие изменения а никак не отражаются на Ь. Для про¬граммиста именно такое поведение выглядит наиболее логично.



При присвоении объектов все меняется. При выполнении операций с объек¬том вы в действительности работаете со ссылкой, поэтому присвоение «одного объекта другому» на самом деле означает копирование ссылки из одного места в другое. Это значит, что при выполнении команды с = d для объектов в конеч¬ном итоге end указывают на один объект, которому изначально соответствова¬ла только ссылка d. Сказанное демонстрирует следующий пример:



//: operators/Assignment java // Присвоение объектов имеет ряд хитростей import static net.mindview.util Print.*,



class Tank {



int level,



}



public class Assignment {



public static void main(String[] args) { Tank tl = new TankO. Tank t2 = new TankO, tl level = 9; t2 level = 47,



printC'l tl level " + tl level + \ t2 level " + t2 level);



tl = t2;



print("2- tl level- " + tl level +



t2.level• " + t2 level), tl.level = 27.



print("3 tl.level- " + tl level + t2.level. " + t2 level).



}



} /* Output



1 tl level. 9. t2.level. 47



2 tl level- 47. t2 level. 47



3: tl.level. 27. t2 level: 27



*/// ~



Класс Tank предельно прост, и два его экземпляра (tl и t2) создаются внутри метода main(). Переменной level для каждого экземпляра придаются различные значения, а затем ссылка t2 присваивается tl, в результате чего tl изменяется. Во многих языках программирования можно было ожидать, что tl и t2 будут независимы все время, но из-за присвоения ссылок изменение объекта tl отра¬жается на объекте t2! Это происходит из-за того, что tl и t2 содержат одинако¬вые ссылки, указывающие на один объект. (Исходная ссылка, которая содержа¬лась в tl и указывала на объект со значением 9, была перезаписана во время присвоения и фактически потеряна; ее объект будет вскоре удален сборщиком мусора.)



Этот феномен совмещения имен часто называют синонимией (aliasing), и именно она является основным способом работы с объектами в Java. Но что делать, если совмещение имен нежелательно? Тогда можно пропустить при¬своение и записать



tl.level = t2 level;



При этом программа сохранит два разных объекта, а не «выбросит» один из них, «привязав» ссылки tl и t2 к единственному объекту. Вскоре вы поймете, что прямая работа с полями данных внутри объектов противоречит принципам объектно-ориентированной разработки. Впрочем, это непростой вопрос, так что пока вам достаточно запомнить, что присвоение объектов может таить в себе немало сюрпризов.



Совмещение имен во время вызова методов



Совмещение имен также может происходить при передаче объекта методу:



// operators/PassObject java



// Передача объектов методам может работать



// не так. как вы привыкли.



import static net.mindview.util.Print.*;



class Letter { char c;



}



public class PassObject {



static void f(Letter y) { y.c = 'z';



}



public static void main(String[] args) { Letter x = new LetterO; x.c = 'a';



printCl; x.c; " + x.c); f(x);



print("2: x.c: " + x.c);



}



} /* Output 1: x.c: a 2: x.c: z */ ///



Во многих языках программирования метод f() создал бы копию своего па¬раметра Letter у внутри своей области действия. Но из-за передачи ссылки строка



у.с = 'z';



на самом деле изменяет объект за пределами метода f().



Совмещение имен и решение этой проблемы — сложные темы. Будьте очень внимательными в таких случаях во избежание ловушек.



Арифметические операторы



Основные математические операторы остаются неизменными почти во всех языках программирования: сложение (+), вычитание (-), деление (/), умноже¬ние (*) и остаток от деления нацело (%). Деление нацело обрезает, а не округ¬ляет результат.



В Java также используется укороченная форма записи для того, чтобы одно¬временно произвести операцию и присвоение. Она обозначается оператором с последующим знаком равенства и работает одинаково для всех операторов языка (когда в этом есть смысл). Например, чтобы прибавить 4 к переменной х и присвоить результат х, используйте команду х += 4.



Следующий пример демонстрирует использование арифметических опе¬раций:



//: operators/MathOps.java // Демонстрация математических операций, import java.util.*;



import static net.mindview.util.Print.*;



public class MathOps {



public static void main(String[] args) {



// Создание и раскрутка генератора случайных чисел



Random rand = new Random(47); int i, j, k;



// Выбор значения от 1 до 100: j = rand.nextlnt(lOO) + 1: printC'j : " + j): к = rand.nextlnt(lOO) + 1. printC'k : " + k): i = J + k;



printC'j + к : " + i); 1 - J - k:



printC'j - к :" + i); i = к / j,



printC'k / j : " + i): i = к * j;



printC'k * j • " + i): i = к % j;



printC'k % j . " + i). j X= k:



printC'j %/ к • " + j); // Тесты для вещественных чисел float u.v.w; // также можно использовать double v = rand.nextFloatO; printC'v . " + v); w = rand.nextFloatO; print("w : " + w), u = v + w;



printC'v + w : " + u); u = v - w;



printC'v - w : " + u). u = v * w;



printC'v * w : " + u); u = v / w;



printC'v / w : " + u): // следующее также относится к типам // char, byte, short, int, long и double: u += v:

Report Page