суббота, 15 декабря 2018 г.

4 Типы данных в JAVA

   Тип данных определяет:
 
      - множество (диапазон) значений, которые могут принимать величины этого типа (которые может хранить переменная или константа)
      - операции, которые могут выполняться над величинами этого типа
      - внутреннее представление данных в памяти компьютера


   Размер типов данных остается неизменным на всех платформах (стандартизирован).
 
   Java - строго типизированный (не динамический) язык программирования. Это означает, что тип данных каждой переменной и выражений задается заранее и известен при компилировании.
 

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

    Примитивные типы Java  – это типы, для которых в ячейке памяти содержатся основные значения (непосредственно данные) – скалярные величины (простые битовые структуры), которые не являются объектами и имеют значения по умолчанию. 
 
   При выполнении операции присваивания для переменных, имеющих примитивный тип, выполняется копирование данных из одной ячейки памяти в другую.
   Примитивными являются логический тип boolean, целые числовые типы byte, short, int, long, char и плавающие числовые типы float и double.
 
 
 
Непримитивные (сложные) типы Java

   Сложные (непримитивные типы данных) образуются из простых путём группировки.
   Переменные примитивных типов хранят в себе значения, а переменные типов-классов хранят ссылку на объекты этого же класса, или null (если ссылка не задана). 
   Например,  String (Строка) - сложный, непримитивный тип данных, хранящий свои данные в виде таблицы символов, где каждый символ таблицы - это примитивный тип char.

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


Рис. 1 Схема классификации типов данных

   Классы в Java представляют собой сложные составные типы данных, данные которого будут либо другими сложными (непримитивными) типами данных и/или примитивными.
 
 
 
Примитивные типы данных

   Среди примитивных типов данных выделяют четыре типа для целочисленных значений (byte, short, int и long), два типа для дробных данных с плавающей точкой (float и double), один тип данных для символов (char) и один тип данных для логических условий true и false (boolean).
 
   В таблице ниже приведены все примитивные типы данных и их характеристики:
   Здесь Size - разрядность (количество байтов, выделяемых для хранения значений типа в оперативной памяти)
      Example Literals - диапазон значений.

   Если требуется создать ссылку на один из примитивных типов данных, необходимо использовать соответствующий класс-обертку. Оборачивание примитива в объект называется упаковкой (boxing), а обратный процесс распаковкой (unboxing).
 
   Соответствие типов данных классам-оберткам:
      byte соответсвует Byte
      short Short
      int Integer
      long Long
      char Character
      float Float
      double Double 
      boolean Boolean


Целочисленные типы данных
 
    • byte: 
         хранит целое число
         диапазон значений: от -128 до 127
         занимает 1 байт
         значение по умолчанию 0

    • short
         хранит целое число
         диапазон значений: от -32768 до 32767
         занимает 2 байта
         значение по умолчанию 0

    • int
         хранит целое число
         диапазон значений: от -2147483648 до 2147483647
         занимает 4 байта
         значение по умолчанию 0

    • long
         хранит целое число
         диапазон значений: от –9 223 372 036 854 775 808 до 9 223 372 036 854 775 807
         занимает 8 байт
         значение по умолчанию 0L (используйте заглавную букву, что бы не спутать букву с единицей)
   (По умолчанию, java интерпретирует все целочисленные переменные как 32-битные значения типа integer. Если нужноуказать, что используется тип long, нужно добавлять суффикс L в конце значения.

   Помимо десятичной системы счисления, можно применять и другие. К примеру:

   int u = 0x6F; // 16-иричная система, число 111
    (Для задания шестнадцатеричного значения после символов 0x указывается число в шестнадцатеричном формате)

   int u = 010; // 8-иричная система, число 8
    (Для задания восьмеричного значения после символа 0 указывается число в восьмеричном формате)

   int u13 = 0b1101; // 2-иричная система, число 13 .
    (Для задания двоичного значения после символов 0b указывается число в двоичном формате)


   Также целые числа поддерживают разделение разрядов числа с помощью знака подчеркивания:
   int x = 123_456; int y = 234_567__789;
   System.out.println(x); // 123456 System.out.println(y); // 234567789

   При делении целочисленных данных остаток отбрасывается.
 


Тип данных с плавающей точкой

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

   • double
         хранит число с плавающей точкой
         диапазон значений: от ±4.9*10^-324 до ±1.8*10^308
         занимает 8 байт
         значение по умолчанию 0.0D (с двойной точностью - 17 цифр)
   • float
         хранит число с плавающей точкой
         диапазон значений: от -3.4*10^38 до 3.4*10^38
         занимает 4 байта; Значение по умолчанию 0.0F (с одинарной точностью - 7-8 цифр)

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

   При присвоении переменной типа float дробного литерала с плавающей точкой, например, 3.1, 4.5 и т.д., Java автоматически рассматривает этот литерал как значение типа double.
   Чтобы указать, что данное значение должно рассматриваться как float, нам надо использовать суффикс f: float fl = 30.6f; double db = 30.6;
   В данном случае обе переменных имеют практически одно значение, но эти значения будут по-разному рассматриваться и будут занимать разное место в памяти.

    К обычным вещественным числам добавляются еще три значения:
      - положительная бесконечность, выражаемая константой POSITIVE_INFINITY и возникающая при переполнении положительного значения
      - отрицательная бесконечность, выражаемая константой NEGATIVE_INFINITY и возникающая при переполнении отрицательного значения
      - «не число», выражаемое константой NaN (Not a Number) и возникающее при делении вещественного числа на нуль или умножении нуля на бесконечность.
 
   Кроме того, спецификация языка Java различает положительный и отрицательный нули (+0.0 и -0.0), возникающие при делении на бесконечность соответствующего знака.


Логический тип данных boolean

   • boolean: хранит значение 'true' или 'false'; Значение по умолчанию 'false'.

    boolean isActive = false;
    boolean isAlive = true;
 
    char sex='m';
    boolean isSexM = 'm' == 1;  //В результате isSexM = true;
 
    Типы boolean и integer в языке Java несовместимы между собой.
    В отличие от языков C и C++, в Java константа true не равна 1, а константа false не равна 0.
 

Тип текстовых данных

   • char: 
      хранит одиночный символ в кодировке UTF-16 (символ представлен в 16-битным значением в Unicode-таблице) и поэтому занимает 2 байта
      диапазон его хранимых значений от 0 до 65535, что позволяет использовать 65536 различных символов
      значение по умолчанию ‘\ u0000’

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

   В качестве значения переменная символьного типа получает одиночный символ, заключенный в ординарные кавычки:
char ch='e';
   Кроме того, переменной символьного типа также можно присвоить целочисленное значение от 0 до 65536. В этом случае переменная опять же будет хранить символ, а целочисленное значение будет указывать на номер символа в таблице символов Unicode (UTF-16).
   Еще одной формой задания символьных переменных является шестнадцатеричная форма: переменная получает значение в шестнадцатеричной форме, которое следует после символов '\u'. 
(Код любого символа в кодировке Unicode набирается в апострофах после обратной наклонной черты и латинской буквы u четырьмя шестнадцатеричными цифрами.) 
   Таким образом, можно закодировать все символы Unicode последовательностями от \u0000 до \uFFFF.  

   Например, если в программу нужно вставить знак с кодом 6917, необходимо его представить в шестнадцатеричном формате (1B05) и записать это значение как \u1B05, причем буква u должна быть строчной, а шестнадцатеричные цифры A, B, C, D, E, F можно использовать как заглавные, так и строчные. 

   Пример: char ch='\u0066'; будет хранить символ 'f'.


   Символьные переменные не стоит путать со строковыми: здесь 'a' не идентично "a".

   Строковые переменные представляют объект String, который в отличие от char или int не является примитивным типом в Java: String hello = "Hello..."; System.out.println(hello);

    Тип char является псевдоцелочисленным типом, поэтому значения этого типа можно задавать в виде числа - кода символа из таблицы кодировки UTF-16. Каждому символу соответствует определённое число из таблицы и Java при виде этого числа в рамках типа char выводит его на экран как символ. То есть, например, при выполнении кода
   char c2 = 97;
   System.out.println(c2);
 
   на консоль выведется a.


Ссылочные типы данных
 
   Ссылочными типами называются типы данных, для которых в ячейке памяти содержится не сами данные, а только адреса этих данных, то есть ссылки на данные.
   К ссылочным типам относятся классы, интерфейсы и массивы.
   Существует также специальный нулевой тип – это зарезервированное слово null, обозначающее нулевой адрес.
 
   Свойства ссылочного типа данных:
      - при выполнении операции присваивания в ссылочную переменную заносится адрес данных, а не сами данные
      - непосредственный доступ к адресу, хранящемуся в ссылочных переменных, в языке Java отсутствует
      - ссылки можно присваивать друг другу, только если они совместимы по типам
      - если переменной ссылочного типа не присвоено значение (ещё нет ссылки на какой-то объект), в ней хранится значение null – специальная «пустая ссылка».
   В этом случае переменная просто хранит адрес объекта равный 0, но так как Java-машина никогда не создаёт объекты с таким адресом, распознает, что если переменная-ссылка содержит 0, то никакого объекта там нет.

      - ссылочным переменным можно присваивать значение null (пустую (нулевую) ссылку):
         b=null;
 
 
   Приведение примитивных типов данных
   (преобразование выражения одного типа данных к выражению другого типа данных)

   Рис.2 Схема совместимости типов данных 

   Здесь: сплошные линии указывают на преобразования без потери данных - с расширением, штриховые линии - на операции с возможной потерей данных, сужающие.
 
 
   Случай 1) Преобразование с расширением (conversion):
      переменная меньшей ёмкости назначается другой переменной большей ёмкости. (автоматическое преобразование)
   Например, от типа byte  к типу int.

   В данном случае конфликта не происходит (такие преобразования безопасны) и операции выполняются автоматически, без дополнительных указаний: новый тип всегда гарантированно вмещает в себя все данные, которые хранились в старом типе, и таким образом не происходит потери данных.
   Поэтому компилятор осуществляет это преобразование сам и никакихспециальных действий для этого предпринимать не требуется.
   Расширяющими являются следующие преобразования:
      - от byte к short, int, long, float, double
      - от short к int, long, float, double
      - от char к int, long, float, double
      - от int к long, float, double
      - от long к float, double
      - от float к double


   Случай 2) Преобразование сужающее (type casting):
      переменная большей ёмкости назначается другой переменной меньшей ёмкости. (явное преобразование типов)

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

   Следующие преобразования являются сужающими:
      - от byte к char
      - от short к byte, char
      - от char к byte, short
      - от int к byte, short, char
      - от long к byte, short, char, int
      - от float к byte, short, char, int, long
      - от double к byte, short, char, int, long, float
 
   Сужающие преобразования проводят, например, если оперируемое значение можно отнести к обоим рассматриваемым типам данных.
   Если же размер целочисленной части слишком велик для присваиваемого типа, то значение будет уменьшено до результата деления по модулю на диапазон целевого типа.
( Также сужающие преобразования выполняют с усечением: когда число с плавающей точкой приводят к целочисленному типу с отбрасыванием при этом хвостовой (дробной) части.)

  Для дробных типов (float и double) сужение (приведение такого числа к целочисленному типу) происходит с отбрасыванием у него дробной части.

   При выполнении операций с переменными, имеющими различные типы данных, тип каждого операнда и результата автоматически повышается до типа с наибольшей ёмкостью; при этом тип данных переменной, которой присваивается результирующее значение должен соответствовать ёмкости результата или же должно использоваться явное приведение.
 
   Пример потери данных при сужающем пребразовании:
   Изначальное значение, хранящееся в переменной типа int - 10000000. Она занимает 32 бита памяти.
   При записи этого значения в переменную типа short, которая может хранить только 16 бит, происходит следующее: только первые 16 бит вышеуказанного числа будут туда перемещены, остальные - отбросятся, не производится округления или каких-либо других действий для получения более корректного результата.
 
Примечания:
! Если сложить число и строку, то Java автоматически конвертирует число в строку.

 
Объявление и инициализация переменных

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

   Пример объявления типа данных:
 int a;

    Также можно комбинировать объявление переменных и их инициализацию:
char b='m';
 
   Пример операции с ссылочными (сложными) переменными:

ТипПеременной имяПеременной = ссылка на новосозданный объект вида (( new ТипСоздаваемогоОбъекта(); ))

 Okras okras=new Okras();

*использованы материалы с сайтов:
https://guru99.ru/java-variables/
https://www.geeksforgeeks.org/data-types-in-java/
https://java-master.com/primitive-types-of-data-in-java/
https://javarush.ru/groups/posts/630-primitivnihe-tipih-v-java--ne-takie-uzh-oni-i-primitivnihe

суббота, 1 декабря 2018 г.

3 Из чего состоит JAVA программа. Классы, объекты, методы, пакеты, интерфейсы

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

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

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

   (Если планируется, что программу не будут запускать на выполнение, а описанный класс будет лишь использоваться в других программах, то наличие в тексте метода main не обязательно)
   Обязательным условием корректности такой программы является совпадение имени файла (без расширения) с именем единственного класса размещённого в этом файле.
   Например, класс Tea должен храниться в файле с именем Tea.java.

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

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

   Пример простейшей программы:

   public class Tea
{
   public static void main (String[] args)
   {
   Код метода
   }
}


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


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

 
   Подробнее о пакетах, подпакетах и их импорте (import) в Java можно прочитать здесь:



Что такое класс (class)
 
     Класс представляет собой контейнер, содержащий программный код.
   Код внутри класса представляет собой набор элементов - описание полей, констант, методов, интерфейсов и других классов.
   Класс - по сути является шаблоном (описанием) для объекта: он определяет, как объект будет выглядеть и какими функциями обладать.
   Класс представляется в исходном коде так:

   class ИмяКласса
{
Тело класса

   Подробнее о классах в Java можно прочитать здесь:
 
 
Объект Java

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

   Класс - по сути является шаблоном (описанием) для объекта: он определяет, как объект будет выглядеть и какими функциями обладать.

   Рецепт (шаблон) выпечки пирожков можно назвать классом. Реально же существующий экземпляр данного класса (шаблона) - пирожок является объектом этого класса.
   Любой объект может обладать двумя основными характеристиками:
      - состояние (некоторые данные, которые хранит объект)
         Для хранения состояния объекта в классе применяются поля или переменные класса. 
      - поведение (действия, которые может совершать объект)
      Для определения поведения объекта в классе применяются методы.


Что такое метод

   Метод (функция) - это набор инструкций (команд), выполняемых программой, которому присвоили имя (имя метода).

   Код (тело) метода – это набор выражений (команд) (инструкций). Инструкции для метода должны быть размещены между его фигурными скобками - в "теле метода".

   Подробнее о методах можно прочитать здсь:


О командах

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

   Примеры команд:
   System.out.print - команда, отвечающая за вывод сообщения на экран. Следующая команда после этой выведет сообщение на эту же строку.
   System.out.println - команда, отвечающая за вывод сообщения на экран с новой строки. Т.е. сначала выводит заданный текст, а потом делает перевод на новую строку. Следующая команда после этой выведет сообщение на новую строку.

   Пример записи команды в коде:
   System.out.println(10); Результат: выводит на экран число 10
   System.out.println("строка"); Результат: выводит на экран слово строка


Что такое интерфейсы

   Интерфейс – это скелет (заготовка) класса с перечислением необходимых методов, но без их кода.

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

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


Наследование в Java

   «родительское/дочернее»     Наследование (inheritance) - свойство системы, позволяющее описать (создать) новый класс на основе уже су...