Скачиваний:
36
Добавлен:
05.07.2021
Размер:
2.64 Mб
Скачать

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

Блоки кода обладают дополнительными свойствами и областями применения. Но их основное назначение – создание логически неразрывных единиц кода.

ПРОБЕЛЫ

Java – язык свободной формы. Это означает, что при написании программы не нужно следовать каким-то специальным правилам в отношении отступов. Например, программу Example можно было бы написать в одной строке или любым другим способом. Единственное обязательное требование – наличие, по меньшей мере, одного пробела

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

ИДЕНТИФИКАТОРЫ

Для именования классов, методов и переменных служат идентификаторы. Идентификатором может быть любая последовательность строчных и прописных букв, цифр или символов подчеркивания и денежной единицы. Идентификаторы не должны начинаться с цифры, чтобы компилятор не путал их с числовыми константами. В Java учитывается регистр символов, и поэтому VALUE и Value считаются разными идентификаторами. Несколько допустимых идентификаторов: AvgTemp, count, a4, $test, this_is_ok. Следующие идентификаторы недопустимы: 2count, high-temp, Not/ok. Начиная с версии JDK 8, один знак подчеркивания не

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

ЛИТЕРАЛЫ

ВJava постоянное значение задается его литеральным представлением.

Вкачестве примера можно привести несколько литералов: 100, 98.6, 'X', "This is a test". Первый литерал в данном примере обозначает целочисленное значение, следующий – числовое значение с плавающей точкой, третий – символьную константу, а последний – строковое значение. Литерал можно использовать везде, где допустимо применение значений данного типа.

РАЗДЕЛИТЕЛИ

ВJava допускается применение нескольких символов в качестве

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

11

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

Таблица – Символы, допустимые в качестве разделителей

Символ

Назначение

()

Употребляются для передачи списков параметров в определениях и вызовах

 

методов. Применяются также для обозначения операции приведения типов и

 

предшествования операторов в выражениях, употребляемых в управляющих

 

операторах

{}

Употребляются для указания значений автоматически инициализируемых

 

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

 

областей действия

[]

Употребляются для объявления типов массивов, а также при обращении к

 

элементам массивов

;

Завершает операторы

,

Разделяет последовательный ряд идентификаторов в объявлениях

 

переменных. Применяются также для создания цепочек операторов в

 

операторе цикла for

.

Употребляется для отделения имен пакетов от подпакетов и классов, а также

 

для отделения переменной или метода от ссылочной переменной

БИБЛИОТЕКИ КЛАССОВ JAVA

Вприведенных примерах программ использовались два встроенных метода println() и print(). Эти методы доступны по ссылке System.out на класс System, который является стандартным Java и автоматически включается в прикладные программы. В более широком смысле среда Java опирается на несколько встроенных библиотек классов, содержащих многие встроенные методы, обеспечивающие поддержку таких операций, как ввод-вывод, обработка символьных строк, работа в сети и отображение графики. Стандартные классы обеспечивают также поддержку графического пользовательского интерфейса. Таким образом, среда Java в целом состоит из самого языка Java и набора его стандартных классов. Библиотеки классов предоставляют большую часть функциональных возможностей среды Jаvа.

КЛЮЧЕВЫЕ СЛОВА JAVA

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

Таблица – Ключевые слова Java

abstract

continue

for

new

switch

assert

default

goto

package

synchronized

boolean

do

if

private

this

break

double

implements

protected

throw

12

byte

else

import

public

throws

case

enum

instanceof

return

transient

catch

extends

int

short

try

char

final

interface

static

void

class

finally

long

strictfp

volatile

const

float

native

super

while

Кроме ключевых слов, в Java зарезервированы также слова true, false и null. Они представляют значения, определенные в спецификации языка Jаvа. Их нельзя использовать для обозначения имен переменных, классов и т.п. Рассмотрим ключевые слова Java разделённые по группам.

Примитивные типы данных: byte, short, int, long, char, float, double, boolean

Циклы и ветвления: if, else, switch, case, default, while, do, break, continue, for

Исключения: try, catch, finally, throw, throws Области видимости: private, protected, public

Объявление \ Импорт: import, package, class, interface, extends, implements, static, final, void, abstract, native

Создание \ Возврат \ Вызов: new, return, this, super Многопоточность: synchronized, volatile

Ключевые слова, которые не вошли ни в одну из групп: const, goto, instanceof, enum, assert, transient, strictfp.

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

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

инкапсуляции;

наследования;

полиморфизма, в частности, «позднего связывания».

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

куче данных (heap) и доступны по объектным ссылкам, которые, в свою очередь, хранятся в стеке (stack). Это решение исключило непосредственный доступ к памяти, но усложнило работу с элементами массивов и сделало ее менее эффективной по сравнению с программами на C++. В свою очередь, в Java предложен усовершенствованный механизм работы с коллекциями, реализующими основные динамические структуры данных. Необходимо отметить, что объектная ссылка языка Java содержат информацию о классе объекта, на который она ссылается, так что объектная ссылка — это не

13

указатель, а дескриптор (описание) объекта. Наличие дескрипторов позволяет JVM выполнять проверку совместимости типов на фазе интерпретации кода, генерируя исключение в случае ошибки. В Java изменена концепция организации динамического распределения памяти:

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

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

существуют конструкторы, но отсутствуют деструкторы (применяется автоматическая сборка мусора), не используется оператор goto и слово const, хотя они являются зарезервированными словами языка.

ОСНОВЫ КЛАССОВ И ОБЪЕКТОВ JAVA

Классы в языке Java объединяют поля класса, методы, конструкторы, логические блоки и внутренние классы. Основные отличия от классов C++: все функции определяются внутри классов и называются методами; невозможно создать метод, не являющийся методом класса, или объявить метод вне класса; спецификаторы доступа public, private, protected воздействуют только на те объявления полей, методов и классов, перед которыми они стоят, а не на участок от одного до другого спецификатора, как в С++; элементы по умолчанию не устанавливаются в private, а доступны для классов из данного пакета. Объявление класса имеет вид:

[спецификаторы] class ИмяКласса [extends СуперКласс] [implements список_интерфейсов] {

/* определение класса */

}

Спецификатор доступа к классу может быть public (класс доступен в данном пакете и вне пакета), final (класс не может иметь подклассов), abstract (класс может содержать абстрактные методы, объект такого класса создать нельзя). По умолчанию, если спецификатор класса не задан, то он устанавливается в дружественный (friendly, default). Такой класс доступен только в текущем пакете. Спецификатор friendly при объявлении вообще не используется и не является ключевым словом языка. Это слово используется в сленге программистов, чтобы как-то коротко обозначить значение по умолчанию.

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

14

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

Все классы любого приложения условно разделяются на две группы: классы — носители информации и классы, работающие с информацией. Классы, обладающие информацией, содержат данные о предметной области приложения. Например, если приложение предназначено для управления воздушным движением, то предметной областью будут самолеты, пассажиры и пр. При проектировании классов информационных экспертов важна инкапсуляция, обеспечивающая значениям полей классов корректность информации. У класса House, например, может быть поле numberWindows, значение которого не может быть отрицательным. С помощью инкапсуляции ключевым словом private закрывается прямой доступ к значению поля через объект, а метод, отвечающий за инициализацию значения поля, будет выполнять проверку входящего значения на корректность. В качестве примера с нарушением инкапсуляции можно рассмотреть класс Coin в приложении по обработке монет.

//Пример №6. Использование класса package by.bsuir.java.first; class Coin {

public double diameter; // нарушение инкапсуляции private double weight; // правильная инкапсуляция public double getDiameter() {

return diameter;

}

public void setDiameter(double value) { if (value > 0) {

diameter = value; } else {

diameter = 0.01; // значение по умолчанию

}

}

//некорректно: неправильное имя метода (это метод getWeight) public double takeWeight() {

return weight;

}

public void setWeight(double weight) { this.weight = weight;

}

}

Класс Coin содержит два поля diameter и weight, помеченные как public и private соответственно. Значение поля weight можно изменять только при помощи методов, например, setWeight().

Поле diameter доступно непосредственно через объект класса Coin. Поле, объявленное таким способом, считается объявленным с нарушением

15

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

//Пример №7. Использование класса public class Runner {

public static void main(String[] args) { Coin ob = new Coin();

ob.diameter = -0.12; // некорректно: прямой доступ ob.setWeight(100);

// ob.weight = -150; // поле недоступно: compile error

}

}

Чтобы компиляция оператора:

ob.diameter = -0.12; // некорректно: прямой доступ

стала невозможной, следует поле diameter класса Coin объявить с атрибутом доступа private:

private double diameter;

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

//Пример №8. Использование класса package by.bsuir.java.first; class Coin {

private double diameter; // правильная инкапсуляция private double weight; // правильная инкапсуляция public double getDiameter() {

return diameter;

}

public void setDiameter(double value) { if (value > 0) diameter = value;

else System.out.println("Oтрицательный диаметр!");

}

// правильное имя метода getWeight вместо имени takeWeight public double getWeight() {

return weight;

}

public void setWeight(double weight) { this.weight = weight;

}

}

16

Проверка корректности входящей извне информации осуществляется в методе setDiameter() и позволяет уведомить о нарушении инициализации объекта.

//Пример №9. Использование объектов класса Coin package by.bsuir.java.first;

class Coin {

private double diameter; // правильная инкапсуляция private double weight; // правильная инкапсуляция public double getDiameter() {

return diameter;

}

public void setDiameter(double value) { if (value > 0) diameter = value;

else System.out.println("Oтрицательный диаметр!");

}

// правильное имя метода getWeight вместо имени takeWeight public double getWeight() {

return weight;

}

public void setWeight(double weight) { this.weight = weight;

}

}

class CompareCoin {

public void compareDiameter(Coin first, Coin second) { double delta = first.getDiameter() -

second.getDiameter(); if (delta > 0) {

System.out.println("Первая монета больше второй на "

+delta);

}else if (delta == 0) {

System.out.println("Монеты имеют одинаковый

диаметр");

} else {

System.out.println("Вторая монета больше первой на "

+ -delta);

}

}

}

public class Runner {

public static void main(String[] args) { Coin coin1 = new Coin();

coin1.setDiameter(-0.11);//сообщение о неверных данных coin1.setDiameter(0.12); // корректная установка поля coin1.setWeight(150);

Coin coin2 = new Coin(); coin2.setDiameter(0.21); coin2.setWeight(170);

CompareCoin compareCoin = new CompareCoin();

17

compareCoin.compareDiameter(coin1, coin2);

}

}

Компиляция и выполнение данного кода приведут к выводу на консоль следующей информации:

Объект класса создается за два шага. Сначала объявляется ссылка на объект класса. Затем с помощью оператора new создается экземпляр объекта, например:

Coin coin1;// объявление ссылки

coin1 = new Coin();// создание объекта

Однако эти два действия обычно объединяют в одно:

Coin coin1 = new Coin();/*объявление ссылки и создание объекта*/

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

Метод compareDiameter() выполняет два действия, которые следует разделять: выполняет сравнение и выводит ответ. Действия слишком различны по природе, чтобы быть совмещенными. Естественным решением будет изменить возвращаемое значение метода на int и оставить в нем только вычисления.

public int compareDiameter(Coin first, Coin second) { int result = 0;

double delta = first.getDiameter() - second.getDiameter(); if (delta > 0) result = 1;

else if (delta < 0) result = -1; return result;

}

Формирование отчета следует поместить в другой метод другого класса.

ОБЪЕКТНЫЕ ССЫЛКИ

Java работает не с объектами, а со ссылками на объекты. Это объясняет то, что операции сравнения ссылок на объекты не имеют смысла, так как при этом сравниваются адреса. Для сравнения объектов на эквивалентность по

18

значению необходимо использовать специальные методы, например, boolean equals(Object obj). Этот метод наследует каждый класс от суперкласса Object, который находится в корне дерева иерархии всех классов. Метод equals() должен переопределяться в каждом классе для определения эквивалентности содержимого двух объектов этого класса.

//Пример №10. Использование переменных типа String package by.bsuir.java.first;

class ComparisonStrings {

public static void main(String[] args) { String s1, s2;

s1 = "Java";

s2 = s1; //две переменные ссылаются на строку "Java"

System.out.println("сравнение ссылок " + (s1 == s2));

// создание нового объекта

s2 = new String("Java");//эквивалентно s2=new String(s1);

System.out.println("сравнение ссылок " + (s1 == s2)); System.out.println("сравнение значений " +

s1.equals(s2));

}

}

В результате выполнения действия s2 = s1 получается, что обе ссылки ссылаются на один и тот же объект. Оператор «==» возвращает true при сравнении ссылок только в том случае, если они ссылаются на один и тот же объект.

Результаты работы программы:

Если же ссылку инициализировать при помощи конструктора s2 = new String(s1), то создается новый объект в другом участке памяти, который инициализируется значением, взятым у объекта s1. В итоге существуют две ссылки, каждая из которых независимо ссылается на свой объект, который никак физически не связан другим объектом. Поэтому оператор сравнения ссылок возвращает результат false, так как ссылки ссылаются на различные участки памяти. Объекты обладают одинаковыми значениями, что легко определяется вызовом метода equals().

Если в процессе разработки возникает необходимость в сравнении по значению объектов классов, созданных программистом, то для этого следует переопределить в классе метод boolean equals(Object obj) в соответствии с теми критериями сравнения, которые существуют для объектов данного типа или по стандартным правилам, заданным в документации.

19

ВЗАИМОДЕЙСТВИЕ С КОНСОЛЬЮ

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

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

//Пример №11. Взаимодействие с консолью package by.bsuir.java.first;

class ReadCharRunner {

public static void main(String[] args) { int x;

try {

System.out.println("Введите символ: "); x = System.in.read();

char c = (char) x;

System.out.println("Код символа: " + c + " = " + x); } catch (java.io.IOException e) {

System.err.println("ошибка ввода " + e);

}

}

}

Результат работы программы:

Обработка исключительной ситуации IOException, которая может возникнуть в операциях ввода/вывода и в любых других взаимодействиях с внешними устройствами, осуществляется в методе main() с помощью реализации блока try-catch. Если ошибок при выполнении не возникает, то выполняется полностью блок try{}, в противном случае генерируется исключительная ситуация, и выполнение программы перехватывает блок catch{}.

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

//Пример №12. Использование класса Scanner package by.bsuir.java.first;

import java.util.Scanner; class RunScanner {

20

Соседние файлы в папке методички для лаб