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

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

https://century-arch.ru/proizvodstvo/programmirovanie/azy-programmirovaniya.html

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

https://century-arch.ru/proizvodstvo/programmirovanie/kakoy-yazik-programmirovaniya-uchit-pervim.html

1. Целочисленный тип и тип с плавающей запятой

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

1.1 Основная часть

Типы данных, такие как целочисленный тип и тип с плавающей запятой, состоят из битов(bit). Бит состоит из одного знака. Этот знак может быть 0 или 1. Байт(byte) состоит из 8 битов. Байт представляет собой абстракцию, понятную для человека, которая сама по себе представляет простой набор из 8 битов.

Целочисленные типы и типы с плавающей запятой состоят из набора битов, количество которых в них отличается от платформы к платформе.

Целочисленный тип представляет собой число в определённом диапазоне, например, от -128 до 127. Или, например, от 0 до 255.

Тип с плавающей запятой, представляет собой число с дробной частью, например, 0,12345 или 1,23456 или 1234,56. Тип с плавающей запятой, как целочисленный тип, ограничен диапазоном, но также он ограничен количеством знаков, которое у него всегда одинаковое. То есть, если число 1 поместить в тип с плавающей запятой и вывести этот тип на дисплей со всеми содержащимися в нём знаками, на дисплее отобразится число 1.00000, которое дополнено нулями, так как количество знаков в типе с плавающей запятой постоянно и зависит от реализации этого типа на определённой платформе. В нашем случае число знаков 6. То есть, если мы поместим в наш тип число, которое содержит меньше знаков, оно дополнится, а если больше, тогда укоротится. Помещаем в наш тип число 123,4567, которое укоротившись становится 123,456.

Этот тип называется типом с плавающей запятой, потому что запятая как бы плавает.

1.23456
12.3456
123.456
1234.56
12345.6
1234.56
123.456
12.3456
1.23456

1.2 Дополнительная часть

Помимо типа байт есть другие фундаментальные типы данных. Они называются слово (word), двойное слово (double word), четверное слово (quad word) и двойное четверное слово (double quad word). Слово состоит из двух байтов, двойное слово из двух слов, четверное слово из четырёх слов, соответственно, двойное четверное слово из двух четверных слов.

Фундаментальные типы представлены в двоичном формате, то есть из набора битов. Младшие биты находятся справа, а старшие слева. То есть в числе в двоичном формате 00000001 первым битом является самый правый бит, который содержит 1. Он является самым младшим. В числе в двоичном формате 10000000 восьмой бит, который находится слева и содержит 1, является самым старшим.

В процессорах, на физическом уровне, используется двоичная система, но в документациях и подобном для лучшего понимания человеком и для краткости, в основном, используются также восьмеричная, десятичная и шестнадцатеричная системы. Наибольшее предпочтение отдают шестнадцатеричной системе счисления. В двоичной используются цифры 0 и 1. В восьмеричной от 0 по 7. В десятичной от 0 по 9. В шестнадцатеричной от 0 по 9 и цифры A, B, C, D, E, F, которые нужны, чтобы представлять собой цифры 10, 11, 12, 13, 14, 15.

Перевод в десятичную систему счисления

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

Пример для двоичной системы счисления.

Получается число 19 в десятичной системе счисления.

Пример для восьмеричной системы счисления.

Получается число 2033 в десятичной системе счисления.

Пример для шестнадцатеричной системы счисления.

Получается число 1112701 в десятичной системе счисления.

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

11111111 == 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1

Числа могут быть без знака(unsigned) и со знаком(signed). У чисел со знаком старший бит отвечает за знак + или -. Если старший бит равен 0, тогда числа положительные. Но если 1, тогда числа отрицательные и все остальные биты в них инвертированы. То есть значат противоположное. 1 значит 0, а 0 значит 1. Чтобы в числах со знаком не было отрицательного нуля, отрицательные числа смещаются на -1. То есть, чтобы привести отрицательное число 11101001 к десятичной системе счисления, отбрасываем старший разряд, который служит для обозначения знака. В нашем случае это 1, что значит, что число отрицательное. После отброса этого разряда получается число 1101001, в котором теперь инвертируем биты. Получается число 0010110 равное -22, к которому применяем смещение -1. В результате получается число -23.

Числа с плавающей запятой

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

Числа с плавающей запятой бывают четырёх типов. Половинной точности(half-precision, состоящий из 16 бит), одинарной точности(single-precision, состоящий из 32 бит), двойной точности(double-precision, состоящий из 64 бит), двойной расширенной точности(double-extended precision, состоящий из 80 бит). В типе с половинной точностью старшие 5 бит отвечают за положение запятой, остальные 11 бит за число. В типе с одинарной точностью старшие 8 бит отвечают за положение запятой, остальные 24 бита за число. В типе с двойной точностью старшие 16 бит отвечают за положение запятой, остальные 53 бита за число. В типе с двойной расширенной точностью старшие 16 бит отвечают за положение запятой, остальные 64 бита за число. По стандарту, к битам, отвечающим за положение запятой, применяется смещение. Смещение у битов, отвечающих за положение запятой, типа с половинной точностью равно -15. Смещение у битов, отвечающих за положение запятой, типа с одинарной точностью равно -127. Смещение у битов, отвечающих за положение запятой, типа с двойной точностью равно -1023. Смещение у битов, отвечающих за положение запятой, типа с двойной расширенной точностью равно -16383.

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

2. Разбор синтаксиса и некоторые общие сведения

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

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

Максимально упрощённо процессор представляет собой электронное устройство, к которому подключаются прямо или через дополнительную аппаратуру устройства ввода, такие как клавиатура и т.п., устройства вывода, такие как дисплей, устройства хранения информации. В общем, другие электронные устройства. Реализаций архитектур процессоров очень много. Опять же очень грубо, в процессоре есть аккумулятор, то есть место, в котором может храниться переменная, которая представляет собой фундаментальный тип. Также процессор содержит в себе реализации инструкций или по-другому команд. Используя инструкции можно сказать процессору взять из памяти процессора (регистры), оперативной памяти, или с внешнего носителя переменную и поместить её в аккумулятор. Или взять другую переменную и сложить её с переменной в аккумуляторе. Или переменную из аккумулятора поместить в память. Инструкций также очень много.

Из этих команд можно составить программу, но составление из таких команд большой программы невозможно, потому что она будет непонятна человеку, и никто не сможет её сопровождать. Чтобы решить эту проблему, начали объединять инструкции в функциональные блоки. После этим наборам инструкций дали имена и написали программу, которая считывает эти имена и переводит их в инструкции процессора. Такие программы называются компиляторами. Всё это безобразие росло и усложнялось, из именованных наборов получились настоящие языки программирования, компиляторы стали намного сложнее.

Первым по-настоящему хорошим языком программирования был C. Из него развился C++.

Java

Следующим прорывом стал язык Java. Он должен был решить проблему портируемости программ на разные архитектуры процессоров. Проблема была в том, что компиляторы переводили код с определённого языка программирования под определённую архитектуру, так как архитектуры процессоров кое в чём отличаются. Если хотелось запустить программу на другом процессоре, её приходилось перекомпилировать под эту архитектуру процессора. В Java вместо этого использовалась программа, которая переводила код с языка программирования в промежуточный код, который понимала эта программа, а уже после могла перевести этот код в инструкции процессора, по мере необходимости. Из-за этого код, написанный однажды, можно было использовать на всех архитектурах, на которых находилась программа Java, просто скомпилировав его в байт код, то есть промежуточный код, который понимали программы Java на любой архитектуре, на которую они были портированы. Если точнее, её назвали Java Virtual Machine или JVM. Именно с этой программой (8 версии) и с этим языком программирования, названным Java, мы будем работать.

Разбирать будем следующий код.

class myClass {
	public static void main(String [] args){
		int value = 2;
		value = 1;

		String myString = "Hello my ";

		System.out.println(myString + value + " world.");
	}
}

Этот код необходимо поместить в файл с расширением java. Можно создать простой текстовый файл и поменять его расширение с txt на java. Имена класса и файла должны совпадать.

Компиляция

Чтобы скомпилировать эту программу в промежуточный код, который также называется байт-код, необходимо установить Java Development Kit или JDK, который содержит JVM и дополнительные классы, которые упакованы в пакеты. Речь о пакетах пойдёт позже.

Далее необходимо создать системную переменную JAVA_HOME, которая содержит путь нахождения папки JDK, и после в переменную PATH прописать путь %JAVA_HOME%\bin.

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

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

Теперь нужно открыть командную строку, перейти в папку с нашим файлом и ввести команду javac myClass.java, которая скомпилирует исходный код в байт-код и поместит его в файл myClass.class. Чтобы после запустить эту программу, в командной строке введите java myClass. JVM переведёт байт-код в инструкции процессора. После запуска программы в командной строке появится текст

Hello my 1 world.

и программа завершится.

Разбор синтаксиса

Теперь разберём синтаксис языка на примере этой программы.

Так как Java объектно-ориентированный язык программирования, в нём всё является объектом.

class myClass {

Сначала мы создаём класс. Класс — это описание объекта, но не сам объект. Позже с помощью класса можно создать объект. Когда пишется программа, состоящая из одного класса, из него не создаётся объект, а вместо этого в нём вызывается статический метод

	public static void main(String [] args){

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

Метод main вызывается первым в каждом проекте до создания любых объектов, поэтому он статический.

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

Подробный разбор

Теперь разберём её подробнее.

Программа начинается с объявления класса. Для этого указываем его тип, то есть class, и затем его имя — myClass. После объявления класса идёт его тело, которое обозначается открывающейся и закрывающейся фигурными скобками. { и }. Тела класса и метода похожи на области видимости. Разберём области видимости на другом примере. Области видимости также обозначаются фигурными скобками, но они существуют сами по себе.

{
	int a;
	int b = 4;
	{
		int c = 5;
		b = c + 1;
	}
}

Области видимости

В этом примере одна область видимости находится в другой. В областях видимости находятся переменные a, b и c. Чтобы объявить переменную, нужно написать её тип, в этом случае стандартный тип int(стандартные типы мы изучим в следующем уроке), потом имя, например, a. Далее нужно поставить ;, чтобы указать, что выражение завершено. Также переменной можно присвоить значение. Для этого после имени переменной необходимо поставить знак присвоения, в Java это =, потом ввести значение. После нужно завершить выражение знаком ;. Значение можно присвоить при объявлении переменной или после. Область видимости, в которой находятся переменные a и b, не может использовать переменную c, потому что переменная с в другой области видимости — внутренней. Но область видимости, в которой находится переменная c, может использовать переменные a и b, потому что область видимости с этими переменными — внешняя. То есть, внутренняя область видимости может использовать ресурсы внешних, но не наоборот. Разберём очень примерный и не точный, но простой для понимания и достаточный для нашей цели, пример принципа действия. Фигурные скобки показывают JVM, что есть две области видимости, и одна входит в другую. В внешней, следуя указаниям, JVM создаёт переменные a и b, a присваивается значение по умолчанию, то есть 0, а b присваивается число 4. Далее во внутренней области видимости JVM создаёт переменную c, которой присваивается число 5. Далее b присваивается переменная c плюс число 1, то есть переменной b присваивает число 6. На этом внутренняя область видимости заканчивается и JVM удаляет все объявленные в ней объекты, то есть удаляется переменная c, но переменные a и b всё ещё существуют. Следующим шагом JVM удаляет и их, так как внешняя область видимости заканчивается немногим позже.

Но в отличии от областей видимости, тела методов и классов работают иначе.

Тела методов и классов

class anotherClass(){
	int a;
	int b = 2;
}

Тела классов можно представить, как контейнеры, в которых что-то хранится. То есть, если из этого класса создать объект (создание своих объектов из классов и работу с ними будем разбирать в другом разделе), тогда получится объект, который хранит переменные a и b.

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

Основной пример

Вернёмся опять к основному примеру.

class myClass {

Мы создали класс с именем myClass.

	public static void main(String [] args){

В теле класса мы создали метод main, который служит точкой входа в программу.

Объявление методов

Теперь разберём объявление методов на этом примере.

private static int myMethod(int a, int b){
	int c = 6;
	return a + b + c;
}

Ключевое слово private говорит о том, что метод может вызываться только в классе, в котором он находится. Если бы на его месте было public, тогда его можно было бы вызывать вне его класса. Если этих ключевых слов нет, метод можно вызывать из любого класса в текущем пакете. Пакеты мы разберём позже. Ключевое слово static, означает, что метод статичен. Если оно отсутствует, метод не статичен. Далее идёт тип метода. В нашем случае это int, что значит, что этот метод при вызове возвращает значение с типом int. Метод может ничего не возвращать, а производить иные действия внутри себя. Для этого нужно указать тип void. Тип void говорит, что метод ничего не возвращает. Внутри метода возврат значения осуществляется с помощью ключевого слова return, после которого следует выражение, результатом которого должен быть тип, который должен вернуть метод. Далее идёт имя метода, после которого в круглых скобках объявляются стандартные переменные или объекты, называемые параметрами, которым мы сможем передать переменные или объекты, называемые аргументами, при вызове метода, и которые используются в нём.

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

Вызов нашего метода может выглядеть так.

int c = 6;
int z = 6;
z = z + myMethod(c, 12);

В этом примере мы объявляем переменные c и z, присваиваем им значение 6. Далее мы снова присваиваем z значение, которое является результатом выражения, где берётся значение переменной z равное 6 и складывается с значением, которое возвращается из нашего метода, то есть 24. Результатом выражения будет число 30. Оно то и присвоится z.

При вызове метода, мы присваиваем его параметрам наши значения, то есть переменную c равную 6 и число 12, а после метод возвращает результат.

Основной пример

Опять вернёмся к основному примеру.

	public static void main(String [] args){

В теле класса мы создали метод main, который служит точкой входа в программу.

Этот метод публичный, статичный, ничего не возвращает, его имя main, и он принимает аргумент, который должен быть массивом типа String, в параметр с именем args. Массивы мы будем рассматривать в другом разделе. В нашем примере этот параметр не используется и рассматривать его мы пока не будем. Так как метод main всегда вызывается первым, он отличается от всех других методов и обладает нестандартными свойствами. Поэтому его параметру args можно передать аргумент, а можно и не передавать, как в нашем примере. Идём далее.

		int value = 2;
		value = 1;
		
		String myString = "Hello my ";

Мы создаём переменную value и инициализируем её значением 2. После ей же просто так присваиваем значение 1. Потом создаём переменную другого стандартного типа String с именем myString. Этот тип хранит текст. Далее мы присваиваем нашей переменной текст Hello my . В исходном коде текст заключается в двойные кавычки, чтобы компилятор мог понять, что это текст.

		System.out.println(myString + value + " world.");

Обращение к библиотекам JDK

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

Мы обращаемся к методу println из класса System. Класс System находится в пакете Java.lang. Этот пакет неявно добавляет к любой программе Java, поэтому его можно не добавлять самим. Как добавлять стандартные пакеты мы разберём в другом разделе. Чтобы обратиться к статическому методу класса, нужно написать имя класса, поставить точку, которая указывает на то, что мы обращаемся к его членам, и ввести имя метода, поставить круглые скобки и точку с запятой. Если у метода есть параметры — передать в них аргументы. Чтобы обратиться к объекту, нужно сделать тоже самое, но написать не имя класса, а имя ссылки на этот объект. Пока без подробностей, так как разберём работу с объектами позже. В нашем примере мы обращаемся к классу System, через точку обращаемся к потоку вывода out, который является членом класса System и выводит информацию на консоль, и опять через точку обращаемся к его методу println, в который отправляем следующее выражение

		myString + value + " world."

Приведение типов и завершение программы

В Java существует механизм, называемый неявным приведением типов. То есть, если в выражении участвуют переменные, типы которых int и те целочисленные переменные, у которых диапазон значений меньше типа int, например, тип short, тогда все типы приводятся к тому типу, диапазон которого всех больше, то есть int. Также, если в выражении участвуют переменные с типами, у которых диапазон меньше, чем у типа int, выражение всё равно приводится к типу int. Но при сложении стандартных типов с типом String, эти типы преобразуются в тип String. В нашем выражении из переменной myString и строки, которая образовалась из значения value (то есть значение переменной value преобразовалось в строку), создаётся новая строка.

Далее из этой новой строки и строки » world» создаётся другая строка, которую возвращает выражение, и которая становится аргументом метода println и передаётся в его параметр. Метод println выводит этот параметр, содержащий текст «Hello my 1 world.», на консоль и переводит курсор на новую строку.

	}
}

Фигурные скобки указывают на конец метода main и нашего класса. На этом наша программа заканчивается.

Программа помещается в несколько строк, но Java позволяет нам уместить её и в одну строку, главное, чтобы «слова» отделялись друг от друга, как минимум, одним разделителем, например, пробелом.

3. Примитивные типы данных и объект String. Передача по значению и по ссылке

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

Тип boolean

boolean. 1 бит. Служит для определения истинности. Ему можно присвоить true или false. Значение по умолчанию false;

boolean isAlive = true;

Как было написано в прошлом разделе, в Java знак = (то есть оператор) значит присвоить. Для проверки равенства служит другой оператор. Это логический оператор ==.

С помощью него типы boolean можно проверять на равенство.

boolean b1 = true;
boolean b2 = false;
boolean b3 = b1 == b2;

Так как b1 не равен b2, выражение вернёт false, которое присвоится b3.

Тип byte

byte. 8 бит. Целочисленный тип. Значение по умолчанию 0.

byte value2 = 1;

Тип short

short. 16 бит. Целочисленный тип. Значение по умолчанию 0.

short value3 = 1;

Тип int

int. 32 бит. Целочисленный тип. Значение по умолчанию 0.

int value4 = 1;

Тип long

long. 64 бит. Целочисленный тип. Значение по умолчанию 0.

long value5 = 1;

Тип float

float. 32 бит. Тип с плавающей запятой. Значение по умолчанию 0.0. После цифры необходимо написать f, чтобы компилятор понял, что тип float. Иначе он примет его за double.

float value6 = 1.0f;

Тип double

double. 64 бит. Тип с плавающей запятой. Значение по умолчанию 0.0.

double
value7 = 1.0;

Тип char

char. 16 бит. Целочисленный тип. Значение по умолчанию 0. Необходим для хранения символов. Так как символы - те же цифры, пример ниже, в котором переменной value7 присваивается символ a (чтобы компилятор понял, что это символ, он с двух сторон окружается одинарными кавычками)

char value8 = 'a';

можно записать и так

char value8 = 61;

Тип String

Также существует девятый стандартный тип, который называется String. В отличии от других типов он не является примитивным. Он объект. Но создаётся как примитивный тип. Ему присваивается текст. Текст заключается в двойные кавычки.

String value9 = "My text.";

При участии в выражении переменных разных типов, переменная меньшего типа преобразуется в переменную большего типа, с которым она взаимодействует. Но тип boolean не преобразуется ни в один другой примитивный тип. При взаимодействии с типом String, все другие примитивные типы, даже boolean, преобразуются в него. Примитивные типы передаются по значению. То есть, при использовании такой переменной в выражении или присвоении её другой переменной, в выражение или в переменную передаётся копия этой переменной. Объекты передаются по ссылке. То есть, при создании объекта, переменной передаётся ссылка на объект, которая хранит местоположение объекта в памяти.

String value9 = "My text.";

Здесь создаётся переменная value9, которая способна хранить ссылку типа String, которой передаётся ссылка на объект String. Ссылки также, как примитивные типы, передаются по значению. То есть, если мы сделаем так

String value9 = "My text.";
String value10 = value9;

в переменную value10 передастся копия ссылки, которая хранится в переменной value9, которая указывает на объект String.

4. Операторы и их приоритет

Все операции в выражениях осуществляются с помощью операторов. Ниже перечислены некоторые из них и их приоритет в выражении. Приоритет значит, что одни операторы производят операции раньше других. Например, оператор * всегда будет срабатывать раньше оператора +. Операторы с высшим приоритетом находятся сверху, с низшим снизу. Если операторы находятся на одной строке, это значит, что приоритет у них равный и порядок вычисления при их использовании в выражении выберет JVM.

value - переменная, необходимая для примера.

value++ value--
++value --value +value -value ~ !
* / %
+ -
<> >>>
 = instanceof
== !=
&
^
|
&&
||
? :
= += -= *= /= %= &= ^= |= <>= >>>=

Разберём некоторые из них.

value++;
value--;

Увеличивают или уменьшают переменную на 1 и возвращают неизменённое значение.

++value;
--value;

Увеличивают или уменьшают переменную на 1 и возвращают изменённое значение.

<= >=

Меньше либо равно, больше либо равно.

== !=

Операторы равно, не равно.

=

Присвоить.

Это выражение

value = value + 5;

с помощью этого оператора += можно записать так

value += 5;

5. Ключевые слова

В Java есть ключевые слова, которые нельзя использовать как идентификатор(например, название переменной). Ниже список этих слов.

abstract
assert
boolean
break
byte
case
catch
char
class
const
continue
default
do
double
else
enum
extends
final
finally
float
for
goto
if
implements
import
instanceof
int
interface
long
native
new
package
private
protected
public
return
short
static
strictfp
super
switch
synchronized
this
throw
throws
transient
try
void
volatile
while

6. Массивы

Массив представляет собой множество одного типа. Чтобы создать массив, например, типа int с 10 элементами в нём, необходимо написать такой код

int[] myArray = new int[10];

Создался массив с десятью элементами в нём. Чтобы обратиться к элементу массива, необходима написать такой код

int value;
value = myArray[0];

Здесь мы обращаемся к первому элементу массива, но пишем цифру 0, потому что элементы массива начинаются с нуля. То есть в выражении

myArray[9] = 17;

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

int[][] myArray2 = new int[10][18];

Этот массив можно представить, как одномерный массив, десять элементов которого вмещают другие одномерные массивы, которые содержат по 18 элементов типа int. В принципе, можно объявлять массивы любой размерности.

int[][][] myArray3 = new int[10][18][5];

Почему массивы создаются так? Потому что синтаксис такой.

7. Использование стандартных пакетов. Создание объектов

Создаём два новых класса. Класс myClass(можно просто изменить старый)

import java.util.Random;

class myClass {
	public static void main(String [] args){
	
	anotherClass object0 = new anotherClass();
	anotherClass object1 = new anotherClass(9);
	
	System.out.println(object0.a);
	System.out.println(object1.a);
	
	System.out.println(object0.addition(8, 10));
	
	Random random0 = new Random();
	
	System.out.println(random0.nextInt());
	}
}

и класс anotherClass

public class anotherClass{

	public anotherClass(){
		a = 7;
	}
	
	public anotherClass(int x){
		a = x;
	}
	
	int a;
	
	int addition(int a, int b){
		return a + b;
	}
}

Файлы должны находиться в одной папке. Компилируем их. Класс anotherClass содержит переменную a и метод addition, который возвращает результат сложения его параметров. Так как он не статический, мы можем создать из него объект. Также этот класс содержит два конструктора. Конструктор можно отличить от метода по его имени. Имя конструктора совпадает с именем класса. Если мы не создадим конструктор, JVM всё равно будет вызывать конструктор, который ничего не делает. Конструкторы рассмотрим строкой позже. Класс myClass содержит метод main, который служит точкой входа в программу, как было сказано в прошлых уроках. До описания класса myClass с помощью ключевого слова import добавляется класс Random из пакета java.util. Чтобы добавить все классы из пакета, необходимо вместо Random поставить *.

import java.util.*;

Но нам нужен только класс Random. Далее создаётся два объекта типа anotherClass, который мы с вами создали. Здесь нам и пригождаются конструкторы. При создании объекта object0, в объект не передаётся аргумент, поэтому вызывается конструктор по умолчанию. Это

	public anotherClass(){
		a = 7;
	}

Объекты

Переменная, хранящая ссылку на объект, создаётся также, как и для других типов. Но чтобы создать объект, нужно использовать ключевое слово new. После него указать тип объекта и с помощью круглых скобок вызвать необходимый конструктор, если он, вообще, есть. При создании объекта object1, в параметр передаётся аргумент. Компилятор находит необходимый конструктор и конструктор присваивает переменной a значение параметра x, то есть 9. Далее мы выводим на консоль значения переменной a каждого объекта. Как видим, чтобы обратиться к членам класса используется .

Получается

7
9

Потом мы вызываем метод из первого объекта addition, с помощью которого складываем два числа и результат выводим на консоль. Далее создаём объект random0 типа Random, который мы добавили с помощью стандартного пакета java.util. Вызываем метод nextInt() этого объекта, который возвращает случайное значение типа int, которое выводим на консоль. Когда я запустил программу, метод вернул случайное значение -1176582137.

Общий вывод выглядит так:

7
9
18
-1176582137

8. Циклы и операторы ветвления

В этом разделе мы рассмотрим такие конструкции, как if, else, for, while, do while, switch.

if

В следующем примере используется оператор ветвления if.

int value = 33;
if(value == 33){
	System.out.println("!!!");
}

В скобках должна оказаться переменная типа boolean. Мы помещаем выражение с логическим оператором ==, который проверяет равенство. Так как значения совпадают, оператор возвращает true, которое является boolean. Если возвращается true - содержимое в фигурных скобках выполняется. Если false - не выполняется. Пример можно дописать с использованием else так

int value = 33;
if(value == 0){
	System.out.println("!!!");
} else {
	System.out.println("???");
}

В нём переменная value не совпадает с 0, поэтому выполнятся содержимое в фигурных скобках после else, а после if игнорируется.

Пример можно дописать даже так

int value = 33;
if(value == 0){
	System.out.println("!!!");
} else if(value == 1){
	System.out.println("!!!");
} else if(value == 2){
	System.out.println("!!!");
} else if(value == 33){
	System.out.println("!!!");
} else {
	System.out.println("???");
}

for

В следующем примере используется цикл for.

for(int x = 0; x < 10; ++x){
	System.out.println(x);
}

Этот пример отправит такой вывод в консоль

0
1
2
3
4
5
6
7
8
9

В круглых скобках первым делом создаётся переменная x, которая будет работать в цикле. Во второй части находится выражение, которое должно вернуть переменную типа boolean. Если её значение true, тогда выполняется содержимое в фигурных скобках. После выполняется третья часть в круглых скобках. Потом идёт следующий цикл, в котором проверяется вторая часть. Если в ней false, тогда цикл прекращается, и программа выполняет следующий за ним код. Если нет, тогда опять выполняется тело цикла, потом третья часть в круглых скобках, снова вторая часть и т.д.

Этот цикл можно написать так

int x = 0;
for(; x < 10; ++x){
	System.out.println(x);
}

В принципе, можно оставить все три части без содержимого

for( ; ; ){
	System.out.println("!!!");
}

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

while

В следующем примере используется цикл while.

int a = 0;

while(a < 10) {
	System.out.println(a);
	a++;
}

Этот пример отправит в консоль следующий вывод

0
1
2
3
4
5
6
7
8
9

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

int a = 10;

do {
	System.out.print(a);
	a++;
} while (a < 10);

Вывод будет таким

10

switch

Далее используется оператор ветвления switch.

int value = 3;

switch(value) {
	case 0: System.out.println("zero");
	break;
	
	case 3: System.out.println("three");
	break;
	
	default: System.out.println("null");
	System.out.println("!!!");
	break;
}

В круглые скобки помещается значение для сравнения. В нашем случае это 3. Сравнивается оно со значениями после ключевых слов case. Если значение совпадает - выполняются все выражения после двоеточия до оператора break. Когда совпадений нет, тогда выполняются выражения после ключевого слова default. Если забыть написать break - выполнение продолжится до ближайшего оператора break. Если и его нет, JVM выполнит все последующие выражения в теле switch.

9. Эпилог

Мы изучили начала программирования, прошлись по самым необходимым вопросам, но осталось ещё много неизученного, которое вы должны будете изучить сами. Стандартные библиотеки, коллекции, лямбда-выражения, исключения, многопоточность и т.п. Также каждый язык чем-то отличается от другого. Указатели в C++, отступы в Python, в C нет объектов и т.д. Всегда найдётся что-то новое или уже забытое старое. Но, как видите, сложного ничего нет. Это руководство, скорее, похоже на набросок карты, а не на снимок местности со спутника, но его вполне достаточно, чтобы легко разобраться во всём оставшемся самому.

Мы Вконтакте Стройка века

https://vk.com/century_arch

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

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