вторник, 8 сентября 2020 г.

Управление исключениями (возникающими ошибками) в Java

  Исключение в программировании - это возникновение ошибок и непредвиденных ситуаций при выполнении программы.

  Исключения (ошибки при выполнении программы) могут возникать в результате:

   - неправильных действий пользователя

   - отсутствии необходимого ресурса на диске

   - потери соединения с сервером по сети

   - ошибки программирования

   - неправильное использование API.

 

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

   (чтобы предупредить и решить исключительные ситуации в программе, для того чтобы её выполнение могло быть продолжено)

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

  Использование исключений в Java позволяет повысить отказоустойчивость программы за счет использования «запасных» путей, отделить логику основного кода от кода обработки исключительных ситуаций за счет использования блоков catch, а также дает возможность переложить обработку исключений на пользователя нашего кода с помощью throws.

 

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

 

try, catch, finally, throws

 

   1) try – определяет (заключает под собой) блок кода, в котором может произойти исключение;

   2) catch – определяет (заключает под собой) блок кода, в котором происходит обработка исключения;

   (Действия при сбое, который может случиться внутри оператора try)

   3) finally – определяет (заключает под собой) блок кода, который является необязательным, но при его наличии выполняется в любом случае независимо от результатов выполнения блока try.

(Блок finally часто используется для того, чтобы закрыть открытые в блоке try потоки или освободить ресурсы. Однако при написании программы не всегда возможно уследить за закрытием всех ресурсов. Для облегчения этой задачи существует конструкция try-with-resources, которая автоматически закрывает ресурсы, открытые в блоке try).

   Эти ключевые слова используются для создания в программном коде специальных обрабатывающих конструкций: try{}catch, try{}catch{}finally, try{}finally{}.

   На стадии разработки программы мы «ограждаем» опасные участки кода в отношении исключений с помощью блока try{}, предусматриваем «запасные» пути с помощью блока catch{}, в блоке finally{} мы пишем код, который выполняется в программе при любом исходе.

 

   При появлении исключения в блоке try обработчик исключения ищется в следующем за ним блоке catch. Если в catch есть обработчик данного типа исключения – управление переходит к нему. Если нет, то JVM ищет обработчик этого типа исключения в цепочке вызовов методов до тех пор, пока не будет найден подходящий catch. После выполнения блока catch управление передается в необязательный блок finally. В случае, если подходящий блок catch не найден, JVM останавливает выполнение программы, и выводит стек вызовов методов – stack trace, выполнив перед этим код блока finally при его наличии.

   Переменные, определенные в try не могут быть использованы в catch или finally, этот код не скомпилируется. Причина в том, что неизвестно, где именно в блоке try могло быть вызвано исключение, например, возможно, что исключение было вызвано до того, как был объявлен объект.


  4) throw – используется для возбуждения исключения

  5) throws – Это ключевое слово в сигнатуре метода означает, что при определенных условиях метод, может выбросить исключение

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

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

   После throws указывается тип выбрасываемого исключения.

 

   Типы выбрасываемых исключений:

   Обычно это наследники класса Exception Java.

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

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

   Иерархия исключений java:




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

   Далее всё это множество исключительных ситуаций можно разделить на две группы:

   1) Непроверяемые на стадии компиляции (неконтролируемые) (unchecked)

   Это Error (исключения, унаследованные из класса Error) + RuntimeException (часть исключений - наследников класса Exception)

  RuntimeException – исключения, генерируемые JVM во время выполнения программы. Часто причиной возникновения их являются ошибки программирования.

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

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

 

Список непроверяемых исключений:

   ArithmeticException - арифметическая ошибка, например, деление на ноль

   ArrayIndexOutOfBoundsException - выход индекса за границу массива

   ArrayStoreException - присваивание элементу массива объекта несовместимого типа

   ClassCastException - неверное приведение

   EnumConstantNotPresentException - попытка использования неопределённого значения перечисления

   IllegalArgumentException - неверный аргумент при вызове метода

   IllegalMonitorStateException - неверная операция мониторинга

   IllegalStateException - некорректное состояние приложения

   IllegalThreadStateException - запрашиваемая операция несовместима с текущим потоком

   IndexOutofBoundsException - тип индекса вышел за допустимые пределы

   NegativeArraySizeException - создан массив отрицательного размера

   NullPointerException - неверное использование пустой ссылки

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

   NumberFormatException - неверное преобразование строки в числовой формат SecurityException - попытка нарушения безопасности

   StringIndexOutOfBounds - попытка использования индекса за пределами строки

   TypeNotPresentException - тип не найден

   UnsupportedOperationException - обнаружена неподдерживаемая операция

 

 

   2) Проверяемые на стадии компиляции (предвидимые еще на стадии написания программы) (контролируемые) (checked)

   Это Exception (кроме RuntimeException)

   Основная часть работы разработчика на Java при работе с исключениями – обработка таких ситуаций: проверяемые исключения должны быть явно пойманы в теле метода или объявлены в секции throws метода.

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


   Список проверяемых системных исключений, которые можно включать в список throws:

   ClassNotFoundException - класс не найден

   CloneNotSupportedException - попытка клонировать объект, который не реализует интерфейс Cloneable

   IllegalAccessException - запрещен доступ к классу

   InstantiationException - попытка создать объект абстрактного класса или интерфейса

   InterruptedException - поток прерван другим потоком

   NoSuchFieldException - запрашиваемое поле не существует

   NoSuchMethodException - запрашиваемый метод не существует

   ReflectiveOperationException - исключение, связанное с рефлексией

 

   Пример использования ключевых слов в java-программе:

//метод считывает строку с клавиатуры

public String input() throws MyException {//предупреждаем с помощью throws,
// что метод может выбросить исключение MyException
      BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    String s = null;
//в блок try заключаем код, в котором может произойти исключение, в данном
// случае компилятор нам подсказывает, что метод readLine() класса
// BufferedReader может выбросить исключение ввода/вывода
    try {
        s = reader.readLine();
// в блок  catch заключаем код по обработке исключения IOException
    } catch (IOException e) {
        System.out.println(e.getMessage());
// в блоке finally закрываем поток чтения
    } finally {
// при закрытии потока тоже возможно исключение, например, если он не был открыт, поэтому “оборачиваем” код в блок try
        try {
            reader.close();
// пишем обработку исключения при закрытии потока чтения
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }

    if (s.equals("")) {
// мы решили, что пустая строка может нарушить в дальнейшем работу нашей программы, например, на результате этого метода нам надо вызывать метод substring(1,2), поэтому мы вынуждены прервать выполнение программы с генерацией своего типа исключения MyException с помощью throw
        throw new MyException("String can not be empty!");
    }
    return s;
}
 

 Этот же пример с помощью try-with-resources:

public String input() throws MyException {
    String s = null;
    try(BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))){
        s = reader.readLine();
   } catch (IOException e) {
       System.out.println(e.getMessage());
   }
    if (s.equals("")){
        throw new MyException ("String can not be empty!");
    }
    return s;
}

вторник, 16 июня 2020 г.

Объектно ориентированное программирование и принципы ООП


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

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

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

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

   1) абстракция данных
   «важное/неважное»

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

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

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

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

 



   2) инкапсуляция
   «ключевое/подробности»

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

   Используется для быстрой и безопасной организации иерархической управляемости.
   Доступ к данным (полям) предоставляется посредством публичных методов (геттеров/сеттеров). Это защитный барьер позволяет хранить информацию в безопасности внутри объекта.
   Одни языки (например, С++, Java или Ruby) отождествляют инкапсуляцию с сокрытием, но другие (Smalltalk, Eiffel, OCaml) различают эти понятия.


   Прочитать больше об инкапсуляции, геттерах и сеттерах можно здесь: https://javaika.blogspot.com/2019/02/encapsulation-getters-and-setters.html


   3) наследование
   «родительское/дочернее»

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

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

    Подробнее о наследовании здесь: https://javaika.blogspot.com/2022/10/nasledovanie.html


   4) полиморфизм подтипов
   «единое/множественное»

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

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

Ограничения

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

Достоинства

  • универсальность кода;

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

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

 

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

   Другой формой полиморфизма является перегрузка метода, когда его поведение определяется набором передаваемых в метод аргументов.
 
   Перегрузка метода (method overloading) - механизм, позволяющий использовать методы с одним и тем же именем, но с разными типами и/или количеством параметров (несколько версий одного метода с разным набором входных параметров): при вызове метода, в зависимости от типа и количества передаваемых параметров, система выберет именно ту версию, которая наиболее подходит.
 
(Механизм перегрузки метода позволяет методу проявлять различное поведение в зависимости от того, какие аргументы он принимает.)

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

    Связывание (binding) — присоединение вызова метода к телу метода.

    Раннее связывание (early binding) — это связывание, происходящее во время компиляции. Также его называют статическим.

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

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

     Позднее связывание (late binding) — это связывание, которое выполняется во время выполнения программы. Его также называют динамическим (dynamic) или связыванием на стадии выполнения (runtime binding). При позднем связывании определяется фактический тип объекта для вызова именно его метода.


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

 

    Восходящее преобразование (upcasting) — это когда, например метод в качестве параметра типа базового класса принимает тип класса наследника. Но это разумно, т.к. класс наследник является разновидностью класса предка. Данный факт позволяет преобразовывать ссылку на объект наследника в ссылку на объект предка.

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

Преобразования можно делать и в обратном порядке — это называется нисходящее преобразование (downcasting).

Типы отношений между классами

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

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

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

Если еще проще, то вся разница между агрегацией и композицией состоит в том, каким образом инициализируются поля в классе-контейнере и как эта инициализация влияет на время их жизни после смерти основного класса.

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

А, если создать объект, а потом передал его в качестве аргумента в сеттер или в конструктор, а потом присвоить его полю, то со смертью класса — все созданные таким образом объекты будут жить и дальше — это агрегация.

А теперь приведу примеры того, что пишут в интернете, возможно, кому-то они покажутся проще.

 
 

    Агрегация (aggregation; «has-a» — есть, имеет, содержит) применяется когда один класс должен быть контейнером для других классов. Причем время существования содержащихся в нем классов (полей) никак не зависит от времени существования класса контейнера.

    Агрегация — отношение «часть-целое» между двумя равноправными объектами, когда один объект (контейнер) имеет ссылку на другой объект. Оба объекта могут существовать независимо: если контейнер будет уничтожен, то его содержимое — нет.

Данный вид связи на UML-диаграмме обозначается в виде линии с незакрашенным ромбиком (ромбик всегда находится со стороны целого, а простая линия со стороны составной части).

 

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

     Данный вид связи на UML-диаграмме обозначается в виде линии с закрашенным ромбиком (ромбик всегда находится со стороны целого, а простая линия со стороны составной части).

    Разница между агрегацией и композицией

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

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

    Композицию часто предпочитают наследованию

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

Достоинства

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

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

   Инстанцирование (англ. instantiation) — создание экземпляра класса. Создать экземпляр класса = инстанцировать класс. Порождающие шаблоны используют полиморфное инстанцирование.

   Анонимный объект (англ. anonymous object) — это объект, который принадлежит некоторому классу, но не имеет имени.

   Инициализация (англ. initialization) — присвоение начальных значений полям объекта.

   Время жизни объекта - время с момента создания объекта (конструкция) до его уничтожения (деструкция).
 
   Подробнее о классах здесь: https://javaika.blogspot.com/2020/11/java-class.html
 
 
   Объекты обладают свойствами наследования, инкапсуляции и полиморфизма.
   Объекты обладают такими характеристиками как состояние и поведение.
 
   Состояние объекта (state) — это значения, которые принимают его поля (fields). Со сменой значения полей — меняется состояние объекта.
   Поведение объекта (behavior) — это набор его методов (methods), которые могут изменять состояние объекта либо выполнять иные функции.
 






Больше об этом можно прочитать здесь: https://topjava.ru/blog/oops-concepts-in-java

Понятие метода - конструктора в JAVA. Ключевое слово this

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

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

   (Java не позволит создать объект, если указанные для него аргументы отсутствуют).
 

               конструктор "медвежонок" инициализирует объект "медвежонок (побольше)"

   У каждого класса есть конструктор. Конструктор вызывается всегда, когда создаётся новый экземпляр класса.
 
   Если в классе не определено (не прописано) ни одного конструктора, то для этого класса компилятор Java автоматически (по умолчанию) создает конструктор без параметров (аргументов).
 
    Конструктор, созданный по умолчанию, срабатывает каждый раз при создании любого объекта любого класса.
      (Каждый раз, когда создается новый объект, будет вызываться как минимум один конструктор)

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


Базовые типы конструкторов в Java:
 
    1) Конструктор по умолчанию (default constructor)
    (невидимый конструктор, автоматически создаваемый компилятором)
 
    Конструктор по умолчанию создает компилятор, если программист не создал свой (Компилятор не сгенерирует конструктор по умолчанию, если программист реализовал свой конструктор).
 
    Поля экземпляра класса при таком конструкторе будут установлены значениями для полей по умолчанию:
    byte     0
    short     0
    int     0
    long     0L
    float     0.0f
    double     0.0d
    char     '\u0000'
    String (or any object)       null
    boolean     false

    2) Конструктор без аргументов (no-args constructor)
 
    Конструктор по умолчанию и Конструктор без аргументов не принимают аргументы.

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

    Хотя у конструктора и не указывается возвращаемый тип, но он все же неявно возвращает тип создаваемого объекта.
    Непосредственно перед тем, как будет возвращен результат в виде ссылки на только что созданный объект, указанный конструктор будет использован для инициализации этого нового объекта.
    Таким образом, вызов Конструктора без аргументов вызывает созданный нами конструктор без аргументов и неявно возвращает результат в виде ссылки на только что созданный объект.

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

ТипПеременной имяПеременной = new ИмяКонструктора();

   Объект создаётся при помощи оператора new, который динамически выделяет для него память в куче (heap) и возвращает на него ссылку, которая присваивается переменной.

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


    3) Параметризованный конструктор (parameterized constructor) 

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

    Если конструкторов у класса несколько, то будет вызываться будет тот конструктор, который указывается при создании объекта набором параметров соответствующим используемому конструктору с таким же самым перечнем праметров.
 
   4) Конструктор копирования (copy constructor)
   Конструктор копирования это специальный конструктор, который принимает в качестве аргумента экземпляр того же класса для создания нового объекта на основе переданного.
   Такие конструкторы применяются тогда, когда необходимо создать копию сложного объекта, но при этом мы не хотим использовать метод clone().
   (Например, если в копии объекта какие-то поля должны отличаться).
 
   Ссылка на имя в конструкторе копирования копируется в значение нового объекта, т. е. значение нового объекта будет ссылаться на один и тот же адрес в памяти, что и оригинальный объект.
   Переменные типа String и класс LocalDateTime являются immutable и никогда не изменятся.
   Чтобы изменить их значения, им нужно будет присвоить другую ссылку. При этом эти поля других объектов будут по прежнему ссылаться на прежнее место в памяти. Заменив ссылку переменной поля порожденного объекта, значение ссылки оригинального объекта остаётся прежним.


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

    Глубокое копирование (deep copy)
    Этот вид копирования позволяет создавать объекты, которые будут содержать точные копии всех полей (в том числе ссылочных) оригинального объекта, но при этом будут абсолютно независимы от оригинального объекта.
    Изменение полей скопированного (склонированного) объекта не отражается на изменении полей оригинального объекта (также и в обратном случае).



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



    Объект-значение (Value Objects)
    Один из вариантов использования конструкторов в Java — создание объектов-значений.
    Value Object — это объект, который не меняет своего внутреннего состояния после инициализации (становится immutable). Это значит, что если требуется изменить такой объект, то для этого придется создать его новый экземпляр, вместо того чтобы изменять существующий.



    Если мы используем ключевое слово final при определении членов класса. Это означает, что каждый из них может быть инициализирован только с помощью конструктора. Их нельзя переназначить позже в каком-либо другом методе. Мы можем считать эти значения, но не можем их изменить.
    Если мы создадим несколько конструкторов для класса, то каждый из них должен будет инициализировать каждую финальную переменную. Невыполнение этого приведет к ошибке компиляции. Например, «java: variable amount might not have been initialized».

 


   Основные требования к конструкторам:

    Класс может содержать любое количество конструкторов (NB! у них должны различаться их аргументы иначе выдаст ошибку). При большом количестве конструкторов для упрощения кода можно использовать Шаблоны проектирования из категории Creational Design Patterns. 

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

   Можно считать, что имя конструктора совпадает с именем класса, а можно рассматривать конструктор как безымянный, и имя класса – как тип возвращаемого значения, так как конструктор может породить только объект класса, в котором он объявлен.
 
   Конструктор не может иметь возвращаемый тип (даже void).

   К конструктору можно применять модификаторы доступа для контроля его вызоваю

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

    Конструктор может принимать в качестве аргумента как примитивные типы данных, так и объекты

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

    Значение примитивов (int, float, double и т. д.) копируются как есть
    Ссылки на объекты типа immutable (например String), также копируются как есть. Несмотря на то, что оригинальный и порожденный объекты ссылаются на тот же самый адрес в памяти, immutable-объекты  никогда не будут изменяться
    Ссылки на mutable объекты (например Date, List и т. д.) должны копироваться при помощи глубокого копирования. Иначе оригинальный и порожденный объекты будут ссылаться на один и тот же адрес в памяти и соответственно, любые изменения объекта (оригинального или порожденного) будут отображаться на всех объектах

    Конструктор не может быть объявлен как final, static, synchronized или abstract
    Конструктор может быть перегружен (overload)

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

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

    Метод namesConcatinate объединяет имя и фамилию в одну строковую переменную. Закрытый конструктор BankAcoountUtils() делает невозможным создание экземпляра класса BankAccountUtils. Следующий код выведет объединенную строковую переменную без создания объекта:

Конструктор по умолчанию имеет тот же самый модификатор доступа, что и класс


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

    Конструктор и сеттеры можно (нужно) использовать совместно:

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

 
 
О конструкторах можно посмотреть по ссылке: https://www.youtube.com/watch?v=f88zS-etDWs
 
 
 
   При инициализации аргументов используется this:

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


   Пример применения метода-конструктора:


public class Tea {

    String name;

     int age;

 //конструктор для класса Tea

     public void setTea(String name, String sort) {

    this.name = name;

    this.sort = sort;

 }

    public static void main(String[] args) {

        Tea cup = new Tea("Green", '"Japanese");

    }

 }

 

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

   Также тело конструктора может содержать любое количество return-выражений без аргументов.
   Если процесс исполнения дойдет до такого выражения, то на этом месте выполнение конструктора будет завершено.
 
    Так как при вызове конструктора осуществляется создание и инициализация объекта, такой процесс не может происходить без обращения к конструкторам всех родительских классов.
   Поэтому вводится обязательное правило - первой строкой в конструкторе должно быть обращение к родительскому классу, которое записывается с помощью ключевого слова super, за которым идет перечисление аргументов.
 
   В теле конструктора используется ключевое слово this с круглыми скобками, которое позволяет вызывать другой конструктор, передавая в него аргументы (не любой, а только тот, который подходит по количеству и типам передаваемых аргументов). Это нормальная практика вызывать конструкторы по цепочке (в рамках текущего класса), когда часть значений используется по умолчанию, а какие-то являются новыми.
   Но бывает и другая ситуация, когда мы хотим перед отработкой конструктора потомка вызвать конструктор суперкласса. В таком случае нужно использовать ключевое слово super().
 
 
   Создание объекта

   Создание объекта начинается при исполнении выражения с ключевым словом new, за которым следует имя класса, от которого будет порождаться объект, и набор аргументов для его конструктора.
   По этому набору определяется, какой именно конструктор будет использован, и происходит его вызов.
   Первая строка его тела содержит вызов родительского конструктора. В свою очередь, первая строка тела конструктора родителя будет содержать вызов далее к его родителю, и так далее. Восхождение по дереву наследования заканчивается, очевидно, на классе Object, у которого есть единственный конструктор без параметров.
   Именно в этот момент JVM порождает объект, и далее начинается процесс его инициализации.
   Выполнение начинает обратный путь вниз по дереву наследования.
 
   У самого верхнего родителя, прямого наследника от Object, происходит продолжение исполнения конструктора со второй строки. Когда он будет полностью выполнен, необходимо перейти к следующему родителю на один уровень наследования вниз и завершить выполнение его конструктора, и так далее.
   Наконец, можно будет вернуться к конструктору исходного класса, который был вызван с помощью new, и также продолжить его выполнение со второй строки.

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

воскресенье, 14 июня 2020 г.

3.1 Переменные в JAVA

   Переменные – это контейнеры для хранения данных.


   Все данные в Java хранятся с помощью переменных.

   Переменные в Java имеют три свойства: тип, имя и значение.

   Имя необходимо для того, чтобы отличать одну переменную от другой.


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

   Переменные делятся на два типа: примитивы (простые типы) и ссылки.
 
   Примитивы хранят основные значения (простые битовые структуры), включая целые числа, булевы значенияи числа с плавающей точкой.
   Ссылки хранят ссылки на объекты.

   Подробнее о типах данных здесь: https://javaika.blogspot.com/2018/12/tipy-dannih-v-java.html

 
 
    Значение – это объект, данные или информация, которая хранится в переменной.
   В переменной не примитивного типа хранится ссылка на объект.

   Чтобы создать переменную используется команда вида: «тип имя».

   Пример создания переменной:
int aj;
   Данная запись создает переменную типа int c именем aj.

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

   Пример занесения значения в переменную:

  i = 3;
  (В переменную i заносится значение 3)

   k = k + 1;
   (В переменную k заносится значение переменной k +1)

   Можно создавать переменные и присваивать им значения в одной строке:

   String per = "Text";

   Для сравнения в языке Java используется двойное равно «= =».


   Правила:

   1 Нельзя создать две переменных с одинаковыми именами в одном методе, но можно - в разных методах?
   2 Имя переменной может содержать латинские буквы и цифры, не может содержать пробелов, символов +,- и д.р.
   3 В языке Java имеет значение регистр букв: peR и per - это имена разных переменных.
 
 
   Переменные экземпляра - переменные, описывающие состояние объекта.

   Локальные переменные - переменные, объявленные внутри метода. Локальная переменная существует только в том блоке кода (методе), в котором она объявлена (существует с момента объявления и до конца блока кода, в котором объявлена).

   Аргументы - значения, передающиеся методу из возвращаемого кода.

   Переменные возвращаемых значений - значения, возвращаемые методов в вызывающий код.

суббота, 16 марта 2019 г.

9 Создание GUI. Пакет Javax.Swing и краткое описание его классов

   GUI (graphical user interface) - это графический пользовательский интерфейс.

   Задача создания GUI - создание гибкого и дружелюбного интерфейса для использования приложения пользователями.


   Для того, чтобы разобраться, как создавать GUI на Java, познакомимся с пакетом javax.swing библиотеки Java API.


   Для подключения библиотеки Swing в приложении необходимо импортировать библиотеку javax.swing.

   Для создания графического пользовательского интерфейса приложения используют различные классы пакета javax.swing.

Классы, предназначенные для создания окон (JWindow, JFrame, JDialog)

   о классе Javax.Swing.JWindow:

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

   о классе Javax.Swing.JFrame:

   Основные отличия окна JFrame от JWindow:
      - наличие рамки, которая позволяет изменять размер окна
      - наличие заголовка с названием приложения (заголовок может быть пустым)
      - возможность использования системного меню, позволяющее проводить манипуляции с окном и приложением
      - наличие кнопок управления для закрытия и свертывания окна

   Класс JFrame(), если не задать параметры создаст пустое окно.
   Класс JFrame(String title) создаст пустое окно с заголовком title. Для определения заголовка окна можно также использовать метод setTitle() класса JFrame.

   Используемые методы для определения параметров окна:
      1) setSize(int width, int height) - для определения размеров окна
   Если не определить размеры окна, то оно будет иметь нулевую высоту независимо от того, что в нем находится. Здесь в размеры окна включены границы и строка заголовка.

      2) setLocation() - для задания положения окна

      3) setBounds(int x, int y, int width, int height) - для задания размеров окна и его положения (путём указания расположения его левого верхнего угла)

      4) setDefaultCloseOperation(int operation) - для определение действия при завершении программы.
   Данный метод позволяет указать, какое действие будет произведено при предварительной обработке события processWindowEvent() перед закрытием окна.
   По умолчанию в качестве параметра operation используется константа HIDE_ON_CLOSE, убирающая окно с экрана при его закрытии.
   При использовании константы EXIT_ON_CLOSE создаётся указание, что при закрытии окна необходимо закончить работу приложения.
   При использовании константы DO_NOTHING_ON_CLOSE - ничего не делать при закрытии окна. К окну JFrame подключается слушатель и обработка события закрытия окна выполняется в методе windowClosing. Алгоритм обработки построен таким образом, что окно закрывается при третьей попытке. Номер попытки отображается в метке интерфейса.

      5) setVisible(boolean visible) и show() - для того, чтобы сделать окно видимым.
   По умолчанию окно создается невидимым.
   Чтобы отобразить окно на экране вызывается метод setVisible с параметром true. Если вызвать его с параметром false, окно станет невидимым.
   Метод show(), вдобавок, проводит валидацию содержащихся в окне компонентов.

      6) pack() - для того, чтобы "упаковать" имеющиеся в окне компоненты так, чтобы они занимали столько места, сколько им необходимо. Компоненты при вызове этого метода переходят в «видимое» состояние, хотя и не появляются на экране до вызова одного из следующих методов

      7) setTitle() - для определения заголовка окна.

      8) setIconImage() - для определения иконки окна, которая располагается на кнопке свернутого окна или в заголовке окна в нормальном состоянии.

Окна Swing (JWindow, JFrame, JDialog) поддерживают два типа событий:

   WindowListener - позволяет узнать об изменениях в состоянии окна
   WindowFocusListener - сообщает о получении или потере компонентами окна фокуса ввода

   о классе Javax.Swing.JDialog:

   Диалоговые окна JDialog чаще всего используются в приложениях для получения дополнительной информации с целью установки параметров приложения, вывода важной вспомогательной или отладочной информации.
   Диалоговые окна при помощи этого класса можно создавать обычными или модальными (modal) - блокирующими доступ к остальным окнам приложения, пока пользователь не закончит работу с модальным диалоговым окном.
   Модальные диалоговые окна располагаются поверх основного окна приложения.
   Внешний вид диалоговых окон мало отличается от окон с рамкой JFrame, но обычно у них меньше элементов управления окна (чаще всего, имеется только кнопка закрытия окна) и отсутствует системное меню.
   Как и JFrame поддерживает закрытие окна, а в остальном сходен с другими окнами Swing.
   При создании диалоговых окон Swing необходимо указать «родительское окно», которым может быть окно с рамкой JFrame или другое диалоговое окно JDialog. Имеется также конструктор, не требующий «родительского» окна, но использующий вспомогательное прозрачное окно.


   Элементы управления - кнопки, флажки, переключатели, выключатели, меню и его элементы, и д.р. (JButton, JToggleButton, ButtonGroup, JRadioButton, JCheckBox)


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

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

   Переключатели JRadioButton
      Переключатель JRadioButton унаследован от выключателя JToggleButton и отличается от него только внешним видом.
      JRadioButton используют, как правило, при объединении нескольких переключателей в группу и реализации выбора «один из многих». По одиночке в интерфейсе их практически не используют; обычно эту роль исполняют флажки.

   Флажки JCheckBox
      Также как и переключатели, отличаются от выключателей только внешним видом.
      Флажки используются там, где нужно предоставить пользователю возможность что-то включить или выключить. Они также могут группироваться, но, в отличие от JRadioButton, никогда не реализуют выбор «один из нескольких», а всегда позволяют выбрать несколько равноценных вариантов.


   Текстовые компоненты библиотеки Swing (JTextField, JTextArea, JTextPane)

   Пакет javax.swing.text библиотеки Swing содержит компоненты для работы с текстом.
   Основные возможности всех текстовых компонентов Swing и их базовая архитектура описаны в абстрактном классе JTextComponent. Именно от этого класса унаследованы все текстовые компоненты Swing, будь то простое текстовое поле или многофункциональный редактор.
   Помимо того что в данном базовом классе задаются общие для всех текстовых компонентов свойства и действия (такие как цвет выделенного текста, цвет самого выделения, курсор, сам текст, механизмы работы с буфером обмена), в нем описывается взаимодействие практически всех составных частей пакета javax.swing.text.
   Текстовые компоненты имеют архитектуру MVC. Модель текстовых компонентов представлена довольно простым интерфейсом Document, который позволяет получать информацию об изменениях в документе и хранящийся в нем текст, а также при необходимости изменять полученный текст.

   JLabel - текст с иконкой

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

   Списки (JList, JCombobox)

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

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

   JComboBox позволяет также вводить собственные значения.


   Панели JTabbedPane, JSplitPane, JScrollPane, JViewPort

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

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

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

   Компонента JViewPort является основой панели прокрутки, и который можно использовать в приложениях как «видоискатель».

   Таблицы JTable

   Таблица JTable позволяет отображать двухмерную информацию в виде строк и столбцов, настраивать и сортировать данные, выводить их в любом подходящем виде, управлять заголовками таблицы и ее выделенными элементами.
   JTable использует три модели, поставляющие ей данные и сохраняющие изменения при изменении этих данных.
   Первая и самая важная модель реализует интерфейс TableModel и хранит данные ячеек таблицы и дополнительную служебную информацию об этих ячейках.
   Вторая модель реализует интерфейс TableColumnModel и управляет столбцами таблицы. TableColumnModel позволяет добавлять, перемещать и находить столбцы, узнавать об изменениях в их расположении, с ее помощью можно изменить расстояние между столбцами и находящимися в них ячейками.
   Модель TableColumnModel имеет собственную модель выделения списка ListSelectionModel. Так что можно формально говорить о четырех моделях таблицы JTable. Просто одна из этих моделей вызывается неявно, через другую модель.
   Третья модель таблицы SelectionModel используется для выделения списка. Она управляет выделением строк таблицы и не затрагивает столбцы.


   Инструмент для отображения иерархической информации JTree

   Отображение иерархической информации в библиотеке Swing реализуется с помощью дерева JTree, основой которого является корневой узел root.
   Потомки корневого узла, могут иметь своих потомков, и т.д.
   Информация о ветвях дерева хранится в узлах nodes.
   Узел без потомков является листом leaf дерева.
   Потомки одного узла являются близнецами siblings.
   Путь path в дереве определяет последовательность узлов, начиная от корня, по которым следует пройти, чтобы найти нужный нам узел.
   Пакет javax.swing.tree хранит основные «строительные» классы деревьев Swing : интерфейс TreeNode, описывающий узел дерева, модель дерева с его данными, реализующую интерфейс TreeModel, модель выделения узлов дерева TreeSelectionModel, позволяющую настраивать различные режимы выделения, класс TreePath, описывающий путь в дереве.


   Визуальные компоненты, позволяющие устанавливать данные в определенном диапазоне и отображать информацию, представляющую часть некоторого диапазона (JSlider, JProgressbar, JSpinner)

   Ползунки JSlider предоставляют пользователю наглядную возможность плавного изменения значения от минимального до максимального.
   Индикатор процесса JProgressBar используется для динамического отображения выполнения какого-либо процесса в приложении и позволяет оценить, на каком этапе выполнения находится интересующий нас процесс и сколько ориентировочно времени он может еще занять.
   Счетчик JSpinner позволяет выбрать значение из некоторого набора, который можно «прокручивать» в обе стороны. В отличие от списков (раскрывающийся список JComboBox, простой список JList) на экран не вызывается всплывающее окно и количество элементов в счетчике JSpinner может быть неограниченным.

   Диалоговые окна JOptionPane

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

   Диалоговое окно JFileChooser

   Компонент JFileChooser представляет собой контейнер, в котором расположены несколько компонентов, списков и кнопок, «управляющих» выбором файлов.
   JFileChooser - это компонент, унаследованный от класса JComponent, так что можно включить его в любое место интерфейса.
   С этим компонентом просто настроить и вывести на экран несложное диалоговое окно для открытия файла или сохранения в нем данных.

Не без использования java-online.ru (хороший ресурс)

суббота, 2 марта 2019 г.

8 Что такое библиотека JAVA API и как её использовать

   Вместе с Java поставляются сотни готовых классов, которые содержатся в библиотеке Java API.



   API (application programming interface) - программный интерфейс приложения, интерфейс прикладного программирования - описание способов (набор классов, процедур, функций, структур или констант), которыми одна компьютерная программа может взаимодействовать с другой программой.
   Обычно API входит в описание какого-либо интернет-протокола, программного каркаса (фреймворка) или стандарта вызовов функций операционной системы.
   Часто реализуется отдельной программной библиотекой или сервисом операционной системы.
   Используется программистами при написании приложений.
 
   Число API для платформы Java огромно.
   Есть три типа Java API:
1) официальный основной Java API, содержащийся в JDK или JRE, в одном из вариантов Java. Три варианта платформы Java: Java ME (Micro edition), Java SE (Standard edition) и Java EE (Enterprise edition).
2) дополнительные официальные API, которые можно загрузить отдельно. Спецификации этих API определяются в соответствии с Java Specification Request (JSR), а иногда и некоторые из этих API позднее включаются в основные API платформы (наиболее ярким примером такого рода является Swing).
3) неофициальный API, разработанный третьими сторонами, но не связанный с JSR.
   Третьи стороны могут свободно реализовать любые спецификации JSR для официального API (даже для основного API языка), при условии, что они соответствуют Technology Compatibility Kit (TCK) для данного JSR (TCK представляет собой набор тестов для проверки соответствия реализаций для JSR). Результатом этой свободы является то, что у многих официальных API больше реализаций, чем эталонных реализаций от Sun

   Документацию по Java, в т.ч. API можно посмотреть здесь:
https://docs.oracle.com/en/java/index.html
https://www.oracle.com/technetwork/java/api-141528.html


   Пример использования API:

   Для того, чтобы увидеть в браузере строчку «Hello, world!», достаточно создать HTML-документ с минимальным заголовком и простейшим телом, содержащим данную строку.
   Когда браузер откроет этот документ, программа-браузер передаст имя файла (или уже открытый дескриптор файла) библиотеке, обрабатывающей HTML-документы.
   Та, в свою очередь, при помощи API операционной системы прочитает этот файл и разберётся в его устройстве, затем последовательно вызовет через API библиотеки стандартных графических примитивов операции типа «очистить окошко», «написать „Hello, world!“ выбранным шрифтом».
   Во время выполнения этих операций библиотека графических примитивов обратится к библиотеке оконного интерфейса с соответствующими запросами, и уже эта библиотека обратится к API операционной системы, чтобы записать данные в буфер видеокарты.


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

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

   *Пакеты, названия которых начинается с javax изначально появились в Java как расширения, а потом повысили свой статус. 

   Чтобы использовать класс из библиотеки API нужно знать, в каком пакете он находится.
   Примеры пакетов из библиотеки Java API:

   а) Пакет  java.lang
      Этот пакет библиотеки всегда импортируется в любое Java-приложение, поскольку содержит базу, без которой в принципе не возможно программировать
      Содержит классы System (System.out.println), String, Double, Enum, Math (Math.random()) и т. д.

   б) Пакет java.util
      Этот пакет библиотеки содержит набор классов-утилит и интерфейсов, реализующих широко используемые структуры данных - коллекции.
      Название этого пакета библиотеки - Java collections framework.
      Это коллекция стандартных структур данных, таких как списки, карты, очереди, стеки.
      Несмотря на то, что это framework, он не имеет явных критических участков кода и работает как библиотека.
      Содержит, к примеру, класс ArrayList.

   в) Пакеты для создания графического интерфейса
      - java.awt (от Abstract Window Toolkit)
      - javax.swing
      Служит для работы с GUI , содержит классы пользовательского графического интерфейса (GUI)
      Пакет javax.swing, в прошлом являлся  расширением пакета java.awt.
      ПО сравнению с более ранним пакетом библиотеки AWT, Swing предоставляет более гибкие интерфейсные компоненты. В отличие от AWT, компоненты Swing разработаны для кросс-платформенной работы, в то время как компоненты AWT повторяют интерфейс исполняемой платформы без изменений.
      AWT использует только стандартные элементы операционной системы для отображения, т.е. для каждого элемента создается отдельный объект ОС (окно), в связи с чем, AWT не позволяет создавать элементы произвольной формы (возможно использовать только прямоугольные компоненты).
      Элементы управления на основе AWT всегда отображаются поверх Swing-элементов, т.к. все Swing компоненты отображаются на поверхности контейнера.

г) Пакеты для работы с аудиофайлами
   - javax.sound.midi
   - javax.sound.midi.spi
   - javax.sound.sampled
   - javax.sound.sampled.spi

д) Набор пакетов для обеспечения безопасных Интернет-коммуникаций
    Этот набор называется Java Secure Socket Extension, JSSE  - Расширение Java для безопасных сокетов.
   Он предназначен для реализации безопасных сетевых соединений. В JSSE реализованы протоколы SSL и TLS. Библиотека включает функциональность по шифрованию данных, аутентификации сервера и клиента, проверки целостности сообщений.
   - javax.net
   - javax.net.ssl
   - java.security.cert

е) Набор пакетов для контроля (мониторинга) и управления приложениями, системными объектами, устройствами (например, принтерами) и сервис-ориентированными (компьютерными) сетями.
   Данные ресурсы представляются MBean-объектами (от англ. Managed Bean - управляемый Java Bean).
   Этот набор пакетов называется Java Management Extensions, JMX - Управленческие расширения Java.
   Для разработки приложений, использующих данную технологию, может применяться Java Dynamic Management Kit. Предоставляемый интерфейс позволяет динамически управлять классами.

   - javax.management
   - javax.management.loading
   - javax.management.modelmbean
   - javax.management.monitor
   - javax.management.openmbean
   - javax.management.relation
   - javax.management.remote
   - javax.management.remote.rmi
   - javax.management.timer

ж) Пакет java.io
   Применяется для чтения файлов, работающих потоками, объектами класса Pipe и т.д.

з) Пакет java.nio
   Является альтернативой java.io. Эта библиотека отвечает за неблокирующий ввод-вывод, позволяя интенсивно использовать операции ввода-вывода.


   Использовать библиотечные классы в своей программе можно двумя способами:
      1) Набирать полное имя класса из библиотеки Java каждый раз при его использовании.
          К примеру, для класса ArrayList из пакета java.util полное имя выглядит так:
java.util.ArrayList

          Чтобы упростить себе жизнь, используют второй способ:

      2) Предварительно импортировать этот класс, поместив оператор import в начале своего исходного файла:

import java.util.ArrayList;
public class MyClass {...}

   *Исключение – пакет java.lang, который как будто импортируется по умолчанию


   Основными проблемами существующих многоуровневых систем API являются:

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

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

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