Избранное сообщение

Использование списков для ввода данных в Excel / Office / Excel

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

Ездил на экскурсию на хлебокомбинат.
Больше я хлеб не ем...
Ездил на экскурсию на мясокомбинат.
Больше я мясо не ем...
Завтра экскурсия на ликеро-водочный завод.
Я не поеду...

воскресенье, 30 сентября 2018 г.

Скульптура лошадей. Бучанский городской парк. Буча, Киевская обл. / Фото из личного архива


Смотри также Бучанский парк:

Скульптура во французском дворике. http://fetisovvs.blogspot.com/2017/08/blog-post_13.html
Скульптура игры в чехарду. http://fetisovvs.blogspot.com/2017/08/blog-post_48.html
Лесовик возле старого дуба. http://fetisovvs.blogspot.com/2017/08/blog-post_54.html
Сундучок с сокровищами возле старого дуба. http://fetisovvs.blogspot.com/2017/08/blog-post_17.html
Мостик через маленький канал. http://fetisovvs.blogspot.com/2018/09/blog-post_25.html
Выход из Бучанского городского парка. http://fetisovvs.blogspot.com/2017/08/blog-post_29.html



Смотри также Буча:

    Памятник М.Булгакову. http://fetisovvs.blogspot.com/2017/08/blog-post_69.html
    Город цветочных клумб. http://fetisovvs.blogspot.com/2015/08/blog-post_3.html
    Площадь. http://fetisovvs.blogspot.com/2015/08/blog-post_10.html
    Мраморный шар. http://fetisovvs.blogspot.com/2017/07/blog-post_2.html
    Скульптура "Речка судьбы". http://fetisovvs.blogspot.com/2017/06/blog-post_28.html
    Парковая скульптура. http://fetisovvs.blogspot.com/2015/08/blog-post_9.html
    Памятник войнам-афганцам. http://fetisovvs.blogspot.com/2015/08/blog-post_29.html
    Зеленые изгороди. http://fetisovvs.blogspot.com/2015/08/blog-post_38.html
    Кофейня. http://fetisovvs.blogspot.com/2015/08/blog-post_23.html
    Просто архитектура. http://fetisovvs.blogspot.com/2015/08/blog-post_19.html

    Как вставить (наложить) рисунок в рисунок / Программное обеспечение. Мультимедиа

    Эта проблема разрешима во всех графических редакторах, поэтому пользователям, достаточно уверенно с ними работающим, этот пост читать незачем. Он предназначен для тех из них, кто достаточно редко имеет дело с графическими редакторами. 
    К счастью, вам не придется устанавливать дополнительную программу, тот самый графический редактор: ведь в Windows уже имеет таковой в своем составе - Paint. И пусть он и довольно простой, но с его помощью вы сможете выполнить, на мой взгляд, все необходимый "простому" пользователю действия. Найти Paint можно в составе стандартных программ.
    Итак запускаем Paint и загружаем в него рисунок, в который необходимо вставить другой рисунок.
    Раскрываем список кнопки меню "Вставить" и выбираем из него пункт "Вставить из", что приведет к появлению стандартного окна поиска файла. 



    Находим в нем нужный файл и щелкаем кнопку "Открыть". Вот, собственно, и все.


    Дальше вам остается только переместить курсором вставленное изображение в нужное место основного файла.


    Смотри также:

    Лучший плеер для Windows 10. http://fetisovvs.blogspot.com/2017/08/windows-10_19.html
    Программы для записи видео с экрана компьютера. http://fetisovvs.blogspot.com/2017/08/blog-post_20.html
    3D Youtube Downloader: Как просто скачать и конвертировать в популярные форматы видео из YouTube. http://fetisovvs.blogspot.com/2018/03/3d-youtube-downloader-youtube.html
    4K Video Downloader — бесплатная программа для скачивания с YouTube видео 4К и 8К. http://fetisovvs.blogspot.com/2018/06/4k-video-downloader-youtube-4-8.html
    Как пользоваться плеером AIMP, как настроить aimp3. http://fetisovvs.blogspot.com/2016/10/aimp-aimp3.html
    Как быстро разделить видеофайл на фрагменты. http://fetisovvs.blogspot.com/2014/05/blog-post_2311.html
    Как соединить несколько видео фрагментов в один файл. http://fetisovvs.blogspot.com/2014/05/blog-post_1692.html
    Ashampoo Photo Optimizer 7 — оптимизация фото одним кликом. http://fetisovvs.blogspot.com/2018/06/ashampoo-photo-optimizer-7.html
    DAEMON Tools Lite — эмулятор виртуальных CD/DVD приводов. http://fetisovvs.blogspot.com/2015/02/daemon-tools-lite-cddvd.html
    Как вырезать музыку из видео. http://fetisovvs.blogspot.com/2016/01/blog-post_26.html
    Free Studio — бесплатный пакет мультимедийных программ. http://fetisovvs.blogspot.com/2015/02/free-studio.html
    Free Video Editor — редактирование и удаление фрагментов из видео. http://fetisovvs.blogspot.com/2014/11/free-video-editor.html
    Freemake Video Converter: конвертор видео и не только... http://www.kv.by/content/freemake-video-converter-konvertor-video-i-ne-tolko
    Учимся рисовать в графическом редакторе Inkscape. http://fetisovvs.blogspot.com/2018/07/inkscape.html
    Как конвертировать DVD-диск в формат MKV. http://fetisovvs.blogspot.com/2018/07/dvd-mkv.html
    Как повернуть видеоролик? http://fetisovvs.blogspot.com/2015/04/blog-post.html
    Как ограничить уровень громкости звука в компьютере. http://fetisovvs.blogspot.com/2017/03/blog-post_14.html
    Как обрезать видео и вырезать отдельные кадры с помощью «Киностудии» Windows Live. http://fetisovvs.blogspot.com/2017/01/windows-live.html
    Программа для восстановления удаленных фотографий — ФотоДОКТОР! http://fetisovvs.blogspot.com/2016/12/blog-post_15.html
    Видеоредактор для Windows 10: особенности, виды, преимущества. http://fetisovvs.blogspot.com/2017/09/windows-10_15.html
    Как обрезать видео штатными средствами Windows 10. http://fetisovvs.blogspot.com/2018/04/windows-10.html

    Американские СМИ рассказали о «страшном российском кибероружии»

    Российские спецслужбы тайно разработали новый вид вредоносной программы, которую невозможно удалить с компьютера. Как сообщает РИА Новости, об этом пишет американское издание Daily Beast со ссылкой на доклад компании ESET на конференции по безопасности Blue Hat.

    Как утверждает издание, за создание этой вредоносной программы ответственна хакерская группа Fancy Bear, якобы связанная с российской разведкой. Новый вирус разработали на основе кода шпионской программы, предложенной в 2015 году другой хакерской группой Hacking Team. "Российские хакеры" позаимствовали код и усовершенствовали его, говорится в материале Daily Beast.

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

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

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

    Как отмечает РБК, в мае нынешнего года Федеральное бюро расследований (ФБР) США выпустило рекомендации для пользователей, чьи компьютерные системы оказались под ударом хакеров из группировки Fancy Bear. По данным ФБР, созданный ими вирус способен блокировать интернет-трафик и собирать проходящую через роутер информацию, а также полностью отключать зараженные устройства. Всем пострадавшим было рекомендовано перезагрузить маршрутизаторы и сетевые накопители, а также обновить программное обеспечение.

    Как записать звонки по Skype в Windows

    До относительно недавнего времени сделать аудио- или видеозапись звонков по Skype можно было только с помощью специального стороннего софта. Но, начиная с версии 8, десктопная программа Skype для Windows кардинально преобразилась, обрела новый интерфейс под стать UWP-приложению Win10, а в числе функциональных улучшений получила возможность видеозаписи звонков.
    Однако эта возможность программы построена на принципах честности и согласованности действий: собеседник узнает о старте записи, более того, как и записывающий разговор, получит доступ к этой записи. Для фиксации разговоров скрыто, без ведома собеседника по-прежнему понадобится помощь сторонних программ.
    Как записать звонки по Skype – открыто с помощью функционала самой программы и скрыто посредством другого софта?

    1. Запись звонков самой программой Skype

    Чтобы начать записывать разговор по Skype, в окне десктопной программы или в приложении Win10 в режиме активного звонка жмём кнопку-плюсик дополнительных опций и выбираем, соответственно, «Начать запись».

    Skype

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

    Собеседник в Скайпе

    Запись прекращается по окончании звонка или в любой момент по нашему требованию.

    Остановить запись

    После чего любой из собеседников может просмотреть видео в общем чате, а при необходимости – ещё и сохранить его в файл MP4.

    Сохранить

    Сам принцип ведения записи построен на облачной технологии. Разговор не сохраняется автоматически в видео- или аудиофайл, как при использовании сторонних программ. Разговор хранится, как и наша история или текстовая переписка, на серверах Microsoft с подвязкой к учётной записи мессенджера. Но хранится только 30 дней. Именно столько нам даётся, чтобы понять, нужен нам этот разговор или нет.

    2. oCam Screen Recorder

    Для фиксации разговоров по Skype существует, как упоминалось, специальный тип софта. В сути своей он ничем не отличается от обычных программ для захвата видео с экрана. Но такой специальный софт заточен под Skype и может предложить удобные функции для тех, кто активно общается с помощью этого мессенджера и постоянно записывает свои разговоры. Как, например, функция автоматической фиксации всех звонков в фоне. Такие программы обычно относятся к платным решениям, и их покупка вряд ли будет оправдана в единичных случаях необходимости записать разговор с кем-то.
    Чтобы записать единичный какой-то разговор, можем взять любую бесплатную программу для видеозахвата экрана. К примеру, oCam Screen Recorder. Это захламлённый рекламой, но функциональный продукт с поддержкой видеозахвата в среде 3D, с разнообразием выбора кодеков и видеоформатов. Чтобы записать беседу по Skype, запускаем oCam Screen Recorder. Жмём кнопку «Размер», далее «Select область» и указываем окно Скайпа в качестве записываемой области экрана.

    oCam Screen Recorder

    Можем нажать кнопку «Кодеки» и указать нужный кодек и формат, если по каким-то причинам предустановленные H.264 и MP4 не устраивают.

    Кодеки

    Далее жмём «Звук» и указываем программе, чтобы она записывала и системные звуки (нужно для фиксации того, что говорит собеседник), и сигнала с микрофона (нужно для фиксации нашей речи).

    Звук
    И можем жать красную кнопку «Запись». Для завершения нажимаем, соответственно, кнопку «Остановить». И с помощью кнопки «Открыть» оперативно получаем доступ к месту хранения записанных видеофайлов.
    ***
    Ну а теперь о том самом специальном софте, заточенном под Skype.

    3. Amolto Call Recorder for Skype

    Программа Amolto Call Recorder for Skype после установки в среду Windows внедряется в системным трей, где впредь будет поджидать входящего или исходящего звонка по Skype, чтобы записать его. И, естественно, чтобы всегда быть на чеку, она будет запускаться вместе с Windows. Автостарт фиксации разговоров предусмотрен по умолчанию. О начале и завершении этого процесса программа уведомит своим сообщением.
    Системным трей
    Получить доступ к записям можно из главного окна: здесь есть ссылки на последний звонок и всю медиатеку записей.
    Amolto Call Recorder for Skype
    В медиатеке записями можно управлять – воспроизводить их, удалять, редактировать свойства файлов, открывать в проводнике и т.п.
    Медиатека
    Программа полностью бесплатна в части создания аудиозаписей разговоров. Для видеофиксации разговоров необходима Premium-версия за $30.

    4. Evaer Skype video call recorder

    Evaer Skype video call recorder – ещё одна программа, заточенная специально под аудио- и видеозапись звонков по Скайпу. Она, как предыдущая, также предназначена для постоянной фиксации разговоров. По умолчанию запускается вместе с Windows, обитает в системном трееи пишет все звонки подряд.
    В системном трее
    В её небольшом окошке, кроме прочих опций, увидим медиатеку созданных записей, где ненужные из них можем удалить, а к нужным получить доступ в проводнике.
    Evaer Skype video call recorder
    В числе возможностей этой программы – выбор различных режимов захвата видео и звука.
    Режимы аудиозаписи
    Landscape
    В базовой редакции, предусматривающей в принципе все необходимые функции, программа стоит $20.
    Если Вам нравятся статьи, заметки и другой интересный материал представленный на сайте Белые окошки и у вас есть непреодолимое желание поддержать этот скромный проект тогда выберите один из двух видов стратегии поддержки на специальной странице - Страница с донатом

    суббота, 29 сентября 2018 г.

    Счастье - есть! / Забавные и милые




    Абстрактный CRUD от репозитория до контроллера: что ещё можно сделать при помощи Spring + Generics / Программирование на Java

    Совсем недавно на Хабре мелькнула статья коллеги, который описал довольно интересный подход к совмещению Generics и возможностей Spring. Мне она напомнила один подход, который я использую для написания микросервисов, и именно им я решил поделиться с читателями.



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

    Сразу ресурсы.
    Ветка, как я не делаю: standart_version.
    Подход, о котором рассказывается в статье, в ветке abstract_version.

    Я собрал проект через Spring Initializr, добавив фреймворки JPA, Web и H2. Gradle, Spring Boot 2.0.5. Этого будет вполне достаточно.




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

    Классический вариант.

    В ресурсах примера представлены несколько сущностей и методов для них, но в статье пусть у нас будет только одна сущность User и только один метод save(), который мы протащим от репозитория через сервис до контроллера. В ресурсах же их 7, а вообще Spring CRUD / JPA Repository позволяют использовать около дюжины методов сохранения / получения / удаления плюс Вы можете пользоваться, к примеру, какими-то своими универсальными. Также, мы не будем отвлекаться на такие нужные вещи, как валидацию, мапинг dto и прочее. Это Вы сможете дописать сами или изучить в других статьях Хабра.

    Domain:


    @Entity
    public class User implements Serializable {
    private Long id;
    private String name;
    private String phone;
    @Id
    @GeneratedValue
    public Long getId() {
    return id;
    }
    public void setId(Long id) {
    this.id = id;
    }
    @Column(nullable = false)
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    @Column
    public String getPhone() {
    return phone;
    }
    public void setPhone(String phone) {
    this.phone = phone;
    }
    //equals, hashcode, toString
    }

    Repository:


    @Repository
    public interface UserRepository extends CrudRepository<User, Long> {
    }

    Service:


    public interface UserService {
    Optional<User> save(User user);
    }

    Service (имплементация):


    @Service
    public class UserServiceImpl implements UserService {
    private final UserRepository userRepository;
    @Autowired
    public UserServiceImpl(UserRepository userRepository) {
    this.userRepository = userRepository;
    }
    @Override
    public Optional<User> save(User user) {
    return Optional.of(userRepository.save(user));
    }
    }

    Controller:


    @RestController
    @RequestMapping("/user")
    public class UserController {
    private final UserService service;
    @Autowired
    public UserController(UserService service) {
    this.service = service;
    }
    @PostMapping
    public ResponseEntity<User> save(@RequestBody User user) {
    return service.save(user).map(u -> new ResponseEntity<>(u, HttpStatus.OK))
    .orElseThrow(() -> new UserException(
    String.format(ErrorType.USER_NOT_SAVED.getDescription(), user.toString())
    )); }
    }


    У нас получился некий набор зависимых классов, которые помогут нам оперировать сущностью User на уровне CRUD. Это в нашем примере по одному методу, в ресурсах их больше. Этот нисколько не абстрактный вариант написания слоёв представлен в ветке standart_version.


    Допустим, нам нужно добавить ещё одну сущность, скажем, Car. Мапить на уровне сущностей мы их друг к другу не будем (если есть желание, можете замапить).


    Для начала, создаём сущность.

    @Entity
    public class Car implements Serializable {
    private Long id;
    private String brand;
    private String model;
    @Id
    @GeneratedValue
    public Long getId() {
    return id;
    }
    public void setId(Long id) {
    this.id = id;
    }
    //геттеры, сеттеры, equals, hashcode, toString
    }


    Потом создаём репозиторий.

    public interface CarRepository extends CrudRepository<Car, Long> {
    }


    Потом сервис…

    public interface CarService {
    Optional<Car> save(Car car);
    List<Car> saveAll(List<Car> cars);
    Optional<Car> update(Car car);
    Optional<Car> get(Long id);
    List<Car> getAll();
    Boolean deleteById(Long id);
    Boolean deleteAll();
    }


    Потом имплементация сервиса…… Контроллер………


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


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

    Итак, абстракции на основе типовых параметров.



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


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


    У всех сущностей есть как минимум одно общее поле (обычно больше). Это ID. Вынесем это поле в отдельную абстрактную сущность и унаследуем от неё User и Car.

    AbstractEntity:


    @MappedSuperclass
    public abstract class AbstractEntity implements Serializable {
    private Long id;
    @Id
    @GeneratedValue
    public Long getId() {
    return id;
    }
    public void setId(Long id) {
    this.id = id;
    }
    }


    Не забудьте пометить абстракцию аннотацией @MappedSuperclass — Hibernate тоже должен узнать, что это абстракция.

    User:


    @Entity
    public class User extends AbstractEntity {
    private String name;
    private String phone;
    //...
    }


    С Car, соответственно, то же самое.


    В каждом слое у нас, помимо бинов, будет один интерфейс с типовыми параметрами и один абстрактный класс с логикой. Кроме репозитория — благодаря специфике Spring Data JPA, здесь всё будет намного проще.


    Первое, что нам потребуется в репозитории — общий репозиторий.

    CommonRepository:


    @NoRepositoryBean
    public interface CommonRepository<E extends AbstractEntity> extends CrudRepository<E, Long> {
    }


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

    UserRepository:


    @Repository
    public interface UserRepository extends CommonRepository<User> {
    }


    На этом, благодаря особенностям Spring Data JPA, настройка репозитория заканчивается — всё будет работать и так. Далее следует сервис. Мы должны создать общий интерфейс, абстракцию и бин.

    CommonService:


    public interface CommonService<E extends AbstractEntity> { {
    Optional<E> save(E entity);
    //какое-то количество нужных нам методов
    }

    AbstractService:


    public abstract class AbstractService<E extends AbstractEntity, R extends CommonRepository<E>>
    implements CommonService<E> {
    protected final R repository;
    @Autowired
    public AbstractService(R repository) {
    this.repository = repository;
    }
    //другие методы, переопределённые из интерфейса
    }


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

    UserService:


    @Service
    public class UserService extends AbstractService<User, UserRepository> {
    public UserService(UserRepository repository) {
    super(repository);
    }
    }


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


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


    Контроллер строится по тому же принципу: интерфейс, абстракция, бин.

    CommonController:


    public interface CommonController<E extends AbstractEntity> {
    @PostMapping
    ResponseEntity<E> save(@RequestBody E entity);
    //остальные методы
    }

    AbstractController:


    public abstract class AbstractController<E extends AbstractEntity, S extends CommonService<E>>
    implements CommonController<E> {
    private final S service;
    @Autowired
    protected AbstractController(S service) {
    this.service = service;
    }
    @Override
    public ResponseEntity<E> save(@RequestBody E entity) {
    return service.save(entity).map(ResponseEntity::ok)
    .orElseThrow(() -> new SampleException(
    String.format(ErrorType.ENTITY_NOT_SAVED.getDescription(), entity.toString())
    )); }
    //другие методы
    }

    UserController:


    @RestController
    @RequestMapping("/user")
    public class UserController extends AbstractController<User, UserService> {
    public UserController(UserService service) {
    super(service);
    }
    }


    Это вся структура. Она пишется один раз.

    Что дальше?



    И вот теперь давайте представим, что у нас появилась новая сущность, которую мы уже унаследовали от AbstractEntity, и нам нужно прописать для неё такую же цепочку. На это у нас уйдёт минута. И никаких копипаст и исправлений.


    Возьмём уже унаследованный от AbstractEntity Car.

    CarRepository:


    @Repository
    public interface CarRepository extends CommonRepository<Car> {
    }

    CarService:


    @Service
    public class CarService extends AbstractService<Car, CarRepository> {
    public CarService(CarRepository repository) {
    super(repository);
    }
    }

    CarController:


    @RestController
    @RequestMapping("/car")
    public class CarController extends AbstractController<Car, CarService> {
    public CarController(CarService service) {
    super(service);
    }
    }


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

    Заключение


    Конечно, в примере описана этакая сферическая ситуация, в которой CRUD для каждой сущности имеет одинаковую логику. Так не бывает — какие-то методы Вам всё равно придётся переопределять в бине или добавлять новые. Но это будет происходить от конкретных потребностей обработки сущности. Хорошо, если процентов 60 от общего количества методов CRUD будет оставаться в абстракции. И это будет хорошим результатом, потому что чем больше мы генерим лишнего кода вручную, тем больше времени мы тратим на монотонную работу и тем выше риск ошибки или опечатки.


    Надеюсь, статья была полезна, спасибо за внимание.

    UPD.


    Благодаря предложению aleksandy удалось вынести инициализацию бина в конструктор и тем самым значительно улучшить подход. Если Вы видите, как ещё можно улучшить пример, пишите в комментариях, и, возможно, Ваши предложения будут внесены.

    Источник: https://habr.com/post/423741/?utm_source=habrahabr&utm_medium=rss&utm_campaign=423741

    Смотри также:

    Зачем нужна Java. http://fetisovvs.blogspot.com/2014/07/java.html
    Разбор основных концепций параллелизма. http://fetisovvs.blogspot.com/2018/04/java.html
    Первый контакт с «var» в Java 10. http://fetisovvs.blogspot.com/2018/01/var-java-10-java.html
    JAVA 9. Что нового? http://fetisovvs.blogspot.com/2017/10/java-9-java.html
    Руководство по Java 9 для тех, кому приходится работать с legacy-кодом. http://fetisovvs.blogspot.com/2018/08/java-9-legacy-java.html
    Концепции объектно-ориентированного программирования — ООП в Java. http://fetisovvs.blogspot.com/2017/01/java-java.html
    Анимации в Android по полочкам (Часть 1. Базовые анимации). http://fetisovvs.blogspot.com/2018/02/android-1-java.html
    Двести пятьдесят русскоязычных обучающих видео докладов и лекций о Java. http://fetisovvs.blogspot.com/2015/12/java-5-java-java.html
    Абстрактные классы и методы. http://fetisovvs.blogspot.com/2017/02/java.html
    Полное руководство по Java Reflection API. Рефлексия на примерах. http://fetisovvs.blogspot.com/2017/02/java-reflection-api-java.html
    Микросервисы для Java программистов. Практическое введение во фреймворки и контейнеры. http://fetisovvs.blogspot.com/2017/10/java-java.html
    Микросервисы для Java программистов. Практическое введение во фреймворки и контейнеры. (Часть 3). http://fetisovvs.blogspot.com/2017/10/java-3-java.html
    ТОП-3 способа конвертировать массив в ArrayList. Пример на Java. http://fetisovvs.blogspot.com/2016/09/3-arraylist-java-java.html
    Ввод–вывод в Java. http://fetisovvs.blogspot.com/2016/05/java-java_28.html
    Enum-Всемогущий. http://fetisovvs.blogspot.com/2017/02/enum-java.html
    Массивы в Java. Создание и обработка. http://fetisovvs.blogspot.com/2017/10/java-java_18.html
    Arrays, Collections: Алгоритмический минимум. http://fetisovvs.blogspot.com/2017/12/arrays-collections.html
    Популярные методы для работы с Java массивами. http://fetisovvs.blogspot.com/2016/09/java-java_29.html
    Пример использования метода replace в Java. Как заменить символ в строке? http://fetisovvs.blogspot.com/2017/01/replace-java-java.html
    Класс Scanner в Java — описание и пример использования. http://fetisovvs.blogspot.com/2017/01/scanner-java-java.html
    Пример использования метода trim в Java: как удалить пробелы в начале и конце строки? http://fetisovvs.blogspot.com/2017/01/trim-java-java.html
    Spark — Потрясающий веб-микрофреймворк для Java. http://fetisovvs.blogspot.com/2017/10/spark-java-java.html
    Чтение и запись CSV файла с помощью SuperCSV. http://fetisovvs.blogspot.com/2017/01/csv-supercsv-java-java.html
    Конструкция try/catch/finally (исключения). http://fetisovvs.blogspot.com/2017/01/trycatchfinally-java.html
    1000+ часов видео по Java на русском. http://fetisovvs.blogspot.nl/2017/06/1000-java-java.html
    Раздача халявы: нетормозящие треды в Java. Project Loom. http://fetisovvs.blogspot.com/2018/09/java-project-loom-java.html

    Шпаргалка Java программиста 7.1 Типовые задачи: Оптимальный путь преобразования InputStream в строку. http://fetisovvs.blogspot.com/2016/04/java-71-inputstream-java.html
    Шпаргалки Java программиста 10: Lombok. http://fetisovvs.blogspot.nl/2017/12/java-10-lombok-java.html
    Шпаргалки Java программиста 9: Java SE — Шпаргалка для собеседований и повторений. http://fetisovvs.blogspot.com/2017/12/java-9-java-se-java.html
    Шпаргалка Java программиста 8. Библиотеки для работы с Json (Gson, Fastjson,
    LoganSquare, Jackson, JsonPath и другие). http://fetisovvs.blogspot.com/2016/04/java-8-json-gson-fastjson-logansquare.html
    Java 8 и паттерн Стратегия. http://fetisovvs.blogspot.com/2018/03/java-8-java.html
    Java EE Concurency API. http://fetisovvs.blogspot.com/2018/08/java-ee-concurency-api-java.html
    Реализация ООП-наследования в классах, работающих с SQL и MS Entity Framework. http://fetisovvs.blogspot.com/2017/02/sql-ms-entity-framework.html
    Как установить соединение с СУБД MySQL в IntelliJ IDEA в редакции Community. http://fetisovvs.blogspot.com/2016/04/mysql-intellij-idea-community-java.html
    Максимально простой в поддержке способ интеграции java-клиента с java-сервером. http://fetisovvs.blogspot.com/2018/09/java-java-java.html
    Как с помощью maven работать с библиотеками, которых в maven нет. http://fetisovvs.blogspot.com/2017/03/maven-maven-java.html
    Проекты по созданию компиляторов из Java в JavaScript и исполняемые файлы. http://fetisovvs.blogspot.com/2018/01/java-javascript-java.html
    Реактивное программирование с JAX-RS. http://fetisovvs.blogspot.com/2018/09/jax-rs-java.html

    Диагностика утечек памяти в Java. http://fetisovvs.blogspot.com/2017/03/java-java_18.html
    Spring AOP и JavaConfig в плагинах для Atlassian Jira. http://fetisovvs.blogspot.com/2018/04/spring-aop-javaconfig-atlassian-jira.html
    Блеск и нищета Java для настольных систем. 
    http://fetisovvs.blogspot.com/2018/04/java-haulmont-java.html
    Разбор задачек от Одноклассников на JPoint 2018. http://fetisovvs.blogspot.com/2018/04/jpoint-2018-java.html
    Программируем… выход из лабиринта. http://fetisovvs.blogspot.com/2015/10/java.html
    Основы работы с IntelliJ IDEA. Интерфейс программы. http://fetisovvs.blogspot.com/2016/09/intellij-idea-java.html
    Ускоряем время сборки и доставки java web приложения. http://fetisovvs.blogspot.com/2018/03/java-web-java.html
    Открытый урок Java Enterprise «CDI in action». http://fetisovvs.blogspot.com/2018/09/java-enterprise-cdi-in-action-java.html
    «Мы все стремимся к сложности, а потом с ней боремся»: интервью с Венкатом Субраманиамом. http://fetisovvs.blogspot.com/2018/09/java_16.html