Объектно-ориентированное программирование на Java. Платформа Java SE

Текст
Читать фрагмент
Отметить прочитанной
Как читать книгу после покупки
Шрифт:Меньше АаБольше Аа

Строки и печать


Мы заинтересованы не только в работе с числами.

Нам также нужно работать с текстом.

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

Текст состоит из последовательности символов.

Один символ – это символ, который вы можете найти на клавиатуре.



Строка представляет собой последовательность символов.

Строка может состоять из нескольких символов, но она может также иметь только один символ, как в этом примере строки с пробелом.

Строка также может не содержать никаких символов.

В этом случае мы говорим о пустой строке.

Обратите внимание, что мы помещаем одиночные символы в одинарные кавычки и строки в двойные кавычки.

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

Теперь, что, если мы хотим иметь двойную кавычку в строке?

Метод, который мы используем, заключается в том, чтобы поставить escape-символ, обратную косую черту.



Здесь внешние двойные кавычки не являются частью строки.

Они просто указывают, что у нас есть строка.

Но теперь, если обратная косая черта является символом со специальным свойством, что делать, если мы хотим иметь обратную косую черту в строке?

Тогда мы тоже ставим перед ней обратную косую черту.

Теперь это объявление переменной для строки с именем s, которой мы присваиваем строку, состоящую из просто символа s.



Так что не путайте имя переменной со строкой.

Вот почему мы используем двойные кавычки.

Теперь, какие есть основные операции для строк?

Очень важной операцией является конкатенация или соединение строк.

Обратите внимание, что символ для операции конкатенации – тот же самый, что и для сложения.



Это знак плюса.

Вы должны быть осторожны, чтобы не путать число один со строкой «1» в кавычках.

В этом примере n является целым числом и s строкой.



Поэтому, если говорить n плюс n, мы складываем числа и в результате получим целое число 2.

Если, смотреть на s плюс s, мы объединяем две строки и получаем строку 11.

Интересно отметить, что разрешено писать s плюс n – строка плюс число.

Если один из операндов является строкой, другой также преобразуется в строку.

Поэтому в последнем примере целое число 1 преобразуется в строку «1»

И в результате получим строку 11.

length – это операция, которая применяется к строке и возвращает число, соответствующее количеству символов в строке.



Интересно отметить, что длина конкатенации двух строк – это сумма их длин.

С операцией substring мы можем извлечь часть данной строки.



Предположим, что у нас есть строка с этими 6 символами, Hello восклицательный знак.

Первый символ, H находится в нулевой позиции.

Второй E в позиции 1 и так далее, до позиции 5.

Таким образом, substring (2,4) означает, что мы извлекаем подстроку, которая начинается в позиции 2, L, и заканчивается в позиции до 4.

Таким образом, позиция 4 не включена.

Мы включаем символы в позициях 2 и 3, два L.

substring (0,2) выбирает два первых символа, а substring (2,6) остальные.

Также возможно написание одного аргумента в substring.

Это означает, что подстрока выбрана до конца строки.

Теперь есть много других операций для строк, таких как indexof, compareto и т. д.

Которые мы увидим позже.

Если вы хотите напечатать строку в Java, вы можете использовать оператор System.out.print.

И этот оператор принимает аргумент, который нужно напечатать.



Это может быть строка или другой тип.

System.out.println, в отличие от System.out.print, переводит печать на новую строку после печати.

Теперь надо отметить, что фактически, String не является примитивным типом данных как boolean или «int».

Вот почему вы пишете String с заглавной буквы S.

Но мы поговорим об этом в позже.

Условия if и else


Теперь поговорим об условии if.

Мы принимаем все время решения.

Если мы думаем, что пойдет дождь, мы берем зонт, прежде чем уйти из дома.

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

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

Выражения выполнялись по порядку одно за другим.

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

Давайте посмотрим пример.

Предположим, что мы хотим вычислить квадратный корень из числа.



И мы знаем, что число должно быть положительным, чтобы квадратный корень был реальным числом.

Поэтому, если нам дано отрицательное число, нам нужно сделать его положительным.

Если число положительное, нам не нужно ничего делать.

Как мы сделаем это на Java?

Ключевое слово if вводит условное выражение.

В этом примере выражение присваивания n равно минус n, выполняется только в том случае, если выполняется условие n меньше 0.

Если это условие ложно, ничего не делается.

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

Мы просто помещаем выражения между фигурными скобками, делая их блоком.



Если условие ложно, ни одно из выражений этого блока не выполняется.

В общем, рекомендуется писать фигурные скобки, даже если при этом условии должно быть только одно выражение.

Логическое выражение для условия должно всегда находиться между круглыми скобками.

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

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



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

Это одна из структур, контролирующих поток выполнения программы.

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

В зависимости от некоторых условий мы идем так или иначе.

Как мы это выразим в Java?

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

Если условие не выполняется, ничего не делается.

Теперь мы хотим выполнить альтернативное выражение в этом случае.

Здесь мы видим простой пример.



x присваивается минус n, если n отрицательно.

Если это не так, x присваивается n.

Таким образом, существует два альтернативных блока выражений.

Тот, который выполняется, если условие истинно.

И тот, который выполняется, если условие ложно.

Этот блок записывается после ключевого слова else.

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

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

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

Например, давайте напишем условное выражение внутри другой ветви.

Новое условие проверяет, равно ли n 0.



Если это так, мы что-то делаем.

Иначе мы делаем что-то еще.

В целом, теперь у нас есть три случая, из которых только один выполняется.

Здесь показан пример с 4 случаями.


Выражение switch


Для исследования проблемы else, давайте взглянем на эти два блока кода.

 

Единственное различие между двумя блоками является идентификация принадлежности else.



И здесь могут быть два вопроса.

Первый, к какому выражению if выражение else принадлежит?

Второй вопрос, это то, каким будет значение после оценки if выражения?

Идентификация фактически не влияет на то, как компилятор будет интерпретировать блоки кодов.

В Java, else выражение соотносится с ближайшим возможным if выражением.

В этом случае, это проверка значения b.

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



Результат оценки блока кода приведет к установке значения a = 30 в конце выполнения.

Мы можем также использовать комбинацию if-else if.

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



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

Сравните со случаем, когда else убрано.



В этом случае поток выполнения прерываться не будет.

В то время как if выражение позволяет выбрать из двух возможных путей, switch выражение позволяет более двух путей выполнения.

Вот диаграмма для иллюстрации потока управления switch выражения.



И вот синтаксис switch выражения.

Синтаксис switch выражения начинается с ключевого слова switch.



Выражение switch может иметь тип char, byte, short или int, и String.

Значения case value1, value2 и т.д., должны быть того же типа, что и выражение switch.

Ключевое слово break используется для выполнения switch выражения.

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

Наконец, есть опция по умолчанию.

С ключевым словом default, эта часть кода будет выполняться только, когда никакие другие случаи не соответствуют.

Теперь посмотрим пример с использованием switch выражения.

Угадайте, что произойдет, если убрать все ключевые слова break?



Это будет то же самое, как если в примере if-else if убрать ключевое слово else.

На самом деле, все, что может быть сделано с помощью switch выражения, также может быть сделано с помощью if-else выражения.

Таким образом, в отличие от операторов if и else оператор switch может иметь несколько возможных путей выполнения.

И switch работает с примитивными типами данных char, byte, short или int и строками.

Решение о том, следует ли использовать операторы if и else или оператор switch, зависит от выражения, которое тестирует оператор.

Операторы if и else могут тестировать выражения на основе диапазонов значений или условий, тогда как оператор switch проверяет выражения, основанные только на одном перечисляемом значении.

Тернарный оператор


Представьте, что мы хотим вычислить абсолютное значение числа.

Это число без знака.

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



Таким образом, abs 3 равна 3, а abs -3 также равно 3.

Давайте определим проблему более формально.

Если условие x больше 0 вычисляется как true, тогда вычисление abs x совпадает с вычислением x.



Если условие x больше 0 вычисляется как false, тогда вычисление abs x – это то же самое, что и вычисление значения минус x.

Теперь мы хотели бы написать выражение, которое вычисляет абсолютное значение.

Мы бы решили проблему, если бы у нас была функция f с тремя аргументами.

Первый аргумент – это условие.



Второй аргумент – это выражение для вычисления в случае true.

И третий аргумент – это выражение для вычисления в случае false.

В Java эта функция существует, называется она тернарный оператор, и имеет определенный синтаксис.

Здесь используется знак вопроса между условием и выражением для случая true и двоеточие между выражением для случая true и выражением для случая false.

В этом примере, если условие истинно, оператор выдает 1.



Если условие ложно, оператор выдает 2.

Основным типом данных в условных выражениях является тип boolean, который имеет два значения: true и false.

Но существуют ли в наших условных выражениях if else только два возможных случая?

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

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



Поэтому, на самом деле, у нас есть три случая, это true, false и undefined.

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

Для логических выражений это означает, что у нас есть три возможных случая – true, false и undefined.

И это отличается от традиционной математики, где мы обычно имеем только истину и ложь.

Теперь, давайте немного вспомним о возможностях, которые мы видели.

Здесь, слева, у нас есть условное утверждение, где, в зависимости от значения булевой переменной b, мы присваиваем m или n переменной x.



С другой стороны, у нас есть тройной оператор, который позволяет писать логические выражения.

Оба сегмента кода эквивалентны.

Теперь рассмотрим этот пример.

Представьте, что у нас есть булево значение b и что выражение сравнивает b с true.



Это может быть явно упрощено до b, так как если b истинно, b == true, вычисляется как true.

И если b является ложным, b == true, вычисляется как false.

И если b не определено, выражение b == true также не определено.

Так почему бы не написать более простую версию, просто b как условие?

Аналогично вы можете поступить, если мы имеем выражение b == false.



Вы можете выбрать более простую версию, не b.

И еще вы можете написать b как условие, и поменять операторы S1 и S2.

Здесь у нас есть другое выражение.



Давайте проанализируем его.

Здесь, если b не определено, результат не определен.

Если b истинно, результат будет истинным.

И если b является ложным, результат будет ложным.

Мы рассмотрели все возможные значения b и всего выражения

И мы видим, что они имеют одинаковые значения, что они эквивалентны.

Поэтому вместо всего этого выражения мы можем написать только b.

Та же самая ситуация будет с выражением не b.

Теперь, давайте посмотрим выражение b? c: false.



Если b не определено, все выражение не определено.



Если b истинно, результат равен c.

Однако, если b является ложным, результат будет ложным.

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

Это эквивалентно логическому оператору и.

И наоборот, выражение b? true: c эквивалентно логическому оператору или.


Циклы while и for


Давайте представим, что мы хотим разделить целое число m на другое целое число n.

И мы хотим получить результат целочисленного деления, то есть самое большое количество раз, которое n вписывается в m.



Например, целочисленное деление 7 на 2, равно 3, потому что 2 по 3 раза, это 6.

Остаток равен 1.

И представьте себе, что у нас нет встроенной операции, которая выполняет эту операцию для нас.

Поэтому нам нужно сделать повторяемые вычитания.

И если нам удастся вычесть 2 из 7 три раза, это означает, что целочисленное деление равно 3.

Целочисленное деление y и целочисленный остаток x соответствуют формуле, m равно y умножить на n плюс x.

Предположим, что нам даны целые числа m и n.

А в x сохраняется оставшееся значение после вычитаний.



Итак, давайте начнем с x равно m.

y содержит результат целочисленного деления.

Мы инициализируем y 0 и приращиваем y на 1 каждый раз, когда мы вычитаем n из x.

И мы продолжаем вычитать n из x, пока x не меньше n.

Если x больше или равно n, мы вычитаем n из x и увеличим y на 1.

Таким образом, эта программа делает то, что мы хотим, но тут есть проблема.

Мы не знаем, сколько операторов if мы должны добавить.

Потому что это зависит от фактических значений m и n.

Например, с 7 и 2, это будет три выражения if.

При других входных данных это должно быть другое число if выражений.

В Java эту проблему решает оператор while.

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



Но теперь у нас есть одно большое преимущество.

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

Но теперь вы должны быть очень осторожны при написании условия while.

Потому что есть опасность войти в бесконечный цикл, если условие while никогда не прекратится.

Преимущество цикла while заключается в том, что нам не нужно заранее знать, сколько раз мы должны что-либо повторять.



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

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

Это легко реализовать подсчетом.

Хитрость заключается в том, чтобы ввести счетчик.

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



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

Здесь мы начинаем с 0 и заканчиваем 3. И шаг 1.

 

Поэтому мы выполняем четыре итерации для i равного 0, 1, 2 и 3.

Теперь, помимо подсчета, мы можем захотеть что-то сделать в теле цикла.

В этом случае предположим, что у нас есть другая переменная, n, которую мы хотим умножать на 2 при каждой итерации.



Так как такого рода подсчет используется часто, в Java для этого есть специальная конструкция.

А именно, цикл for.

Этот цикл объединяет три важных момента для переменной счетчика:



Ее инициализацию, условие остановки, и выражение обновления.

Имейте в виду, что обновление выполняется после того, как выполняется тело цикла, а не раньше.

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

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

Но это хорошая практика, чтобы всегда писать их.

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



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

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

И в Java есть именно такой цикл: do-while.

Этот цикл всегда выполняет тело цикла хотя бы один раз, так как его условное выражение проверяется в конце цикла.

В приведенном примере тело цикла выполняется до первой проверки условия завершения.

Мы уже видели оператор break в выражении switch.



Но оператор break также может прерывать любой цикл.

Предположим, у вас есть цикл.

И иногда желательно немедленно завершить цикл, не проверяя условие.

В таких случаях используется оператор break.

Оператор break немедленно завершает цикл, и управление программой переходит к следующему выражению, следующему за циклом.

Оператор break почти всегда используется вместе с выражением if else.

Также иногда желательно не прервать цикл, а пропустить код тела цикла и перейти к следующей итерации.



Оператор continue пропускает текущую итерацию цикла и когда выполняется оператор continue, управление программой переходит к концу цикла.

Затем проверяется условие, которое управляет циклом.

Оператор continue также почти всегда используется вместе с выражением if else.

Массивы


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



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

Ячейки обычно обозначаются последовательными номерами.

Ячейки или шкафчики могут быть разного размера.

В программировании мы видели переменные, которые позволяют хранить значения.

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

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

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

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

Как нам к этим переменным обращаться?

Мы привыкли свободно выбирать имена переменных.



И таким же образом мы можем дать имя массиву переменных.

Для обозначения местоположения одной переменной используется индекс.

Так, например, мы могли бы назвать массив a.

Предположим, что у него четыре элемента в четырех позициях.

Мы будем ссылаться на каждую позицию, добавляя индекс в квадратные скобки.

Обратите внимание, что мы начинаем с индекса 0 и увеличиваем его на единицу.

Здесь мы видим примеры массивов.



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

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

Надо помнить, что есть два шага при работе с массивами. Объявление массива и его создание.



Элементы в массиве можно получить с помощью индекса.

Мы не должны путать значение элемента с его индексом.

Еще одна вещь, которую следует помнить, это то, что первым элементом массива является элемент с индексом 0.

Таким образом, индексы начинаются с 0 и до длины массива минус 1.

Мы объявляем массив, указывая тип элементов, затем открываем и закрываем квадратные скобки, и затем указываем имя, которое мы выбрали для нашего массива.

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

Мы также можем сделать это вместе: объявить и создать массив в одной строке.

Теперь мы можем хранить значения в разных позициях.

Как мы сохраняем значения?

Мы используем оператор присваивания, как раньше мы использовали его для переменных.



Имя массива с индексом используется, как мы раньше использовали идентификаторы переменных.

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

Обратите внимание, что в этом случае нам не нужно писать ключевое слово «new».

Теперь, если строки – это упорядоченные последовательности символов, вопрос, является ли строка и массив символов одним и тем же.

Это не так, хотя можно конвертировать одно в другое.



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

Здесь ответ да.

Таким образом, мы получаем то, что мы называем двумерными массивами.



Но возможны и многомерные массивы.

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

И длина фиксируется при создании массива.

И элементы массива могут быть массивами.

Массивы и циклы for имеют нечто общее.

Массив состоит из последовательности данных, а цикл for выполняет выражения последовательно несколько раз подряд.

Здесь мы видим массив с четырьмя целыми числами от 0 до 3.



И ниже приведена структура цикла for, которая повторяет выражения четыре раза.

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

Например, если применить операцию возведения в степень 2 к целому числу 3, получим 9.



Теперь представьте, что мы хотим применить эту операцию ко всем целым числам в массиве.

Цикл for поможет нам последовательно брать все значения в массиве и возводить их в степень 2, начиная с индекса 0 до индекса 3.

Другой пример – сложить все числа в массиве.



Если вы хотите сделать это для любой длины массива, используйте x. length вместо 4.



Перебор элементов массива в цикле for, начиная с индекса 0 до длины массива, настолько распространен, что для этого существует специальный цикл for.



В этом цикле for мы можем проинструктировать переменную elem последовательно использовать все элементы массива.

Купите 3 книги одновременно и выберите четвёртую в подарок!

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

  1. Нажмите на многоточие
    рядом с книгой
  2. Выберите пункт
    «Добавить в корзину»