Введение
Для работы в AnyLogic используется полноценный объектно-ориентированный язык
Java. Глубокого знания всей платформы не требуется — достаточно понимать базовые принципы синтаксиса и уметь решать типовые задачи, возникающие при разработке имитационных моделей.
Ранее мы уже применяли фрагменты Java-кода. Обращение к объектам происходит через
точку: запись
main.объект даёт доступ к подобъекту внутри
main, а последующие точки — к свойствам и методам этого подобъекта. Основной инструментарий, который понадобится: условные операторы, циклы и ряд встроенных функций.
Базовый синтаксис
•
Регистр имеет значение:
MyVar и
myvar — разные переменные.
• Имена не могут содержать
пробелов; для разделения слов используют нижнее подчёркивание.
• Каждая инструкция завершается
точкой с запятой (
;).
• Вызов любой функции требует
круглых скобок. Если аргументы не передаются, скобки пусты, например
time(). Функция добавления элемента
add(элемент) уже принимает аргумент.
•
Точечная нотация организует доступ к внутренним элементам объекта:
agent.event.restart() означает вызов метода
restart() события
event, принадлежащего агенту
agent.
•
Массивы индексируются с нуля; последний элемент массива длины N имеет индекс N–1.
Типы данных
Примитивные типы:
•
double — вещественное число (например, 1.5).
•
int — целое число (включая отрицательные).
•
boolean — логический тип, принимающий исключительно
true или
false. Использование 1 и 0 недопустимо.
Ссылочные типы (классы):
•
String — текстовая строка, заключается в двойные кавычки.
• Коллекции:
ArrayList,
LinkedList.
LinkedList дополнительно поддерживает доступ по ключу, который может быть содержательным объектом.
• Геометрические и другие классы, например
Shape3DPolyline (трёхмерная ломаная). Полный список доступен в справочнике AnyLogic.
Операторы
Арифметические: +,
-, *,
/,
% (остаток от деления).
Логические: && (и),
|| (или),
! (отрицание).
Сравнения: <,
<=,
>,
>=,
== (проверка равенства),
!= (проверка неравенства).
Одиночный знак
= выполняет
присваивание.
Целочисленное деление: если оба операнда типа
int, дробная часть отбрасывается.
3 / 2 даёт
1, а
2 / 3 —
0.
Приоритеты: умножение и деление выше сложения и вычитания. Операции одного приоритета выполняются слева направо. Для изменения порядка используют скобки.
Конкатенация строк: оператор + склеивает строки.
Составное присваивание: +=,
-=,
*=,
/= (например,
a += b эквивалентно
a = a + b).
Инкремент/декремент: ++ и
-- увеличивают или уменьшают переменную на 1.
Вызов методов и доступ к полям
Метод вызывается указанием имени с круглыми скобками. Параметры передаются внутри скобок:
moveTo(getX(), getY() + 100) перемещает агента по оси Y на 100 единиц вверх.
traceln("текст") выводит сообщение в консоль.
К
полям (атрибутам) обращаются также через точку. Например,
rectangle.setFillColor(red) вызывает метод заливки цветом. Получение значения поля другого агента:
sum += agents.get(i).X — здесь
agents.get(i) возвращает i-го агента, а
.X — его параметр.
Популяции агентов
Популяция
people обладает встроенными методами:
•
people.size() — текущее количество агентов.
•
people.get(i) — i-й агент (индекс от 0 до
size()-1).
•
people.random() — случайный агент.
•
add_people() — добавляет нового агента в популяцию.
• agent.remove_people() — удаляет конкретного агента из популяции.
Условный оператор if
text
if (условие) {
// действия, если истина
} else {
// действия, если ложь
}
Если в блоке одна инструкция, фигурные скобки можно опустить. При двух и более — обязательны. Рекомендуется выделять тело отступами. Существует краткая форма без
else.
Циклы
Перебор популяции (for-each):
text
for (Person p : people) {
total += p.income;
}
Person — класс агентов,
people — популяция, p — временная переменная для каждого элемента.
Классический for со счётчиком:
text
for (int i = 0; i < distributor.numOfTrucks; i++) {
// тело цикла
}
Переменная i пробегает от 0 до значения
distributor.numOfTrucks, увеличиваясь на 1.
Цикл while:
text
while (условие) {
// тело
}
Выполняется, пока условие истинно. Если изначально ложно — ни разу не выполнится.
Цикл do-while:
text
do {
// тело
} while (условие);
Гарантирует хотя бы один проход, так как проверка происходит после итерации.
Оператор switch
text
switch (выражение) {
case значение1:
// действие
break;
case значение2:
// действие
break;
default:
// действие, если ни одно значение не подошло
}
break прерывает проверку последующих
case. Секция
default необязательна.
Функции и return
Каждая функция должна завершаться оператором
return. Если возврат значения не нужен, пишут
return null.
Пример поиска первого грузовика в определённом состоянии:
text
for (Truck t : fleet) {
if (t.state == AT_DISTRIBUTOR) {
return t;
}
}
return null;
Как только условие выполнилось, функция возвращает найденный объект и прекращает работу. Если ни один не подошёл, возвращается
null.
Комментарии
Однострочные начинаются с
// и действуют до конца строки. Многострочные заключаются между
/* и
*/.
Диаграмма действий
Диаграмма действий — графическое представление алгоритма, заменяющее ручное написание управляющих конструкций.
• Прямоугольник — присваивание или вызов метода.
• Ромб — условие if, внутри записывается только само условие; ветви «истина» и «ложь» ведут к соответствующим блокам.
• Шестиугольник — цикл for, где внутри указывается параметр цикла, а тело описывается отдельным блоком.
Такой подход делает логику наглядной и удобен при документировании.
Источники информации
Помимо литературы по Java, справочная система AnyLogic содержит детальное описание использования языка. Эффективный метод освоения — открыть встроенную модель-пример, близкую к вашей задаче, изучить синтаксис и адаптировать код под свои нужды.
Краткие итоги
Освоение Java в AnyLogic отталкивается от объектной природы моделей: любое действие строится как взаимодействие с объектами через точечную нотацию. Материал выстраивает фундамент, начиная с жёстких синтаксических правил — учёт регистра, обязательность точки с запятой и скобок, корректное именование переменных, — без которых код не будет скомпилирован. Далее вводится система типов, где особый акцент сделан на различиях между примитивными числами и булевыми значениями, а также на том, что строки и коллекции являются полноценными классами. Это формирует правильное понимание операций, особенно целочисленного деления, способного привести к трудноуловимым ошибкам в расчётах.
Практическая мощь раскрывается через управляющие конструкции. Условный оператор
if становится главным инструментом принятия решений; демонстрируется, как избегать двусмысленности с помощью фигурных скобок и отступов. Циклы представлены в трёх вариантах, каждый из которых решает свой класс задач:
for-each идеален для обхода популяций агентов, классический
for — для итераций со счётчиком, а
while и
do-while покрывают сценарии с заранее неизвестным числом повторений, причём подчёркивается гарантированное однократное выполнение последнего. Оператор
switch дополняет арсенал ветвления, позволяя лаконично обрабатывать множественный выбор без каскада
if-else.
Центральное место отводится работе с популяциями агентов — ядру агентного моделирования. Набор методов
size(),
get(),
random(),
add_...() и
remove_...() покрывает все типовые потребности: от сбора статистики до динамического изменения состава популяции. Механизм функций с
return даёт возможность инкапсулировать поиск, расчёт или преобразование, чётко ограничивая зону ответственности кода, а
return null служит безопасным способом завершить функцию, когда результат не требуется.
Визуализация логики с помощью диаграмм действий переводит текстовый код в интуитивно понятные блок-схемы, что упрощает коммуникацию в команде и документирование. Наконец, прагматическая рекомендация ориентироваться на готовые примеры из библиотеки AnyLogic замыкает образовательный контур: разработчик получает не только теорию, но и стратегию самостоятельного решения задач через адаптацию существующих решений. Совокупность этих элементов образует ровно тот минимальный, но достаточный инструментарий Java, который позволяет существенно расширить стандартную функциональность AnyLogic, переходя от простого размещения готовых блоков к написанию гибкой логики, управляющей поведением агентов и экспериментами.
1. Java в AnyLogic требует соблюдения регистра, завершения инструкций точкой с запятой и использования скобок для всех функций.
2. Доступ к свойствам и методам объектов всегда осуществляется через точечную нотацию.
3. Массивы и коллекции индексируются с нуля.
4. Примитивные типы включают double, int, boolean; для логических значений используются только true и false.
5. Целочисленное деление отбрасывает дробную часть, что необходимо учитывать при вычислениях.
6. Логические операторы &&, ||, ! и сравнения ==, != формируют условия ветвления.
7. Популяции агентов предоставляют методы size(), get(), random(), add_...(), remove_...() для динамического управления составом.
8. Оператор if может использоваться в полной (if-else) и краткой форме; блоки из нескольких инструкций требуют фигурных скобок.
9. Цикл for-each упрощает перебор агентов популяции, классический for — итерации со счётчиком, while и do-while — циклы с условием.
10. do-while гарантирует выполнение тела хотя бы один раз, в отличие от while.
11. Каждая функция обязана завершаться return; для отсутствия значимого результата используется return null.
12. Диаграммы действий заменяют текстовые управляющие конструкции графическими элементами, повышая наглядность алгоритма.
1. Почему имена Agent и agent считаются разными, и как это свойство языка называется?
2. Для чего после каждой инструкции в Java ставится точка с запятой?
3. Каким образом можно обратиться к атрибуту speed объекта car?
4. Какие три примитивных типа данных обсуждались, и какие значения допустимы для логического типа?
5. Чем опасно деление двух целых чисел, если ожидается вещественный результат? Приведите пример.
6. Как проверить равенство двух переменных и чем эта операция отличается от присваивания?
7. Какие методы позволяют получить размер популяции агентов и случайного агента из неё?
8. В каком случае при использовании if обязательно заключать тело в фигурные скобки?
9. Опишите синтаксис цикла для перебора всех агентов популяции customers класса Customer.
10. В чём принципиальное различие между циклами while и do-while?
11. Для чего в операторе switch применяется break, и что произойдёт, если его опустить?
12. Какими графическими символами на диаграмме действий обозначаются условие и цикл for?