Смотритель: hubert
  • ,

Объектно-ориентированное программирование (перевод статьи)

Автор: Mohit Kanwar
9 ноября, 2015. Java Zone.
Оригинал статьи

От переводчика:
К сожалению, у меня нет сколько-нибудь значительного опыта перевода с английского, хотя я и довольно много читаю на английском. Но выяснилось, что читать и переводить – разные вещи. Также, к сожалению, у меня нет значительного опыта в программировании (недавно только сделал простейшее веб-приложение на Spring MVC и Hibernate). Поэтому перевод получился значительно хуже, чем мог бы быть. Я взял на себя смелость несколько подкорректировать примеры кода, которые даются в статье, так как они не соответствуют соглашениям по наименованию (code conventions) в Java. Возможно, не стоило переводить название некоторых паттернов (такой перевод мало что дает для понимания), но я посчитал, что это меньшее зло. Отдельно стоит сказать о «высокой сцепленности» как переводе «high cohesion». Согласен, не самый лучший перевод. Но «сильная связность» — это «high coupling» (другое важное понятие), а «когерентность» здесь вряд ли подойдет. Я открыт для критики и с признательностью приму замечания по статье в любой форме.


Объектно-ориентированное программирование – это стиль программирования, в котором программа состоит из компонентов, соответствующих объектам реального мира

Любой реальный объект имеет какие-то свойства (которые могут изменяться или нет с течением времени) и поведение (которое может меняться или нет в зависимости от других условий). Например, карандаш – это объект реального мира, который имеет следующие свойства:
  • Он красный (это не меняется с течением времени).
  • Он 10 сантиметров в длину сейчас (это может меняться, если карандаш заточить).
И он имеет следующее поведение:
  • Он оставляет след, если его использовать правильно.
  • След может отличаться в зависимости от давления (зависит от внешних факторов).
  • Его длина сокращается, если его затачивать (постоянное поведение).
Как в этом примере, объекты реального мира могут иметь много свойств, но при написании программ мы принимаем во внимание только необходимые свойства.
Объектно-ориентированное программирование имеет свои преимущества. Например, оно облегчает установление связи между объектом реального мира и программой так, как это ожидается. Это реально помогает по мере того, как приложение растет и множество объектов взаимодействуют друг с другом. Это помогает в распределении ответственности внутри объективного мира, позволяя сфокусироваться на продумывании приложения.
Другая важная особенность, ассоциируемая с ООП (Объектно-ориентированным программированием), — это классификация объектов. Так как мир (реальный/виртуальный) полон объектов, сложно управлять по отдельности. Нам нужен способ классификации этих объектов, который поможет нам связать различные объекты и их свойства, например, черный карандаш. Он был бы неотличим (тот же самый?), если бы использовался в предыдущем примере, но это другой объект. Но так как это оба карандаши, они принадлежат одному и тому же классу «Карандаш». Тогда как ручка, которая очень похожа на карандаш, принадлежит к другому классу. Тем не менее, ручка и карандаш оба являются «Пишущими инструментами».

Объектно-ориентированное программирование имеет следующие принципы:

Абстракция
Абстракция определяется как характерная черта (quality) взаимодействия с идеями, а не событиями или, другими словами, свобода от репрезентирующих качеств. Это позволяет программистам сфокусироваться на том, что программировать, а не как. Абстракцию можно рассматривать в качестве соглашения, посредством которого мы предоставляем функциональность. Детали реализации могут быть скрыты, если использовать этот концепт.
Например, если нам нужен класс, который пишет, то мы должны быть уверены, что обладает методов «писать»
abstract class writer {
	write ();
}

Что мы сделали? Мы разработали класс высокого уровня, являющийся абстрактными, иными словами, он знает, что за функциональность нам нужна, но как ее реализовать – это за пределами видимости (out of scope) данного класса.
Это дает много преимуществ:
  • Мы раскрываем минимум информации необходимой внешним сущностям, это позволяет сосредоточиться на продумывании программы (this enable focused thinking), избежать путаницы и не давать непреднамеренных обещаний.
  • Мы оставляем место для улучшений в будущем, которые были бы невозможны, если детали реализации были раскрыты.

Наследование
«Наследование» в общеупотребительном английском означает «приобретать и передавать дальше». Это слова существует в нашей культуре очень давно. Предки приобретали землю с помощью тяжелой работы и передавали ее своим детям, даже природа благоволит наследованию. Все свойства тела, например, рост, цвет кожи/глаз/волос и т.д. зависят от генов, наследуем нами от наших родителей. Наследование предотвращает изобретение колеса заново и ускоряет прогресс. То же самое и в ООП. Мы создаем родительский класс с несколькими базовыми свойствами/поведением. Все классы, наследуемые от этого родителя, будут содержать такие же свойства/поведение, что и их родитель. Тем не менее, наследуемые классы могут получить больше свойств/поведения или изменить реализацию поведения.
class WritingInstrument {
	colour;
	write() {
}
}
class Pen (child of parent) {
	inkcolour;
}

В примере сверху класс-родитель (WritingInstrument) имеет свойство «цвет» и поведение «писать». Когда класс-наследник (ручка) объявляется, повторное объявление свойства «цвет» и поведения «писать» не требуется. Они присутствуют в классе «ручка» в силу наследования. Однако класс-наследник может объявить собственные дополнительные свойства/поведение.
Как мы можем использовать это на практике? Мы, разработчики, очень ленивы. Мы не хотим печатать что-то снова и снова. Существование множества копий одного и того же кода не приветствуется в силу следующих соображений:
  • Чем меньше копий кода, тем легче его сопровождать.
  • Если нет множества копий кода, то изменение в одном месте становится видимым везде.
  • Чем меньше кода – тем меньше ошибок.
  • Если один код используется во многих местах, то так достигается обобщение.
  • Мы фокусируемся на написании кода.
  • Мы фокусируемся на тестах.
Наследование в Java достигается с помощью ключевых слов «extends» и «implements».
class WritingInstrument {
}
class Pen extends WritingInstrument {
}


Полиморфизм
Слова «полиморфизм» произошло от двух слов:
«Поли», т.е. «множество» / «больше, чем один»
«морф», т.е. «форма»
Буквально, слово «полиморфизм» отсылает к способности объектов вести себя различным образом в зависимости от условий.
В программировании полиморфизм может быть воплощен в нескольких местах:
  • Классы
  • Методы
  • Операторы
Все, перечисленное выше, может вести себя различным образом в зависимости от условий, возможно, от контекста, в которых они используются. Это полезно, так как клиенту (программисту, использующему ваши библиотеки) не нужно знать множество тонкостей, и желаемая функциональность реализуется посредством отбора необходимой информации из контекста.
Class WritingObject {
	wrire() {
	// пишем, используя стандартные (по дефолту) цвета
	}
}

class Pencil extends WritingObject {
	write() {
	// пишем, используя серый цвет, написанный текст можно стереть
	}
}

class Pen extends WritingObject {
	write() {
	// пишем, используя голубой цвет, написанный текст нельзя стереть
	}
}

class Main {
	main() {
		WritingObject wr = new WritingObject();
		wr.write(); // первый вызов
		WritingObject wr = new Pen();
		wr.write(); // второй вызов
		WritingObject wr2 = new Pencil();
		wr2.write(); // третий вызов 
	}
}

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

Инкапсуляция
Инкапсуляция определяется как сбор связанных данный/функциональностей в одном модуле (unit). Это помогает в облегчении доступа/модификации данных. Например, если нам нужно напечатать все свойства, которыми данный пользователь обладает, мы имеем следующие опции:
printUserProperties(userName, userId, firstname, lastname, email, phone, … … ….)

Мы создали метод, который принимает все свойства и печатает их друг за другом. С увеличением количества элементов в списке пропадет возможность идентифицировать корректные поля, а добавление/удаление одного поля изменит сигнатуру метода. Поэтому нам нужно заменить всех пользователей этого метода, если даже недавно добавленные поля им не нужны. Чтобы сделать код более читаемым и упростить будущие модификации проще, мы инкапсулируем свойства в классе и превращаем его в коллективный объект (collective object)
class User {
	userName
	userId
	firstname
	lastname
email
	phone
	..
	..
	..
}
printUserProperties(user) {}

Объект – это система (software bundle) переменных и связанных методов. Вы можете представить объекты реального мира, используя объекты программы. Вы можете представить реальных собак в анимационной программе или реальный велосипед как программный объект внутри велотренажера.
В ООП класс – расширяемый шаблон (program-code-template) для создания объектов, обеспечения их начальным состоянием (переменные) и реализацией поведения (функции, методы).
Аббревиатура SOLID была введена Michael Feather’ом для «первых пяти принципов», названных так Robert C. Martin’ом в начале 2000-х. Целью принципов, реализуемых совместно, является увеличение вероятности того, что программист создаст систему, которую легко будет поддерживать и расширять. Принципы SOLID – ориентиры в разработке программ, которые необходимы для удаления «протухшего» кода посредством рефакторинга, в результате которого код должен стать легко читаемым и расширяемым. Это часть стратегии agile and adaptive programming (гибкого и адаптирующегося программирования).

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

Принцип открытости/закрытости (Open/Closed Principle)
В ООП принцип открытости/закрытости гласит «сущности программного обеспечения (классы, модули, методы и т.д.) должны быть открыты для расширения, но закрыты для изменения». Иными словами, сущность должна позволять расширять ее поведение без изменения исходного кода.

Принцип подстановки Лисковой (Liskov Substitution Principle)
Возможность подстановки (Substituability) – это принцип в ООП. Он гласит, что если S в компьютерной программе является подтипом T, то объекты типа T должны быть такими, чтобы их можно было заменить объектами типа S (т.е. объекта типа S могут заменить объекты типа T) без изменения каких-либо требуемых свойств программы (точность, выполнение задачи и т.д.).

Принцип разделения интерфейса (Interface Segregation Principle)
Принцип разделения интерфейса гласит, что программист-клиент не должен быть принужден зависеть от методов, которые он не использует. Согласно этому принципу нужно разделять большие интерфейсы на маленькие и более специфичные, чтобы программист-клиент знал только о методах, которые ему интересны. Целью принципа разделения интерфейса является сохранение системы в несвязанном состоянии (system decoupled), что облегчит рефакторинг, внесение изменений и повторное развертывание (redeploy).

Принцип инверсии зависимостей (Dependency Inversion Principle)
В ООП принцип инверсии зависимости означает специфическую форму несвязности программных модулей. При следовании этому принципу стандартные отношения зависимости, установленные от модулей высокого уровня, формирующих архитектуру приложения (policy-setting) к зависимым модулям низкого уровня инвертированы (обращены), поэтому измененные модули высокого уровня становятся независимы от деталей реализации модулей низкого уровня. Этот принцип утверждает:
  • Модули высокого уровня не должны зависеть от модулей низкого уровня. Модули обоих типов должны зависеть от абстракций.
  • Абстракции не должны зависеть от деталей реализации. Детали должны зависеть от абстракций.
Принцип обращает (inverts) путь, согласно которому люди могут думать об объектно-ориентированном дизайне, утверждая, что объекты высокого и низкого уровней должны зависеть от одних и тех же абстракций.

Принципы GRASP

Паттерны (принципы), используемые для решения общих задач по назначению обязанностей классам и объектам (General Responsibility Assignment Software Patterns (GRASP)) содержат руководства (guidelines) по назначению ответственности классам и объектам в объектно-ориентированном дизайне.

Контроллер (Controller)
Паттерн Контроллер назначает ответственность за взаимодействие с системными событиями классов без графического интерфейса, которые представляют всю систему или use case scenario (сценарии вариантов использования).
Контроллер:
  • Это не взаимодействующий напрямую с пользователем объект, ответственный за получение и реакцию на системные события.
  • Должен использоваться так, чтобы иметь дело со всем системными событиями одного (или множества взаимосвязанных) use cases.
  • Это первый объект за графическим интерфейсом, который контролирует системные операции.
  • Он не должен делать работу сам, его задача – контроль над потоком событий.

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

Высокая сцепленность (High Cohesion)
Высокая сцепленность – оценочный паттерн, целью применения которого является сохранение объектов в таком состоянии, чтобы они были нацелены на выполнение одной четкой задачи, легко управляемы и понимаемы. Высокая сцепленность обычно используется для поддержки слабой связности (Low Coupling). Высокая связность означает, что ответственность данного элемента четко обозначена (strongly related and highly focused). Разбиение программы на классы и подсистемы – пример действий, что повышает сцепленность свойств системы. Слабая сцепленность, наоборот, — ситуация, в которой элемент имеет слишком много несвязанных задач. Элементы со слабой сцепленностью обычно отличаются тем, что их сложно понять, сложно повторно использовать, поддерживать и изменять.

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

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

Слабая связность (Low Coupling)
Слабая связность – оценочный паттерн, который указывает, как назначать ответственность: слабая зависимость между классами, изменение одного должно иметь минимальные последствия для другого, максимальная возможность повторного использования.

Полиморфизм (Polymorphism)
В соответствии с полиморфизмом изменения поведения основывается на типе объекта, на который ссылается переменная (responsibility of defining the variation of behaviors based on type is assigned to the types for which this variation happens). Это достигается использованием полиморфных операций.

Защищенные изменения (Protected Variations)
Паттерн Защищенные изменения защищает элементы от изменений других элементов (объектов, систем, подсистем) путем обертывания центра нестабильности (the focus of instability) интерфейсом и использования полиморфизма для создания различных реализаций данного интерфейса.

Чистое конструирование (Pure Fabrication)
Чистое конструирование предполагает класс, не представляющий концепт в проблемной области (the problem domain) и созданный специально для достижения слабой связности, высокой сцепленности и, следовательно, максимального потенциала повторного использования (решение, предлагаемое паттерном Информационный эксперт этого не обеспечивает). Такая класс обычно называется “Service” в Предметно-ориентированном дизайне (Domain-driven design).

Критика

Исследования Potok’a и др. показали отсутствие существенных различий между ООП и процедурными подходами.
Критическое сравнение ООП с другими технологиями, в особенности реляционными, затруднено в силу отсутствия определения ООП, которое было бы строгим и широко принятым (Christopher J. Date)
В сравнении с другими языками (LISP диалекты, функциональные языка и т.д.) ООП языки не имеют уникального преимущества и навязывают ненужную сложность. (Lawrence Krubner)
Я нахожу объектно-ориентированное программирование технически неосновательным. Оно пытается разложить мир на части в терминах интерфейсов, которые изменяются в пределах одного типа. Чтобы иметь дело с реальными проблемами, вам нужны многосортные алгебры — семейства интерфейсов, которые простираются на многие типы. Я нахожу объектно-ориентированное программирование философски нездоровым. Оно утверждает, что всё является объектом. Даже если это так, это не очень интересно: сказать, что всё является объектом — значит, не сказать вообще ничего. (Александр Степанов)
Популярность ООП среди больших компаний связана с «большими (и часто меняющимися) группами посредственных программистов». Дисциплина, навязываемая ООП, предотвращает нанесение программистом «слишком большого вреда». (Paul Graham)
Объектно-ориентированное программирование ставит существительные первыми и самыми главными. Зачем идти на такие крайние меры и ставить одну часть речи на пьедестал? Почему один концепт получает преимущество над другим? Это невозможно, чтобы ООП внезапно сделало глаголы менее важными для нашего мышления. Это странным образом перекошенная перспектива. (Steve Yegge)
Rick Hickey, создатель Clojure, описывал объектные системы как крайне упрощенные модели реального мира. Он подчеркивал неспособность ООП моделирования времени правильно, что создает огромные проблемы, когда в программах большое распространение получает многопоточность.
Eric S. Raymond, Unix-программист и сторонник программного обеспечения с открытым кодом, был критически настроен в отношении заявления, что ООП является «Единственно верным решением», и писал, что ООП поощряет многослойные программы, что препятствует понятности (transparency). В качестве противоположного подхода Raymond приводил пример Unix и С.

Ссылки

By Margaret Rouse @ WhatIs.com
Wikipedia! (Русский вариант)
inheritance is polymorphism
SOLID (Object Oriented Design) (Русский вариант)
Single Responsibility PrincipleArguments against OOPS (Русский вариант)
What is OOPS (without the hype)

Перевод: Варыгин Д.В.
  • ,

Основы Параллелизма: взаимоблокировки и мониторы объектов (раздел 3) (перевод статьи)

Исходная статья: www.javacodegeeks.com/2015/09/concurrency-fundamentals-deadlocks-and-object-monitors.html
Автор: Martin Mois

Первые две части перевода здесь.

Содержание

1. Живучесть
 1.1 Взаимоблокировка
 1.2 Голодание
2. Мониторы объектов совместно с wait() и notify()
 2.1 Вложенные синхронизированные блоки совместно с wait() и notify()
 2.2 Условия в синхронизированных блоках
3. Проектирование для многонитевости
 3.1 Неизменяемый объект
 3.2 Проектирование API
 3.3 Локальное хранилище нити

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

3.1 Неизменный объект
Одним из правил проектирования, являющихся очень важным в данном контексте, является Неизменяемость. Если вы распределяете экземпляры объектов, например, между различными нитями, то должны уделить внимание тому, чтобы две нити не изменяли один и тот же объект одновременно. В подобных ситуациях легко управляться с немодифицируемыми объектами, поскольку вы не можете их изменить. Вы всегда должны создавать новый экземпляр, когда хотите изменить данные. Базовый класс java.lang.String — пример неизменяемого класса. Вы получаете новый экземпляр всякий раз, когда хотите изменить строку:

String str = "abc";

String substr = str.substring(1);


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

Далее приведён список правил, которые необходимо применять, чтобы сделать класс неизменяемым:
  • ,

Java. Справочное руководство для интервью - Часть 1. (Перевод статьи)

Исходная статья находится по адресу:
http://www.javacodegeeks.com/2014/02/java-interview-reference-guide-part-1.html

Опубликовал: Nitin Kumar, в Core Java, 3 февраля 2014 г

Java. Объектно-Ориентированная концепция.


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

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

В Java, класс — это документация, шаблон или прототип, который определяет общее поведение объектов того же вида. Экземпляр является реализацией определенного класса, и все экземпляры класса имеют аналогичные свойства, как представлено в описании класса. Например, вы можете определить класс, который называется Дом, с числом комнат, как атрибутом, и создать объекты: дом с 2 комнатами, дом с 3 комнатами и т.д.

Преимущества:

Ниже перечислено несколько преимуществ разработки объектно-ориентированного программного обеспечения:

  • Меньше затрат на обслуживание, главным образом благодаря модульности.
  • Код легче повторно использовать за счет таких функций, как наследование, что как следствие ускоряет разработку.
  • Повышается надежность и гибкость кода.
  • Код легче понять, это обусловлено моделированием реального мира.
  • Лучшая абстракция на объектном уровне.
  • Уменьшение сложности перехода от одной стадии разработки к другой.

Существуют четыре основных понятия ООП:

  • Инкапсуляция
  • Наследование
  • Полиморфизм
  • Абстракция

Инкапсуляция:

Инкапсуляция представляет собой правила для других объектов, которые указывают, какие элементы скрыты, а какие открыты для доступа другим объектам. В Java мы используем модификатор доступа private для того, чтобы скрыть метод и ограничить доступ к переменной из внешней среды. Java также предусматривает различные модификаторы доступа, такие как public, который устанавливается по-умолчанию, protected и private, которые используются для ограничения видимости на различных уровнях, но конечная цель инкапсуляции — это скрыть те элементы, которые не должны изменяться. На практике лучше всего, когда класс имеет только одну причину для изменения, и инкапсуляция реализует принципы проектирования этой «одной причины».

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

Преимущества:
  • ,

Как писать методы эффективно (перевод статьи)

Исходная статья лежит по адресу:
http://www.javacodegeeks.com/2015/09/how-to-write-methods-efficiently.html#download

учебник

Опубликовано: Andrey Redko ( Андреем Редько) в Core Java (Java Ядро) 18 сентября 2015г

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

Оглавление курса
1. Введение
2. Сигнатура методов
3. Тело метода
4. Перегрузка метода
5. Переопределение метода
6. Встраивание
7. Рекурсия
8. Ссылки метода
9. Неизменность
10. Документирование метода
11. Параметры метода и возвращаемые значения
12. Метод как точка входа в приложение
13. Что дальше
14. Загрузка исходного кода

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

2. Сигнатуры методов
Как вы уже знаете, Java — это объектно-ориентированный язык. По существу, каждый метод Java относится к какой-то части класса (или к самому классу в случае статистического метода). Он имеет правила видимости (или доступности), может быть объявлен абстрактным или финальным и так далее. Однако возможно наиболее важная часть метода — это его сигнатура: тип возвращаемого значения и аргументов, плюс список проверяемых исключений реализации каждого метода, который может быть выброшен (но эта часть раньше использовалась не часто, и еще менее часто в наши дни). Начнем с маленького примера.
1	public static void main( String[] args ) {
2	    // Some implementation here
3	}

Метод main принимает массив строк только как аргумент args и ничего не возвращает. Это могло бы быть очень приятно — делать все методы такими простыми как main. Но в реальности сигнатура метода может стать нечитаемой. Давайте взглянем на следующий пример:
1	public void setTitleVisible( int lenght, String title, boolean visible ) {
2	    // Some implementation here
3	}

Первое что здесь заметно, что условные обозначения изначально используются в названиях методов Java, например setTitleVisible.Имя хорошо подобрано и пытается описать, что в методе полагается сделать.
Второе, имена аргументов говорят (или по крайней мере намекают) насчет их цели. Это очень важно найти правильные, толковые имена для аргументов метода, вместо int i, String s, boolean f(в очень редких случаях это, однако, имеет смысл).
Третье, метод имеет только три аргумента. Хотя Java имеет гораздо больший предел разрешенного числа аргументов, настоятельно рекомендовано не превышать количество аргументов больше 6. Выход за эти рамки делает сигнатуру тяжело понимаемой.
С тех пор как была выпущена Java 5, методы могут иметь различный список аргументов одинакового типа (названный varargs — переменные аргументы) и использовать специальный синтаксис, например:
1	public void find( String … elements ) {
2	    // Some implementation here
3	}

Внутренне, компилятор Java конвертирует переменные аргументы в массив соответствующих типов и, таким образом, переменные аргументы могут быть приняты для реализации метода.
Интересно, Java также разрешает декларировать varargs используя параметры типа generic. Однако, потому что тип аргумента неизвестен, компилятор Java хочет быть уверенным что varargs используются правильно и советует методы final снабжать комментариями с пометкой @SafeVarargs(более детальная информация содержится в части 5 учебника, How and when to use Enums and Annotations (как и когда мы используем Перечисления и Комментарии). Например:
  • ,

15 вопросов для собеседования разработчиков, относительно Enum в Джаве (с ответами!)

Перечисление (Enum) было введено в Java 5 и с тех пор оно стало весьма популярно среди разработчиков Java. Оно широко используется в различных Java-приложениях. Поскольку Enum в Java намного универсальнее, чем в C или C ++, оно также представляет множество интересных вариантов использования, пару из которых, вы видели в статье 10 способов использовать Enum в Java.

Но, несмотря на такую популярность, многие Java-программисты по-прежнему не знают о функциональности, предоставляемой Enum и тонкостей использования Enum в Java коде.

Отличия между слабыми, мягкими, фантомными и обычными ссылками в Java.

    «Слабые» ссылки и «мягкие» ссылки (WeakReference, SoftReference) были добавлены в Java API давно, но не каждый программист знаком с ними. Это свидетельствует о пробеле в понимании где и как их использовать. Ссылочные классы особенно важны в контексте сборки мусора . Как все мы знаем сборщик мусора сам освобождает память занимаемую объектами, но не все программисты знают что решение об освобождении памяти он принимает исходя из типа имеющихся на объект ссылок.
    Главное отличие SoftReference от WeakReference в том как сборщик с ними будет работать. Он может удалить объект в любой момент если на него указывают только weak ссылки, с другой стороны объекты с soft ссылкой будут собраны только когда JVM очень нужна память. Благодаря таким особенностям ссылочных классов каждый из них имеет свое применение. SoftReference можно использовать для реализации кэшей и когда JVM понадобится память она освободит ее за счет удаления таких объектов. А WeakReference отлично подойдут для хранения метаданных, например для хранения ссылки на ClassLoader. Если нет классов для загрузки то нет смысла хранить ссылку на ClassLoader, слабая ссылка делает ClassLoader доступным для удаления как только мы назначим ее вместо крепкой ссылки (Strong reference). В этой статье мы рассмотрим отличия типов ссылок в том числе Strong reference и Phantom reference (фантомная ссылка).

Как отправить письмо из Java-приложения (с примером)

Перевод статьи: How to Send Email from Java Program with Example

Отправка электронного сообщения из Java-приложения это распространенное требование. Не имеет значения работаешь ли ты над core Java-приложением, веб-приложением или enterprise Java — приложением, тебе может понадобится отправить письмо для оповещения персонала из тех.поддержки об ошибках, или просто отправить письмо пользователям при регистрации, восстановить пароль или попросить их подтвердить адрес электронной почты после регистрации. Есть очень много сценариев(случаев), когда тебе нужна возможность отправить электронные письма из Java-приложения. В готовых приложениях у тебя уже есть модуль или библиотека, работающая со всеми функциями для отправки электронных писем, например, возможность отправлять вложения, изображения, включая подписи и форматированный текст в электронных письмах, НО если тебе нужно написать что-то с нуля, тогда Java Mail API это прекрасный вариант. В этой статье мы научимся как отправлять электронные письма из Java-приложения, используя почтовый API(javax.mail). Перед написанием кода ты должен знать некоторые основы работы электронной почты, например, тебе нужен SMTP(простой протокол передачи почты) сервер. Если ты запускаешь свое Java-приложение под Linux, тогда ты должен знать, что SMTP демон(прим. «компьютерная программа в системах класса UNIX, запускаемая самой системой и работающая в фоновом режиме без прямого взаимодействия с пользователем») использует порт 25. Ты можешь использовать любой почтовый сервер для отправки сообщений применяя Java, включая общедоступные почтовые сервера, такие как GMail, Yahoo или любой другой поставщик услуг, все что тебе нужно это детали их SMTP сервера, например, имя хоста, порт, параметры соединения и т.д. Так же ты можешь использовать SSL(англ. secure sockets layer — уровень защищённых сокетов), TLS(англ. Transport Layer Security — безопасность транспортного уровня) для безопасного соединения и отправки писем, но этот пример мы сделали простым и cфокусировались на минимальной логике для отправки письма из Java-приложения. В дальнейших статьях мы научимся как отправлять письмо используя вложения, как отправлять форматированное с помощью HTML письмо, как прикрепить изображения в письмо, как использовать SSL аутентификацию для соединения с сервером GMail и отправки писем и т.д. А сейчас, давай поймем(разберем) этот простой пример Java Mail API.

Пример Java-кода для отправки электронного сообщения



Для отправки письма из Java-программы тебе потребуются Java Mail API и Java Activation Framework(JAF); если более точно, то тебе понадобятся mail-1.4.5.jar, smtp-1.4.4.jar, и activation-1.1.jar. Тебе нужно скачать эти JAR файлы и включить их в твой Classpath для запуска этой программы. В качестве альтернативы ты можешь использовать Maven для управления зависимостями и включить все зависимости там. Как только у тебя будут все эти JAR файлы, просто следуй шагам ниже для создания и отправки электронного письма c помощью Java.

  1. Создай объект Session вызывая Session.getDefaultInstance(properties), где properties — содержит все важные свойства, например, имя хоста SMTP сервера.
  2. Создай объект MimeMessage передавая ему объект Session, полученный на предыдущем шаге. У нас есть набор различных свойств в этом объекте, таких как получатель письма, тема, тело сообщения, вложения и т.д.
  3. Используй javax.mail.Transport для отправки письма вызывая статический метод send(email), где email может быть объект MimeMessage.

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

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


Принципы объектно-ориентированного дизайна (далее — ООД) — ядро объектно-ориентированного программирования (далее — ООП), но я вижу большинство Java-программистов, работающих с паттернами Singleton («Одиночка», например Singleton), «Декоратор» (Decorator) или «Наблюдатель» (Observer), и не уделяющих должного внимания изучению объектно-ориентированного анализа и дизайна. Конечно, важно изучать основы ООП: абстракция, инкапсуляция, полиморфизм и наследование, но, в то же время, не менее важно знать принципы дизайна, чтобы создавать хорошо структурированные и понятные продукты. Постоянно наблюдаю программистов, разработчиков различного уровня, которые или не слышали о принципах ООД SOLID, или просто не знают о преимуществах, которые тот или иной принцип дизайна дает, или как применить его в коде.

В итоге, всегда стремитесь к связности кода и хорошему дизайну в решении. Отличные примеры для изучения Java и ООД — открытый код Apache и Sun. Они демонстрируют, как принципы ООД должны использоваться в написании кода, в программах на Java. Иллюстрация применения паттернов в JDK: Factory, паттерн «фабрика» в классе BorderFactory, Что такое паттерн дизайна Factory..., паттерн Singleton, «одиночка», в классе Runtime RunTime, паттерн Decorator, «декоратор», в различных java.io классах. К слову, если вы заинтересованы практиковаться в java-коде, прочтите Effective Java, Joshua Bloch (например, Effective Java в переводе на русский), шедевр от автора Java API. Еще на тему ООД и паттернов рекомендую Head First Design Pattern (на русском Дизайны проектирования), а также Head First Object Oriented Analysis and Design (на английском OOAD). Эти книги помогут писать лучший код, используя преимущества принципов ООД.

Хотя лучший способ усвоить любые принципы — практиковаться и понимать последствия нарушения этих самых принципов, тема этой статьи — введение в принципы ООД для java-программистов, которые пока их не используют или только изучают язык. Я полагаю, каждый из озвученных принципов ООД (SOLID) достоин отдельной статьи с подробным объяснением сути, и я в дальнейшем постараюсь (написать эти статьи — прим. перев.), но сейчас приготовьтесь просто быстро пробежаться.

10 вещей которых вы не знали в Java

перевод статьи: 10 Things You Didn’t Know About Java


Итак вы с недавних пор начали работать с Java? А помните времена когда она называлась
«Oak», когда объектно-ориентированность было еще горячей темой, когда люди С++
думали что у Java нет никаких шансов, и когда про апплеты никто даже не слыхал?
Я могу предположить, что вы не знаете даже и половины следующих вещей. Давайте
начнем неделю с нескольких крутых сюрпризов внутренней работы Java.

1. Не существует такого понятия как – checked exception.

Все верно! JVM понятия не имеет о такой вещи, лишь язык Java знает.
Сегодня все соглашаются, что checked exceptions были ошибкой. Как говорил Брюс
Эккель на своем заключительном выступлении на GeeCON в Праге, ни один другой язык
после Java не использует checked exception, даже Java 8 больше не охватывает их в новом
Streams API (что правда может доставлять небольшие неудобства, когда ваши лямбды
будут использовать IO или JDBC).
Вы хотите доказательств того что JVM не знает такой вещи? Попробуйте следующий
код:

public class Test {
  
    // No throws clause here
    public static void main(String[] args) {
        doThrow(new SQLException());
    }
  
    static void doThrow(Exception e) {
        Test.<RuntimeException> doThrow0(e);
    }
  
    @SuppressWarnings("unchecked")
    static <E extends Exception>
    void doThrow0(Exception e) throws E {
        throw (E) e;
    }
}


Это не только скомпилируется, это также бросит SQLException, вам даже не нужно
использовать Lombok's @SneakyThrows для этого.
2. Вы можете иметь перегруженные методы отличающиеся только возвращаемыми
типами
  • ,

10 статей, которые должен прочитать каждый программист

Перевод статьи 10 Articles Every Programmer Must Read

Будучи Java-программистом и разработчиком программного обеспечения, я многому научился из множества статей под названием Что каждый программист должен знать о ....., они, как правило, дают много полезной и исчерпывающей информации о конкретной теме, которую иначе трудно обнаружить. В моих стремлениях к знаниям я сталкивался с некоторыми очень полезными статьями, которые добавлял в закладки как справочную информацию для перечитывания. Мысль, что многие программисты смогут извлечь пользу из чтения этой подборки, побудила меня написать данный пост и поделиться с вами всеми этими статьями «Что каждый программист должен знать». В этой статье вы познакомитесь с классическим набором знаний, необходимых каждому программисту, в таких темах как память (memory), Unicode, вычисления с плавающей точкой (floating point arithmetic), работа с сетями (networking), объектно-ориентированное проектирование (object oriented design), время (time), URL Encoding, String и многим другим. Этот список очень важен для начинающих и новоприбывших, так как им часто не хватает практических знаний. Поскольку большинство статей написаны на основе реальных примеров, программисты начального и среднего уровня могут извлечь из них много полезного. Также, изучение основ в начале карьеры поможет избежать ошибок, которые уже сделали другие программисты и разработчики программного обеспечения на их пути обучения. К сожалению, не вся информация из описанных статей легко усваивается с первого прочтения. Скорее всего, вы можете не сразу понять некоторые подробности о числах с плавающей точкой или можете запутаться с особенностями памяти, но важно держать эту подборку под рукой и обращаться к ней время от времени за уточнениями. Так что желаю вам удачи и наслаждайтесь чтением этих замечательных статей.  Кстати, не забывайте делиться какими-либо еще статьями «Что каждый программист должен знать», если они еще не попали в наш список.

  • ,

Почему NULL - это плохо?

Почему NULL – это плохо?


Вот простой пример использования NULL в Java:

public Employee getByName(String name) {
  int id = database.find(name);
  if (id == 0) {
    return null;
  }
  return new Employee(id);
}

Что не так с этим методом?

Он может вернуть NULL вместо объекта – вот что не так. Использование NULL – ужасная практика в ООП, и этого стоит избегать всеми способами. По данному вопросу уже опубликовано достаточно разных мнений, в том числе презентация Tony Hoare «Нулевые ссылки: Ошибка на миллиард долларов» и целая книга David West «Объектно ориентированное мышление».

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

Сначала рассмотрим две возможные альтернативы NULL.
  • ,

Перевод: Использование синтаксиса Markdown в комментариях Javadoc

Использование синтаксиса Markdown в комментариях Javadoc


В этом посте мы рассмотрим как можно писать комментарии Javadoc используя Markdown вместо стандартного синтаксиса Javadoc.

Итак, что такое Markdown?

Markdown – это простой язык разметки, который можно при желании перевести в HTML с помощью одноименного инструмента. Markdown широко используется для форматирования readme файлов, при написании сообщений на форумах, а также в текстовых редакторах для быстрого создания красивых текстовых документов.
(Википедия: Markdown)

Текст, отформатированный в Markdown, очень легко читается. Различные разновидности Markdown используются на сайтах Stack Overflow или GitHub для форматирования пользовательского контента.

Установка
По умолчанию инструмент Javadoc использует Javadoc комментарии для генерации API документации в виде HTML. Этот процесс можно перенастроить с помощью Doclets. Doclets – это Java программы, которые задают содержание и способ форматирования выходного файла инструмента Javadoc.

Markdown-doclet заменяет стандартный Java Doclet и тем самым дает разработчику возможность использовать Markdown синтаксис в своих Javadoc комментариях. Установить его в Maven можно с помощью maven-javadoc-plugin.


<build>
  <plugins>
    <plugin>
      <artifactId>maven-javadoc-plugin</artifactId>
      <version>2.9</version>
      <configuration>
        <doclet>ch.raffael.doclets.pegdown.PegdownDoclet</doclet>
        <docletArtifact>
          <groupId>ch.raffael.pegdown-doclet</groupId>
          <artifactId>pegdown-doclet</artifactId>
          <version>1.1</version>
        </docletArtifact>
        <useStandardDocletOptions>true</useStandardDocletOptions>
      </configuration>
    </plugin>
  </plugins>
</build>


Написание комментариев в Markdown

Теперь можно использовать Markdown синтаксис для написания Javadoc комментариев:

/**
 * ## Large headline
 * ### Smaller headline
 *
 * This is a comment that contains `code` parts.
 *
 * Code blocks:
 *
 * ```java
 * int foo = 42;
 * System.out.println(foo);
 * ```
 *
 * Quote blocks:
 *
 * > This is a block quote
 *
 * lists:
 *
 *  - first item
 *  - second item
 *  - third item
 *
 * This is a text that contains an [external link][link].
 *
 * [link]: http://external-link.com/
 *
 * @param id the user id
 * @return the user object with the passed `id` or `null` if no user with this `id` is found
 */
public User findUser(long id) {
  ...
}


После выполнения
mvn javadoc:Javadoc
сгенерированный HTML API документ располагается по адресу
target/site/apidocs.

Документ, сгенерированый для вышеприведенного кода, выглядит так:


Как видно из рисунка, Javadoc комментарии прекрасно конвертируются в HTML.

Заключение

Markdown имеет явное преимущество перед стандартным синтаксисом Javadoc: он гораздо легче читается в исходном коде. Просто взгляните на некоторые комментарии к методам из java.util.Map: многие из них полны форматирующих тэгов и с трудом могут быть прочитаны без использования дополнительных инструментов.

Но нужно помнить, что Markdown может вызвать проблемы с инструментами и IDE, которые умеют работать только со стандартным Javadoc синтаксисом.

Источник: Using Markdown syntax in Javadoc comments от нашего JCG партнера Michael Scharhag из блога mscharhag, Programming and Stuff.