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

Этот блог Java знакомит программистов с программированием на Java. Мы представляем базовый синтаксис и передовые практики, которым следует следовать при программировании на Java. Мы рекомендовали установить Eclipse IDE & Java 1.8+ для запуска предоставленных файлов кода. Пожалуйста, прочтите комментарии к коду для получения дополнительных советов. Этот блог также можно найти в виде репозитория GitHub вместе с полными примерами кода с выводом по этой ссылке.

Этот блог - первая из серии, состоящей из двух частей. Прочтите « Введение в Java для программистов: Часть 2 », чтобы узнать, как работать с обработкой ошибок, многопоточностью, коллекциями, функциональным программированием и обработкой файлов в Java.

1. О Java

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

Он работает на различных платформах, таких как Windows, Linux, MacOS и т. Д. Он имеет широкую поддержку сообщества и онлайн-форумы, которые помогают повысить нашу продуктивность и решить любые проблемы, возникающие при программировании.

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

2. Инструменты Java

Мы должны узнать о JDK, JRE и JVM и различиях между ними, прежде чем узнаем о языке Java.

Виртуальная машина Java (JVM)

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

Среда выполнения Java (JRE)

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

Комплект для разработки Java (JDK)

Это инструмент разработки программного обеспечения, который используется для разработки приложений Java. Он состоит из JRE, компилятора Java (javac), отладчика Java, загрузчика Java (java), документации Java (javadoc) и архиватора (jar).

Мы используем JDK для создания программ на Java. Однако для их запуска нам понадобится только JRE. JVM, JRE и JDK зависят от платформы, а язык Java не зависит от платформы.

3. Привет, мир

Первая программа, которую мы напишем на Java, просто выведет фразу «Hello World!».

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

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

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

Для вывода на консоль мы используем класс System и его метод System.out.println (), который печатает аргумент вместе с дополнительным символом новой строки. Класс System - один из немногих классов, импортируемых по умолчанию в любой класс java.

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

4. Примитивный тип данных

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

Java поддерживает 8 предопределенных типов данных, называемых примитивными типами данных:

  • int: это 32-битное целое число, которое имеет минимальное значение -2³¹ и максимальное значение 2³¹ – 1. Мы также можем использовать восьмеричную или шестнадцатеричную систему счисления в качестве целых чисел, которые можно указать, начав значение с «0» или «0x» соответственно.
  • байт: это 8-битное целое число, которое имеет минимальное значение -128 и максимальное значение 127. Это полезно для экономии памяти при сохранении числовых кодов, возраста и т. д. в больших массивах.
  • вкратце: это 16-битное целое число, минимальное значение которого составляет -32 768, а максимальное - 32 767.
  • long: это 64-битное целое число, которое имеет минимальное значение -2⁶³ и максимальное значение 2⁶³ – 1.
  • float: это 32-битное значение с плавающей точкой с точностью до 6–7 десятичных знаков.
  • double: это 64-битное значение с плавающей точкой с точностью до 15–16 десятичных знаков.
  • логическое: имеет только два возможных значения: истина и ложь. Используется для хранения условных результатов или флагов.
  • char: это один 16-битный символ Unicode.

Все эти значения по умолчанию равны 0 или ложному значению. Однако компилятор Java не инициализирует локальные переменные.

В PrintData мы использовали функцию System.out.printf () для вывода переменных. Эта функция называется средством форматирования печати и позволяет нам печатать строку со ссылками на следующие за ней аргументы переменных. Мы можем отметить, что код символа - «% c», логическое значение - «% b» и целое число - «% d».

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

5. Непримитивный тип данных

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

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

Доступны следующие непримитивные типы данных:

Нить

Это класс, в котором хранится последовательность символов (char). Строковые объекты неизменяемы, а также имеют множество вспомогательных функций для выполнения операций со строковыми данными.

Множество

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

Класс

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

Для каждого примитивного типа данных в Java у нас есть специальный класс Wrapper, который помогает нам выполнять дополнительные операции с помощью предопределенных методов. Эти классы имеют то же имя, что и примитивный тип данных, с заглавными буквами в их первом алфавите. Единственное исключение - класс Character для char.

Интерфейс

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

Мы узнаем больше о массивах, классах и интерфейсах в следующих разделах.

6. Условные выражения

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

Если еще

Это позволяет нам проверять различные условия с помощью предложения else if.

Синтаксис

if(condition1){
	statements;
}else if(condition2){
	statements;
}else{
	statements;
}

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

Класс Scanner используется для сканирования любого потока на предмет входных данных и позволяет нам получить к нему доступ через функции метода. Мы использовали поток System.in для проверки входных данных. Мы всегда должны быть бдительными, чтобы закрыть сканер после использования, иначе это приведет к утечке ресурсов, поскольку он не будет собран сборщиком мусора Java.

Выключатель

Оператор Switch обеспечивает более интуитивный подход к проверке условий.

Синтаксис

switch(variable){
case value1: //statements
		break;
case value2: //statements
		break;
	default: //statements
}

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

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

Это переработанное выражение if-else. Это помогает нам писать однострочные операторы if-else.

Синтаксис

variable = condition ? value1 : value2;

Если данное условие истинно, то переменной присваивается значение1, в противном случае - значение2.

7. Петли

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

Мы представляем четыре основных цикла в Java, то есть цикл For, цикл Enhanced-For, цикл While и цикл Do-While.

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

Для петли

for(initialization; condition; increment/decrement){
	statements;
}

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

Улучшено для цикла

for(DataType var:list){
	doSomething(var);
}

Этот цикл является более простым вариантом классического цикла for и позволяет легко перебирать элементы списка. Мы можем легко перемещаться по элементам списка с помощью этого расширенного цикла for. Переменная var обращается к каждому элементу списка последовательно и позволяет нам выполнять над ними нужные операции.

Пока цикл

while(condition){
	statements;
}

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

Цикл Do-While

do{
	statements;
} while(condition);

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

8. Списки

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

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

Мы можем использовать класс ArrayList, предоставляемый Java, для создания изменяемых списков. Этот класс предоставляет нам возможность добавлять / удалять элементы в список, но это происходит за счет дополнительной временной сложности. Многие другие классы, такие как Vector и Stack, также реализуют интерфейс List и могут использоваться при необходимости. Vector похож на ArrayList, но все его методы синхронизированы, следовательно, потокобезопасны.

Класс ArrayList и Iterator используют Generics, чтобы сделать возможным создание списка и итератора любого желаемого типа данных. Мы указываем тип данных здесь в ‹› как ArrayList ‹String›, чтобы создать список строк. Мы также можем создать список наших собственных пользовательских классов. Мы узнаем больше о дженериках в следующих разделах.

9. Методы

При каждом вызове метод запускает блок кода. Это помогает уменьшить избыточность кода. В Java методы определены внутри классов.

Синтаксис

access-specifier access-modifier return-type method-name(parameter-list, data-type... var-name){
	statements;
}

Каждый метод в классе должен иметь уникальное имя. Спецификаторы доступа решают, откуда мы можем получить доступ к методу. Модификаторы отсутствия доступа добавляют к методу определенные характеристики. Эти спецификаторы и модификаторы также можно использовать для переменных данных-членов. Для получения более подробной информации о различных спецификаторах доступа и модификаторах отсутствия доступа перейдите по этим ссылкам [1, 2].

Для данного возвращаемого типа каждая функция должна возвращать значение этого типа, за исключением void, для которого не требуется возвращаемое значение.

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

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

10. Объектно-ориентированное программирование.

Объектно-ориентированное программирование лежит в основе Java. ООП использует объекты, которые имеют определенные данные / атрибуты, называемые состоянием объекта, и определенные функции-члены, называемые действиями, выполняемыми объектом. Сущности объекта иногда соответствуют вещам в реальном мире и отношениям между ними. Например, у всех людей есть имя, возраст и пол, и мы выполняем такие действия, как еда, ходьба и сон. Как и люди, каждый объект может иметь разные атрибуты или другое состояние, но каждый может выполнять одни и те же функции. Класс предоставляет атрибуты и доступные действия для объекта. Он служит планом для каждого экземпляра объекта. Мы можем назвать Homosapiens классом, а каждого человека - его объектом.

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

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

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

Класс Tiger наследуется от класса Animal и добавляет дополнительные состояния и действия, такие как рев. Это действие уникально для Тигра, поэтому был создан подкласс. Это помогает уменьшить избыточность кода в классе Tiger. Метод eatFood () выполняет разные действия в зависимости от того, введен строковый аргумент или нет. Таким образом, мы можем реализовать полиморфизм в классах.

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

Абстрактный класс

В Java абстрактный класс объявляется с помощью ключевого слова abstract. Обычно мы указываем абстрактные функции-члены внутри абстрактного класса, которые не реализованы. Абстрактный класс не может быть создан, и он должен быть унаследован от другого подкласса, в котором реализованы все его абстрактные методы. В абстрактном классе могут быть абстрактные или не абстрактные методы вместе с членами данных. Эти классы помогают развернуть общие функции для всех наследующих классов.

Абстрактный класс обозначает отношение IS-A между собой и наследующими классами.

Класс устройства действует как шаблон для всех создаваемых устройств и гарантирует, что все устройства реализуют методы switchOn () и switchOff ().

MediaPlayer наследует класс Device и предоставляет собственную реализацию всех своих абстрактных методов.

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

Интерфейс

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

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

Интерфейсы помогают нам решить проблему отсутствия множественного наследования в Java. Класс может реализовывать более одного интерфейса. Однако не следует путать интерфейс с классом. Он не отражает отношения IS-A между реализующим классом и интерфейсом, скорее он отражает особенность класса / то, как класс работает.

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

Подробнее в части 2.