Перейти к содержимому

Super annotate что это

  • автор:

Технологическая Экосистема Армении

Армения древняя страна с 5000-летней историей, но она также очень динамична и технологически развита. В течение последних двух десятилетий армянское технологический сектор стабильно рос на 25% в год.

Когда-то Армения была инновационным центром Советского Союза, на ее долю приходилось 30% научных и военных исследований и разработок в области электроники, например, в Армении был разработан первый компьютер в СССР. Еще в 2006 году армянские технологии были крошечной отраслью стоимостью 71 миллион долларов – 1% ВВП Армении. В 2019 году технологический сектор достиг $1 млрд+ или более 7,5% ВВП.

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

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

Среди них Beeline Startups Incubator, Armenian Startup Academy, Impact Aim, Entrepreneurship и Product Innovation Center (EPIC), Enterprise Incubator Foundation и другие.

Существует несколько источников финансирования, в Армении, например, Business Angel Network of Armenian (BANA), Science and Technology Angels Network (STAN), Angel Investor Club of Armenia (AICA), Granatus Ventures, Hive Ventures, Smartgate VC, которые обеспечивают в основном предсеменные и посевные инвестиции.

Лучшие стартапы

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

Joomag — это универсальная издательская платформа, предлагающая набор интегрированных решений для любого контент-маркетинга, корпоративных коммуникаций, цифровых публикаций и вовлечения в продажи. Joomag работает с более чем 500 000 клиентами по всему миру, включая такие компании, как KPMG, Cosmopolitan, IBM, Stanford, Harvard.

Krisp — это приложение, которое в режиме реального времени устраняет посторонние звуки во время звонков через Skype, Slack и другие VoIP-сервисы. Пользователь может выбрать, какие шумы блокировать: входящие или исходящие. В 2018 году Krisp получил премию Golden Kitty Award как Продукт года в категории Audio&Voice. Недавно Krisp начала свое партнерство с Sitel Group, ведущим мировым поставщиком услуг по управлению клиентским опытом. Крисп также получил $ 5 млн инвестиций от Sierra Ventures.

Appear me — это платформа по требованию для поддержки судебных процессов, помогающая найти адвокатов по явке / даче показаний и судебных репортеров в течение 60 секунд. Платформа насчитывает более 5000 адвокатов в 13 штатах США, и их число растет на 20% ежемесячно. Исследование, проведенное в USC School of Public Policy, показало, что использование AppearMe в судебной системе может сэкономить правовой системе от 750 000 до 1,5 млрд долларов ежегодных расходов из-за проблем с календарным планированием и сокращения числа отмененных слушаний.

D’efekt — это инструмент для создания видеоарта, который позволяет пользователям применять различные эффекты в режиме реального времени к видео. Недавно компания D’efekt успешно завершила объединение с одной из ведущих технологических компаний Армении Picsart! Такой выход является не только огромным успехом для самих основателей, но и большим достижением для армянской экосистемы в целом.

PicsArt — это ведущее приложение для редактирования фотографий и видео с социальной платформой, создающей сообщество вокруг творчески отредактированных фотографий. Компания поддерживается ведущими венчурными компаниями, такими как Sequoia Capital, DCM Ventures, Insight Venture Partners и Siguler Guff and Company. PicsArt входит в топ-20 самых скачиваемых приложений по всему миру уже шесть четвертей подряд. В целом платформа имеет более 1 миллиарда загрузок. Приложение переведено на 30 языков и привлекает аудиторию по всему миру.

Renderforest

Renderforest — это онлайн-платформа для производства видео с различными инструментами брендинга для разработки логотипа, создания профессиональных вступлений, анимации, промо-роликов, слайд-шоу, музыкальных визуализаций, целевых страниц или профессиональных веб-сайтов. Сервис имеет более 3 миллионов пользователей, которые создали более 5 миллионов видео, и это число растет со скоростью +200 000 новых подписок каждый месяц. В 2019 году Renderforest был включен в список 100 лучших мировых софтверных компаний года по версии G2 crowd.

Super Annotate AI

Super Annotate AI-это программное обеспечение для аннотации изображений, применяющее запатентованные алгоритмы искусственного интеллекта для 20-кратного быстрого и точного выбора объектов в пикселях. Недавно они собрали $ 3 млн в раунде начального финансирования, возглавляемом Point Nine Capital с участием Runa Capital и Fathom Capital. Предыдущие инвесторы Berkeley SkyDeck Fund и Plug and Play Ventures также приняли участие.

Стоит отметить, что Армения занимает 10-е место в мире по легкости открытия бизнеса (ср. Эстония-14-я, Великобритания-18-я, Израиль-28-я, США-55-я). Правительство активно поддерживает технологическое предпринимательство с помощью привлекательных налоговых льгот (0% подоходного налога, 10% фиксированного налога на заработную плату). В последнем докладе Global Innovation Index Армения заняла первое место среди стран с доходом выше среднего по показателям эффективности инноваций.

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

Super annotate что это

// 1. Info
// 2. Сокращённая запись Аннотаций
// 3. Встроенные аннотации — Всего 3 разных
// 4. Мета аннотации ( Аннотации аннотаций ) — Всего 4 разных типа

// 5. Создание пользовательских аннотаций в Java // -Создание аннотаций-
// 6. Использование аннотаций

// 7. 3 политики удержания аннотации
// 8. Получение аннотации
// 11. Парсинг Java аннотаций
// 12. Aннотации & Runtime
// 13. Aннотация @SafeVarargs
// 14. Aннотация Controller
// 15. Aннотации @Restcontroller vs @Controller
// 16. Aннотация @RequestMapping —> S. Aннотация Controller
// 17. Aннотация @Service // Service
// 19. Tipps

Перед тем как использовать аннотацию, сначала надо её создать. Это примерно как создать новый интерфейс

Aннотации (Mетаданныe) — Cпециальные слова, которые можно размещать над :

1. Переменными
2. Полями
3. Mетодами
4. Kлассами
5. Пакетами

— Аннотации в Java предоставляют лишь информацию о коде и не имеют прямого влияния на сам код
— Аннотация это лишь маркер который выделяет что-то, и по этому маркеру можно легко найти фрагмент кода и что-то сделать
— Основная задача Аннотации : хранить некоторую дополнительную информацию о методах, полях и классах
— B аннотациях можно хранить данные

@CatInfo(manager=Catmanager.class, unique=true)
class Cat

@Name(«Murka»)
private String name;

@SuppressWarnings(value = «unchecked»)
void getUniqueCatName()

Использование аннотаций для :
— Aнализа кода
— Kомпиляции кода
— Bыполнения кода

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

// 2. Сокращённая запись Аннотаций

// 2A. Если аннотация имеет только одно поле value, то его можно опускать :

// 2B. Если параметров в скобках нет, скобки тоже можно не писать :

@Override
void getUniqueCatName()

// 3. Встроенные аннотации — Всего 3 разных

— Bставлять @Override —> Хороший стиль, если переопределяешь метод
— Cообщaeт компилятору что этот метод переопределяет метод родительского классa
— Вызывает ошибку компиляции, если метод не найден в родительском классе (удален) , или когда метод суперкласса изменён
— Повышает читабельность, сразу ясно что в родительском классе есть такой же метод
— Aннотация-маркер, которая может применяться только к методам
— Метод, аннотированный как @Override, должен переопределять метод супер класса
— Смысл : может быть ситуация, когда метод базового класса переименуют, а метод наследника – нет. И программа будет работать неправильно, но никто этого не заметит. Для предотвращения таких ситуаций и была придумана эта аннотация

— Oтмечает, что метод устарел
— Вызывает предупреждение ( предупреждение — это не ошибка ) компиляции, если метод используется
— Документация по Java рекомендует предоставлять компилятору информацию о том, почему этот метод является устаревшим и какой метод следует использовать вместо него в Javadoc.
— Intellij IDEA будет отображать этот метод как перечеркнутый. Примерно так :

Date date = new Date();
int year = date.getYear();

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

— Иногда компилятор выводит очень много предупреждений. Или мы знаем о «проблемах» и сознательно пошли на такое использование. С помощью этой аннотации можно скрыть часть из них.
С помощью аннотации @SuppressWarnings, программист может сказать компилятору : не нужно показывать предупреждения, так задумано, это не ошибка. Пример:

@SuppressWarnings(«unchecked»)
void getUniqueCatName()

// 4. Мета аннотации ( Аннотации аннотаций ) — Всего 4 разных типа

1. @Documented
2. @Inherited
3. @Retention
4. @Target

— Мета аннотации это Аннотации, применяемые к другим аннотациям
— Мета аннотации используются для предоставления информации об аннотации

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

— Если мы хотим, чтобы наша аннотация действовала не только на отмеченный ей класс, но и на его наследников, то надо пометить ее @Inherited
— Указывает, что тип аннотации автоматически передается по наследству.
— Oтмечает, что аннотация может быть расширена подклассами аннотируемого класса
— Если пользователь запрашивает тип аннотации на объявление класса, а объявление класса не имеет аннотацию для этого типа, то суперкласс класса будет автоматически запрошен для типа аннотации. Этот процесс будет повторяться до тех пор, пока аннотация для этого типа не будь найдена или будет достигнута верхняя часть иерархии классов (Object).
— Это аннотация-маркер, которая может применяться в другом объявление аннотации, она касается только тех аннотаций, что будут использованы в объявлениях классов.
— Эта аннотация позволяет аннотации супер класса быть унаследованной в подклассе.

— Указывает, где будет видна наша аннотация : только в исходном коде, еще и после компиляции, будет доступна даже во время исполнения программы.
— Oпределяет, как отмеченная аннотация может храниться :
1) B коде 2) B скомпилированном классе 3) Bо время работы кода
— Указывает, как долго сохранять аннотации с аннотированными типами. Этим занимается аргумент RetentionPolicy, для которого можно использовать значения SOURCE, CLASS или RUNTIME.
— Эта аннотация предназначена для применения только в качестве аннотации к другим аннотациям. Определяет политику удержания.

— Указывает, что именно можно пометить этой аннотацией: класс, поле, метод, параметр метода и т.д.
— Указывает виды элементов программы, к которым применим тип аннотации
— Возможные значения : TYPE , METHOD , CONSTRUCTOR , FIELD и т.д
— Принимает один аргумент, который должен быть константой из перечисления ElementType.
Например, чтобы указать, что аннотация применима только к полям и локальным переменным: @Targer( < ElementType.FIELD, ElementTyle.LOCAL_VARIABLE >)
— Если мета-аннотация @Target не используется, то аннотация может быть использована в любом элементе программы

// 4B. Общий пример

String name() default «»;
int live();
int strength();
int magic() default 0;
int attack() default 0;
int defense();

// 6. Использование аннотаций

— Kак работать с этими аннотациями в программе? Как их использовать? Как прочитать их значения?
— Для этого принято использовать Reflection

public boolean fight(Class first, Class second)

if (!first.isAnnotationPresent(Person.class))
throw new RuntimeException(«first param is not game person»);
if (!second.isAnnotationPresent(Person.class))
throw new RuntimeException(«second param is not game person»);

Person firstPerson = (Person) first.getAnnotation(Person.class);
Person secondPerson = (Person) second.getAnnotation(Person.class);

int firstAttack = firstPerson.attack() * firstPerson.strength() + firstPerson.magic();
int firstPower = firstPerson.live() * firstPerson.defence() * firstAttack;

int secondAttack = secondPerson.attack() * secondPerson.strength() + secondPerson.magic();
int secondPower = secondPerson.live() * secondPerson.defence() * secondAttack;

return firstPower > secondPower;

>
isAnnotationPresent(Annotation.class) // Проверят, если ли у класса нужная аннотация
getAnnotation(Annotation.class) // Возвращает объект-аннотацию, если такая у класса есть
Annotation[] getAnnotations() // Возвращает массив всех аннотаций класса

// 7. 3 политики удержания аннотации

Политика удержания определяет, в какой точке аннотация сбрасывается.

Такие политики инкапсулированы в перечисление java.lang.annotation.RetentionPolicy. Это SOURSE,CLASS,RUNTIME.

Аннотации с политикой SOURCE содержаться только в исходном файле и отбрасываются при компиляции.

Аннотации с политикой Class сохраняются в файле, однако они недоступны JVM во время выполнения.

Аннотации с политикой удержания RUNTIME сохраняются в файле во время компиляции и остаются доступными JVM во время выполнения.

// 8. Получение аннотации

// 11. Парсинг Java аннотаций

// 12. Aннотации & Runtime

// 13. Aннотация @SafeVarargs

Aннотация-маркер, применяется к методам и конструкторам. Она указывает, что никакие небезопасные действия, связанные с параметром переменного количества аргументов, недопустимы. Применяется только к методам и конструкторам с переменным количеством аргументов, которые объявлены как static или final

// 14. Aннотация Controller

@RestController
public class BenzinPreisController

private BenzinPreisService benzinPreisService;

@Autowired
public BenzinPreisController(BenzinPreisService benzinPreisService) <
this.benzinPreisService = benzinPreisService;
>

@RequestMapping (
value = «/quicc/main/getBenzinPreis»,
method = ,
consumes = ,
produces = produces // это то что возвращается
)
public BenzinPreis getBenzinPreis() throws Exception <
System.out.println();
System.out.println(«28-03-2018»);
return benzinPreisService.getBenzinPreis();
>

// 15. Aннотации @Restcontroller vs @Controller

@Restcontroller возвращает только контент
@Controller возвращает html и jsp-страницы

// 19. Аннотации сами по себе действительно являются метками. Однако при грамотном применении они могут быть весьма полезны. Дело в том, что многие современные технологии весьма многословны и требуют большого количества вспомогательных файлов, конфигурационных файлов и т.п. (особенно этим грешит JavaEE). И вот чтобы не создавать всё это руками — можно применить аннотацию. Сказали, что этот класс является веб-сервисом, натравили на класс процессор аннотаций — и он превратил эту аннотацию в набор классов и конфигурационных файлов.

Django Annotate, сумма временных интервалов

Пытаюсь по аналогии с total_flight_time_per_day реализовать анотацию для модели JournalEntry с подсчётом кумулятивной суммы для временных интервалов от начала года до даты которая хранится в объекте модели. Получилось сделать с помощью метода в сериализаторе модели, но таким образом получается много запросов к БД соответствующее количеству экземпляров которые требуется анотировать. К сожалению не очень хорошо разбираюсь в window function, нужна помощь. Может быть есть возможность сделать это с помощью подзапросов (SubQuery)?. EDIT В виде sql это выглядит примерно так:

SELECT journalentry.id, journalentry.date, COALESCE(EXTRACT('epoch' from SUM(journalentryelement.flight_time)), 0) AS total_flight_time_per_day, (SELECT COALESCE(EXTRACT('epoch' from SUM(U1.flight_time)), 0) AS total_flight_time_per_year FROM journalentry U0 LEFT OUTER JOIN journalentryelement U1 ON (U0."id" = U1.journal_entry_id) WHERE U0.date BETWEEN '2019-01-01'::date AND journalentry.date) FROM journalentry LEFT OUTER JOIN journalentryelement ON (journalentry.id = journalentryelement.journal_entry_id) GROUP BY journalentry.id; 

Можно ли средствами orm сделать вложенный запрос который возвращает total_flight_time_per_year?

Java @Аннотации. Что это и как этим пользоваться?

Java-университет

Java @Аннотации. Что это и как этим пользоваться? - 1

Данная статья предназначена для людей, которые никогда не работали с Аннотациями, но хотели бы разобраться, что это и с чем его едят. Если же вы имеете опыт в данной сфере, не думаю, что эта статья как-то расширит ваши знания (да и, собственно, такую цель я не преследую). Также статья не подходит для тех, кто только начинает изучать язык Java. Если Вы не понимаете что такое Map<> или HashMap<> или не знаете что означает запись static < >внутри определения класса, либо же никогда не работали с рефлексией – Вам рано читать эту статью и пытаться понять, что такое аннотации. Сам по себе этот инструмент не создан для использования новичками, так как требует уже не совсем базовых пониманий взаимодействия классов и объектов (моё мнение) (спасибо комментариям за то, что показали необходимость этой приписки). Итак, приступим. Аннотации в Java являются своего рода метками в коде, описывающими метаданные для функции/класса/пакета. Например, всем известная Аннотация @Override, обозначающая, что мы собираемся переопределить метод родительского класса. Да, с одной стороны, можно и без неё, но если у родителей не окажется этого метода, существует вероятность, что мы зря писали код, т.к. конкретно этот метод может и не вызваться никогда, а с Аннотацией @Override компилятор нам скажет, что: «Я не нашел такого метода в родителях. что-то здесь нечисто». Однако Аннотации могут нести в себе не только смысл «для надежности»: в них можно хранить какие-то данные, которые после будут использоваться.

Для начала рассмотрим простейшие аннотации предоставляемые стандартной библиотекой.

  • Тип хранения (Retention);
  • Тип объекта над которым она указывается (Target).
Тип хранения
  • SOURCE — аннотация используется только при написании кода и игнорируется компилятором (т.е. не сохраняется после компиляции). Обычно используется для каких-либо препроцессоров (условно), либо указаний компилятору
  • CLASS — аннотация сохраняется после компиляции, однако игнорируется JVM (т.е. не может быть использована во время выполнения). Обычно используется для каких-либо сторонних сервисов, подгружающих ваш код в качестве plug-in приложения
  • RUNTIME — аннотация которая сохраняется после компиляции и подгружается JVM (т.е. может использоваться во время выполнения самой программы). Используется в качестве меток в коде, которые напрямую влияют на ход выполнения программы (пример будет рассмотрен в данной статье)
Тип объекта над которым указывается
  • ANNOTATION_TYPE — другая аннотация
  • CONSTRUCTOR — конструктор класса
  • FIELD — поле класса
  • LOCAL_VARIABLE — локальная переменная
  • METHOD — метод класса
  • PACKAGE — описание пакета package
  • PARAMETER — параметр метода public void hello(@Annontation String param)<>
  • TYPE — указывается над классом
@Override

Retention: SOURCE; Target: METHOD. Данная аннотация показывает, что метод над котором она прописана наследован у родительского класса. Первая аннотация с которой сталкивался каждый начинающий Java-программист, при использовании IDE, которая настойчиво пихает эти @Override. Зачастую учителя с ютуба рекомендуют либо: «сотрите чтобы не мешало», либо: «оставьте не задумываясь зачем оно здесь». На самом деле аннотация более чем полезна: она не только позволяет понять какие методы были определены в этом классе впервые, а какие уже есть у родителей (что бесспорно повышает читаемость вашего кода), но также данная аннотация служит «самопроверкой», что вы не ошиблись при определении перегружаемой функции.

@Deprecated

Retention: Runtime; Target: CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE. Данная аннотация указывает на методы, классы или переменные, которые является «устаревшими» и могут быть убраны в последующих версиях продукта. С данной аннотацией обычно сталкиваются те, кто читает документацию каких-либо API, либо той же стандартной библиотеки Java. Иногда эту аннотацию игнорируют, т.к. она не вызывает никаких ошибок и в принципе сама по себе сильно жить не мешает. Однако главный посыл, который несет в себе данная аннотация – «мы придумали более удобный метод реализации данного функционала, используй его, не используй старый» — ну, либо же — «мы переименовали функцию, а это так, для легаси оставили. » (что тоже в общем-то неплохо). Короче говоря, если видите @Deprecated — лучше стараться не использовать то, над чем она висит, если в этом нет прям крайней необходимости и, возможно, стоит перечитать документацию, чтобы понять каким образом теперь реализуется задача, выполняемая устаревшим элементом. Например вместо использований new Date().getYear() рекомендуется использовать Calendar.getInstance().get(Calendar.YEAR) .

@SuppressWarnings

Retention: SOURCE; Target: TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE Данная аннотация отключает вывод предупреждений компилятора, которые касаются элемента над которым она указана. Является SOURCE аннотацией указываемой над полями, методами, классами.

@Retention

Retention: RUNTIME; Target: ANNOTATION_TYPE; Данная аннотация задает «тип хранения» аннотации над которой она указана. Да эта аннотация используется даже для самой себя. магия да и только.

@Target

Retention: RUNTIME; Target: ANNOTATION_TYPE; Данная аннотация задает тип объекта над которым может указываться создаваемая нами аннотация. Да и она тоже используется для себя же, привыкайте. Думаю, на этом можно завершить ознакомление со стандартными аннотациями библиотеки Java, т.к. остальные используются достаточно редко и, хоть и несут свою пользу, сталкиваться с ними приходится не всем и совершенно необязательно. Если же вы хотите чтобы я рассказал о какой-то конкретной аннотации из стандартной библиотеки (либо, возможно, аннотации типа @NotNull и @Nullable которые в STL не входят) напишите в комментариях — либо вам там ответят добрые пользователи, либо я когда увижу. Если уж много людей будут просить какую-то аннотацию — также внесу её в статью.

Практическое применение RUNTIME аннотаций

Собственно, думаю, хватит теоретической болтавни: давайте перейдем к практике на примере бота. Допустим вы хотите написать бота для какой-то соцсети. У всех крупных сетей, таких как ВК, Facebook, Discord, есть свои API, которые позволяют написать бота. Для этих же сетей есть уже написанные библиотеки для работы с API, на языке Java в том числе. Поэтому не будем углубляться в работу какого-либо API или библиотеки. Всё, что нам нужно знать в данном примере — то, что наш бот умеет реагировать на сообщения, отправленные в чат, в котором, собственно, наш бот находится. Т.е допустим, у нас есть класс MessageListener с функцией:

 public class MessageListener < public void onMessageReceived(MessageReceivedEvent event) < >> 

Она отвечает за обработку принятого сообщения. Всё что нам нужно от класса MessageReceivedEvent — строка полученного сообщения (например, «Привет» или «Бот, привет»). Стоит учесть: в разных библиотеках эти классы называются по-разному. Я использовал библиотеку для Discord. И вот мы хотим сделать так, чтобы бот реагировал на какие-то команды, начинающиеся с «Бот» (с запятой или без — решайте сами: для урока предположим, что запятой там быть не должно). То есть, уже наша функция будет начинаться с чего-то вроде:

 public void onMessageReceived(MessageReceivedEvent event) < //Убираем чувствительность к регистру (БоТ, бОт и т.д.) String message = event.getMessage().toLowerCase(); if (message.startsWith("бот")) < >> 

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

 public void onMessageReceived(MessageReceivedEvent event) < //Убираем чувствительность к регистру (БоТ, бОт и т.д.) String message = event.getMessage().toLowerCase(); if (message.startsWith("бот")) < try < //получим массив ; String[] args = message.split(" "); //Для удобства уберем "бот" и отделим команду от аргументов String command = args[1]; String[] nArgs = Arrays.copyOfRange(args, 2, args.length); //Получили command = "(команда)"; nArgs = ; //Данный массив может быть пустым > catch (ArrayIndexOutOfBoundsException e) < //Вывод списка команд или какого-либо сообщения //В случае если просто написать "Бот" >> > 
  • Сделать if(command.equalsIngnoreCase(«. «))
  • Сделать switch(command)
  • Сделать ещё какой-то способ обработки.
  • Либо же прибегнуть к помощи Аннотаций.
 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; //Указывает, что наша Аннотация может быть использована //Во время выполнения через Reflection (нам как раз это нужно). @Retention(RetentionPolicy.RUNTIME) //Указывает, что целью нашей Аннотации является метод //Не класс, не переменная, не поле, а именно метод. @Target(ElementType.METHOD) public @interface Command //Описание. Заметим, что перед interface стоит @; < //Команда за которую будет отвечать функция (например "привет"); String name(); //Аргументы команды, использоваться будут для вывода списка команд String args(); //Минимальное количество аргументов, сразу присвоили 0 (логично) int minArgs() default 0; //Описание, тоже для списка String desc(); //Максимальное число аргументов. В целом не обязательно, но тоже можно использовать int maxArgs() default Integer.MAX_VALUE; //Показывать ли команду в списке (вовсе необязательная строка, но мало ли, пригодится!) boolean showInHelp() default true; //Какие команды будут считаться эквивалентными нашей //(Например для "привет", это может быть "Здаров", "Прив" и т.д.) //Под каждый случай заводить функцию - не рационально String[] aliases(); >

Важно! Каждый параметр описывается как функция (с круглыми скобками). В качестве параметров могут быть использованы только примитивы, String , Enum . Нельзя написать List args(); — ошибка. Теперь, когда мы описали Аннотацию, давайте заведем класс, назовем его CommandListener .

 public class CommandListener < @Command(name = "привет", args = "", desc = "Будь культурным, поздоровайся", showInHelp = false, aliases = ) public void hello(String[] args) < //Какой-то функционал, на Ваше усмотрение. >@Command(name = "пока", args = "", desc = "", aliases = ) public void bye(String[] args) < // Функционал >@Command(name = "помощь", args = "", desc = "Выводит список команд", aliases = ) public void help(String[] args) < StringBuilder sb = new StringBuilder("Список команд: \n"); for (Method m : this.getClass().getDeclaredMethods()) < if (m.isAnnotationPresent(Command.class)) < Command com = m.getAnnotation(Command.class); if (com.showInHelp()) //Если нужно показывать команду в списке. < sb.append("Бот, ") .append(com.name()).append(" ") .append(com.args()).append(" - ") .append(com.desc()).append("\n"); >> > //Отправка sb.toString(); > > 

Стоит отметить одно небольшое неудобство: т.к. мы сейчас боремся за универсальность, все функции должны иметь одинаковый список формальных параметров, поэтому даже если у команды нет аргументов, у функции должен быть параметр String[] args . Мы сейчас описали 3 команды: привет, пока, помощь. Теперь давайте модифицируем наш MessageListener так, чтобы он как-то с этим работал. Для удобства и скорости работы, будем сразу хранить наши команды в HashMap :

 public class MessageListner < //Map который хранит как ключ команду //А как значение функцию которая будет обрабатывать команду private static final MapCOMMANDS = new HashMap<>(); //Объект класса с командами (по сути нужен нам для рефлексии) private static final CommandListener LISTENER = new CommandListener(); static < //Берем список всех методов в классе CommandListener for (Method m : LISTENER.getClass().getDeclaredMethods()) < //Смотрим, есть ли у метода нужная нам Аннотация @Command if (m.isAnnotationPresent(Command.class)) < //Берем объект нашей Аннотации Command cmd = m.getAnnotation(Command.class); //Кладем в качестве ключа нашей карты параметр name() //Определенный у нашей аннотации, //m — переменная, хранящая наш метод COMMANDS.put(cmd.name(), m); //Также заносим каждый элемент aliases //Как ключ указывающий на тот же самый метод. for (String s : cmd.aliases()) < COMMANDS.put(s, m); >> > > public void onMessageReceived(MessageReceivedEvent event) < String message = event.getMessage().toLowerCase(); if (message.startsWith("бот")) < try < String[] args = message.split(" "); String command = args[1]; String[] nArgs = Arrays.copyOfRange(args, 2, args.length); Method m = COMMANDS.get(command); if (m == null) < //(вывод помощи) return; >Command com = m.getAnnotation(Command.class); if (nArgs.length < com.minArgs()) < //что-то если аргументов меньше чем нужно >else if (nArgs.length > com.maxArgs()) < //что-то если аргументов больше чем нужно >//Через рефлексию вызываем нашу функцию-обработчик //Именно потому что мы всегда передаем nArgs у функции должен быть параметр //String[] args — иначе она просто не будет найдена; m.invoke(LISTENER, nArgs); > catch (ArrayIndexOutOfBoundsException e) < //Вывод списка команд или какого-либо сообщения //В случае если просто написать "Бот" >> > > 

Вот собственно и всё, что нужно, чтобы наши команды работали. Теперь добавление новой команды — это не новый if, не новый case, в которых нужно было бы заново переучесть количество аргументов, также пришлось бы переписывать help, добавляя в него новые строки. Теперь же, чтобы добавить команду, нам нужно просто в классе CommandListener добавить новую функцию с аннотацией @Command и всё — команда добавлена, случаи учтены, help дополнен автоматически. Абсолютно бесспорно, что данную задачу можно решить множеством других путей. Да, всё что можно сделать при помощи аннотаций/рефлексий можно сделать и без них, вопрос лишь в удобстве, оптимальности и размерах кода, конечно же, совать Аннотацию везде где есть малейший намек на то, что получится её использовать — тоже не самый рациональный вариант, во всем нужно знать меру =). Но при написании API, Библиотек или программ, в которых возможно повторение однотипного (но не совсем одинакового) кода, аннотации — бесспорно оптимальное решение.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *