Pro Java: Оператор switch

Оператор switch состоит из выражения и тела, которое содержит различные пронумерованные точки входа. Выражение вычисляется, и управление переходит на точку входа, определенную полученным значением. Выражение должно возвращать следующие тип данных: int, short, char, byte (или их обертки), String (с Java 7) или enum. Тип данных enum мы пока не проходили.

Общая форма оператора switch имеет следующий вид:

Часто он оказывается эффективнее применения длинных последовательностей операторов if-else-if.

Например, программу из предыдущего поста можно переписать таким образом:

И варианты исполнения программы:

При выполнении оператора switch интерпретатор вычисляет значение выражения в круглых скобках, а затем ищет метку case, соответствующую полученному значению. Если интерпретатор находит метку, он начинает выполнять блок программы с первого оператора после метки case. Если интерпретатор не находит метку case с соответствующим значением, он начинает выполнение блока с первого оператора после специальной метки default:. Или, если нет метки default:, интерпретатор выполняет только соответствующий метод case если он есть, либо не выполняет ни какой если нет подходящей метки.

Можете попробовать закомментировать в предыдущем примере выполнение метки default и посмотреть как будет выполнятся программа.

Обратите внимание на использование ключевого слова break в конце каждого case в предыдущем коде. Оператор break будет описан чуть позже; в данном случае он заставляет интерпретатор покинуть оператор switch. Метки case определяют только на чальную точку нужного кода. Отдельные варианты не являются независимыми блоками программы и не содержат никакой неявной точки окончания. Поэтому при помощи оператора break или другого подходящего оператора нужно явно определить окончание каждого варианта. Если нет оператора break, оператор switch начинает выполнять код с первого оператора после соответствующей метки case и продолжает выполнять операторы, пока не достигнет конца блока. Иногда удобно писать код с последовательным переходом от одной метки case к другой, однако в 99% случаев вам придется завершать каждый раздел case и default оператором, приводящим к завершению выполнения оператора switch. Обычно в таких случаях применяют оператор break, но также подходят return и throw. Как только программа доходит до оператора break (rerturn, throw), она продолжает выполнение с первой строки кода, следующей за всем оператором switch.

Оператор switch может содержать более одной метки case для одного и того же оператора. По существу это спользование нескольких операторов case без разделяющих их операторов break.

Есть несколько важных ограничений для оператора switch и его меток case.  Во-первых типы с плавающей точкой и boolean не поддерживаются. То же самое относится к long, хотя long является целым типом. Во-вторых, значение, ассоциируемое с каждой меткой case, должно быть постоянным значением или выражением, которое может вычислить компилятор. Например, метка case не может содержать выражение, вычисляемое во время выполнения – с переменными и вызовами методов. В-третьих, значения меток case должны соответствовать типу данных выражения switch. И наконец, не разрешается создавать две и более метки case с одинаковым значением или больше одной метки default.

Вложенные операторы switch

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

В данном случае оператор case1:  внутреннего оператора switch не конфликтует с оператором case1:  внешнего оператора switch. Программа сравнивает значение переменной count только со списком ветвей case внешнего уровня. Если значение count равно 1, программа сравнивает значение переменной target c внутренним списком ветвей case.

Ну и на последок можно сказать, что как правило, оператор switch эффективнее набора вложенных операторов if. Это свойство представляет особый интерес, поскольку позволяет понять работу компилятора Java. Компилируя оператор switch, компилятор Java будет проверять каждую из констант case и создавать “таблицу переходов”, которую будет использовать для выбора ветви программы в зависимости от значения выражения. Поэтому в тех случаях, когда требуется осуществлять выбор в большой группе значений, оператор switch будет выполняться значительно быстрее последовательности операторов if-else. Это обусловлено тем, что компилятору известно, что все константы case имеют один и тот же тип, и их нужно просто проверять на предмет равенства значению выражения switch. Компилятор не располагает подобными сведениями о длинном списке выражений оператора if.

Подробное руководство по операторам в Java

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

Различные типы операторов в Java

Java предлагает следующие операторы:

  • Унарные операторы
  • Арифметические операторы
  • Побитовые операторы
  • Логические операторы
  • Реляционные операторы
  • Сменные операторы
  • Тернарные операторы
  • Операторы присваивания

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

Унарные операторы Java

Унарные операторы в Java требуют только одного операнда. Они используются для увеличения/уменьшения и согласования значения. Также можно инвертировать логическое значение с помощью унарных операторов. В приведенной ниже таблице показаны различные унарные операторы и то, что они делают.

Унарный оператор
Описание

++

Увеличивает значение на 1. Если используется перед выражением, сначала увеличивается значение, а затем вычисляется результат. При использовании после выражения сначала вычисляется результат, а затем значение увеличивается.

Уменьшает значение на 1. Если используется перед выражением, значение сначала уменьшается, а затем вычисляется результат. При использовании после выражения сначала вычисляется результат, а затем значение уменьшается.

~

Используется для согласования значения.

!

Инвертирует логическое значение.

Вот пример использования унарных операторов.

Арифметические операторы Java

Арифметические операторы в Java выполняют мультипликативные и аддитивные операции, такие как сложение, вычитание, умножение, деление и модуль. В таблице ниже показаны различные арифметические операторы и то, что они делают.

Арифметический оператор
Описание

+

Выполняет дополнение

Используется для вычитания

*

Выполняет умножение

/

Используется для разделения

%

Выполняется по модулю (возвращает остаток).

В приведенном ниже примере показано использование всех арифметических операторов.

Побитовые операторы Java

Побитовые операторы в Java выполняют операции над отдельными битами. В таблице ниже показаны различные побитовые операторы и то, что они делают.

Побитовый оператор 9

Оператор побитового XOR вернет результат побитового XOR для каждого входного значения

~

Оператор побитового дополнения инвертирует биты всех входных значений

Давайте рассмотрим пример ниже, чтобы понять побитовый оператор. Предположим, что значение a равно 108, а значение b равно 29. Двоичный формат этих значений:

.

108: 0110 1100

9б = 0111 0001 = 113

~a = 1001 0011 = -109 (не путайтесь, он вычисляет ответ в форме дополнения до 2, поскольку это двоичное число со знаком).

Теперь посмотрите, дает ли наша программа на Java такие же результаты.

Логические операторы Java

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

Логические операторы
Описание

&&

Логическое И возвращает истину, если все выражения истинны

||

Логическое ИЛИ возвращает истину, если одно из выражений истинно

!

Логическое НЕ возвращает обратное выражение (если истинно, то ложно и наоборот)

В приведенном ниже примере показано использование логических операторов в Java.

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

Реляционные операторы Java

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

Реляционные операторы
Описание

==

Возвращает true, если первое выражение равно второму выражению

!=

Возвращает true, если левый операнд не равен правому

<

Возвращает true, если левый операнд меньше правого

<=

Возвращает true, если левый операнд меньше или равен правому операнду

>

Возвращает true, если левый операнд больше правого

>=

Возвращает true, если левый операнд больше или равен правому операнду

экземпляр из

Возвращает значение true, если первый операнд (обычно объект) является экземпляром второго операнда (обычно родительского класса)

Давайте рассмотрим пример использования операторов отношения в Java.

Операторы смены Java

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

Сменные операторы
Описание

<<

Оператор сдвига влево сдвигает биты влево на указанное число, тем самым умножая число на 2 в указанной степени числа

>>

Оператор сдвига вправо сдвигает биты вправо на указанное число, тем самым делит число на 2 в указанной степени числа

>>>

Оператор беззнакового сдвига вправо сдвигает биты вправо и изменяет бит четности на 0, но только если входное значение отрицательное

В приведенном ниже примере показано использование операторов сдвига.

Тернарный оператор Java

Тернарный оператор в Java используется как сокращенный заменитель операторов if-else. Его также называют смешанным оператором. В таблице ниже показаны различные тернарные операторы и то, что они делают.

Тернарный оператор
Описание

? :

Если условие истинно, выполняется оператор перед ‘:’; в противном случае выполняется оператор после ‘:’

Давайте рассмотрим пример использования тернарного оператора в Java.

Операторы присваивания Java

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

В таблице ниже показаны различные операторы присваивания и то, что они делают.

Оператор присвоения
Описание

=

Присваивает значение операнда справа операнду слева

Вы также можете комбинировать оператор присваивания с другими операторами, чтобы сократить оператор. Например, мы можем объединить = с +, чтобы написать +=10 вместо того, чтобы писать а=а+10. Точно так же мы можем комбинировать = с -, *, /, % и другими операторами. В приведенном ниже примере показано использование оператора присваивания.

Приоритет и ассоциация операторов Java

Если в одном операторе более одного оператора, приоритет определяет, как они будут оцениваться и выполняться. Например, умножение имеет более высокий приоритет, чем сложение. Следовательно, в выражении a=8+3*4 a станет равным 20, а не 44, поскольку 3 сначала умножается на 4, а затем прибавляется к 12. Точно так же все операторы в Java имеют приоритет. У них также есть ассоциация, которая определяет, будут ли операторы оцениваться слева направо или наоборот. В таблице ниже показаны приоритеты и связи операторов Java. Операторы, расположенные выше в таблице, имеют более высокий приоритет, чем операторы, расположенные ниже.

Тип оператора

Категория

Приоритет

Ассоциация

Унарный

Постфикс

выражение++ выражение—

Слева направо

Префикс

++выражение —выражение +выражение -выражение ~  !

Справа налево

Арифметика

Мультипликатив

*  /  %

Слева направо

Добавка

+ —

Слева направо

Смена

Смена

<<  >>  >>>

Слева направо

Реляционный

Сравнение

<  >  <=  >=  instanceof

Слева направо

Равенство

==  !=

Слева направо

Побитовый

И

и

Слева направо 9

Слева направо

ИЛИ

|

Слева направо

Логический

И

&&

Слева направо

ИЛИ

||

Слева направо

9=  |=  <<==  >>==  >>>==

Справа налево

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

Первая попытка Java Operator SDK. Демо на java-operator-sdk и сравнение… | by Stefanie Lai

Демонстрация java-operator-sdk и сравнение ее с Kubebuilder

Опубликовано в

·

8 мин чтения

·

3 окт. 2022 г.

автор

Я работал над разработкой оператора Kubernetes для облегчения управления кластером. При разработке оператора мы обычно фокусируемся на двух пунктах:

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

Не требует программирования. Пользователи могут выбрать любой язык для контроллера CRD.

— с https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/#choosing-a-method-for-adding-custom-resources

Я подробно описал реализации оператора в предыдущей статье Kubernetes Operator for Beginners — What, Why, How , , в которой мы построили оператор поверх фреймворка Kubebuilder.

Go — наиболее часто используемый язык для разработки операторов, но не единственный. Java хорошо работает при разработке операторов и имеет свои сильные стороны, которые будут показаны в демо ниже. И я надеюсь, что после прочтения этой статьи вы получите представление о том, как разработать оператор на Java, как реализовать тесты на операторах Java, а также о различном опыте работы с Java VS Go Kubebuilder.

Java Operator SDK

Хотите ли вы создавать приложения, которые работают сами по себе или предоставление инфраструктуры из кода Java, операторы Kubernetes — это то, что вам нужно. JAVA-OPERATOR-SDK основан на клиенте Fabric8 Kubernetes и позволит Java-разработчикам с по освоить этот новый способ автоматизации.

Наш оператор Java будет основан на фреймворке Java Operator SDK (JOSDK), который имеет развитую клиентскую библиотеку (fabric8) для взаимодействия с сервером API Kubernetes. Это ключевая часть, поскольку оператор в значительной степени полагается на API для взаимодействия с кластером.

— от Architecture and Internals (javaoperatorsdk.io)

JOSDK полагается на механизм наблюдения и распределения событий Kubernetes, и под капотом фреймворка реализованы четыре основные функции.

  • Оберните ткань 8 и настройте ее для прослушивания изменений в указанных настраиваемых ресурсах.
  • Предоставляет интерфейс для реализации циклов координации для определенных типов ресурсов.
  • Эффективное планирование событий изменений и фильтрация нежелательных событий с помощью фильтров.
  • Повторите неудачную попытку координации.

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

Demo

Для лучшего сравнения я воспроизведу UserIdentityV1 , созданный с помощью Kubebuilder.

Код конструкции

Как правило, нам нужен maven для создания проекта Java и создания файловых структур, таких как src/main/java, src/test и т. д. И зависимости должны быть добавлены пользователями, поскольку JOSDK не предоставляет архитектуру maven для быстрой генерации.

Я скопировал «чистый» фрейм у операторов-образцов, чтобы сэкономить время.

А файл pom выглядит так, как показано ниже, это окончательный вариант после того, как я развязал все узлы. Например, я добавил несколько зависимостей Fabric8, которые не указаны в документации. Если вы не знакомы с разработкой Fabric8, на их поиск уходит время.

Define CRD

Я прочел документацию по началу работы с java-operator-sdk , но не смог найти инструмент формирования шаблонов. Поэтому я добавил код шаг за шагом со ссылкой на пример в Sample-Controller.

  • Определить , спецификация и , статус соответственно. Требуемая информация о роли объявлена ​​в спецификации , а информация о состоянии операции и ошибках возвращается в .0814 статус .
  • Определить CRD, расширить CustomResource и реализовать интерфейс Namespaced .

Обратите внимание на следующие моменты.

  • Fabric8 предоставляет набор аннотаций, связанных с метаданными.
  • Проверка может быть добавлена ​​к полям с помощью библиотеки jsonProperty и javax.validation.constraints , что в конечном итоге отражается в определении CRD, например, @NotNull делает поле помеченным как требуется в CRD
  • Пространство имен помечает CRD как область пространства имен или область кластера .

Для получения информации о некоторых нативных ресурсах Kubernetes вы можете обратиться к этой памятке, предоставленной Fabric8.

Генерация CRD YAML

Чтобы взломать этот крепкий орешек, я потратил много времени на чтение документации, чтобы не писать YAML самостоятельно, после того как мне не удалось найти инструмент для генерации CRD YAML на Java.

Из Unsplash, @rocinante_11

К счастью, мне удалось найти создание CRD в Java и наоборот в kubernetes-client/java .

  • Добавьте следующую зависимость в pom.
  
io.fabric8
crd-generator-apt
provided
  • Run 9081 4 мвн компиляция .
  • Скопируйте <множественное число>.<группа>-<версия спецификации CRD>.yml под target/class/META-INF/fabric8/ до k8s/ .

Определение согласователя

Я чувствую облегчение, добравшись до этой части, которая намного проще.

  • Реализовать метод согласования интерфейса Reconciler . Обновление ресурса каждый раз запускает выполнение согласователя. Здесь мне нужно обновить ресурс, сгенерировать соответствующий ClusterRoleBinding и сохранить его с Fabric8 client и, наконец, обновить статус ресурса.
  • Реализовать интерфейс Cleaner для обработки удаления.

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

  • Внедрение интерфейса ErrorStatusHandler для обработки состояния ошибки, например, для настройки синтаксического анализа ошибок кластера и возврата простых для понимания сообщений об ошибках в соответствии со сценариями.
  • Предотвращение слишком частых вызовов с помощью интерфейса MaxReconciliationInterval для управления интервалом согласования. Эту аннотацию необходимо загрузить в класс.
  • Использование GradualRetry для управления максимальным количеством попыток в случае сбоя и предотвращения перегрузки APIServer из-за неправильной настройки.
  • Установка поля ObservedGeneration с интерфейсом ObservedGenerationAware , который является эффективным методом управления оптимистичной блокировкой ресурсов Kubernetes.
  • Использование аннотации RateLimited для управления частотой обновления, например RateLimited(maxReconciliations = 2, within = 3, unit = TimeUnit.SECONDS) , ограничивает обновление согласователя дважды максимум в течение 3 секунд.
  • Реализовать веб-перехватчик допуска.

Дополнительные функции см. в официальной документации и исходном коде.

Определение основного метода

Теперь последний шаг, инициализация согласователя и определение основного метода Java.

Модульный тест

Сквозной тест состоит из 5 шагов.

  • Инициализация KubernetesClient
  • Внедрение AbstractOperatorExtension и регистрация согласования
  • Загрузка роли в локальный Kubernetes
  • Создать новый UserIdentity , который затем отправляется клиентом
  • Проверить после a while

Тест развертывания

Развертывание оператора в соответствующем кластере за 6 шагов.

  • Создайте своеобразный кластер и переключите kubecontext
  • Отправьте локальный CRD в кластер с помощью kubectl apply -f k8s/useridentities.identity.company.org-v1.yml
  • Создайте образ оператора с помощью maven. Здесь jib-maven-plugin используется для отправки изображений в докер при запуске mvn install или mvn jib:dockerBuilder
  • Создайте развертывание вручную и отправьте
  • Создайте 908 14 тест-нс и отправьте k8s/roles-test. yml в кластер для создания Role
  • Отправьте UserIdentity.yaml , чтобы увидеть ClusterRolebinding , созданный в кластере

Язык

JOSDK <= Kubebuilder

JOSDK использует всю экосистему Java, которая была создана многими интернет-компаниями благодаря 20-летнему распространению Java. Существует полный набор процессов, от родителя maven, тестовых фреймворков до интеграции CI/CD и т. д., а также гораздо более богатых сторонних библиотек. Но JOSDK в основном полагается на Fabric8 и не может работать должным образом, если API Kubernetes не инкапсулированы в Fabric8.

С другой стороны, Kubebuilder является первоклассным в экосистеме Kubernetes, которая в основном построена на Go. И он может быстро интегрировать различные пакеты Kubernetes, такие как Controller-runtime , что позволяет сосредоточиться на разработке функций.

Инструменты

JOSDK ** < Kubebuilder *****

JOSDK слабее в этом аспекте. Генератора кода не нашел, а только java-operator-plugin, инструмент на основе operator-sdk. Хотя мы можем быстро начать проект по разработке оператора, следуя руководству, оператор фокусируется только на quarkus , а не оригинальный оператор Java, который мне нужен.

Kubebuilder гораздо более зрелый, чем JOSDK, хотя JOSDK также предоставляет несколько подключаемых модулей maven и генераторов Fabric8. Это видно непосредственно из таблицы ниже.

CRD Definition

JOSDK*** < Kubebuilder *****
JOSDK плохо справляется с автоматизацией. Несмотря на то, что интерфейсы, такие как CustomResource , предоставляются, создание класса Java, соответствующего CRD, по-прежнему требует ручного создания спецификации 9.0815 и превращаются в , хотя специальных полей нет. Аннотации необходимо добавить для APIGroup и версии из-за отсутствия инструментов для их создания. Единственным преимуществом является то, что некоторые аннотации удобны.

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

Поддерживаемые функции

JOSDK **** <= Kubebuilder *****

Что касается поддерживаемых функций, то их самая большая разница заключается в том, что они на самом деле реализуют: JOSDK реализует согласователь, а контроллер встроен в фреймворк и распределяет запросы по событиям.

Хотя Kubebuilder реализует контроллер, который запускается автоматически через определенные промежутки времени.

Кроме того, следует отметить их поддержку следующих операций.

  • Обновление ресурса . Они в основном одинаковы с фреймворком, который делает больше всего. И JOSDK пропускает Получить .
  • чтение и запись собственных ресурсов Kubernetes . Разница заключается в API Fabric8 и собственном API Kubernetes, особенно в API среды выполнения контроллера. А Java нуждается в большем количестве кода для создания и обновления объектов, таких как геттеры и сеттеры.
  • Удаление . JOSDK более элегантен благодаря независимому интерфейсу Cleaner , в то время как Kubebuilder справляется с этим с помощью DeletionTimeStamp и 9.0814 Финиализатор .
  • Контроль согласования . JOSDK имеет отличный дизайн с аннотациями; В то время как Kubebuilder обрабатывает его в контроллере, например, используя ratelimit .
  • Управление зависимостями . Дизайн maven делает библиотеки, от которых зависит JOSDK, разбросанными, от операторской среды до Fabric8, затем до тестирования, и многие требуемые API-интерфейсы не могут быть найдены в документации. В то время как у Kubebuilder меньше зависимостей, и в основном после генерации кода дополнительные пакеты не требуются.
  • Обработка ошибок . JOSDK имеет централизованную обработку исключений, что упрощает написание и тестирование логики согласования. И Kubebuilder полагается на обработку ошибок Go, и нам нужно обрабатывать шаг за шагом во время согласования.
  • Вебхуки . JOSDK не имеет достаточной поддержки веб-перехватчиков доступа. Нам нужно реализовать функции webhook с перехватчиками, за исключением проверки некоторых полей CRD. Прочтите этот выпускной билет, чтобы узнать больше.

Test Support

JOSDK ***** > Kubebuilder

JOSDK предлагает вам очень хороший опыт в тестировании: отлично поддерживаются как фиктивные модульные тесты, так и тесты E2E; Нет необходимости использовать контейнеры или локальные кластеры Kubernetes; Отладка точки останова отлично поддерживается IDE. Кроме того, Java лучше справляется с удаленной отладкой.

Для сравнения, Kubebuilder плохо поддерживает тесты и больше полагается на другие пакеты Go, такие как ginkgo . И это не так хорошо, как Java в отладке и насмешках.

Документация

JOSDK * < Kubebuilder ****

В документации JOSDK отсутствует информация для пошаговой разработки оператора.