Вспомогательные классы для работы со строками в java
Содержание:
- Тернарная операция
- Блоки кода и циклы, IIFE
- Разделение
- JVM, JRE и JDK
- Основы
- Static
- Метка
- Текстовое поле
- Causes of Error Code 0xc0000001
- Операции с числами
- Кнопка
- 3 Остаток от деления целых чисел
- Стиль оформления кода
- 2.3 Арифметические операторы
- Практическое применение побитовых операций
- Нам доверяют
- Безымянный
- 3 String Pool
- Запрещенные темы для публикаций
- Загрузка статического и динамического класса
- 3 Создание подстрок
Тернарная операция
Операция «?:» называется тернарной, потому что он принимает три операнда.
<выражение_boolean> ? <выражение1> : <выражение2>
1 | <выражение_boolean> ? <выражение1> : <выражение2> |
Тернарная операция вычисляет
<выражение_boolean>, если оно равно
true, то вычисляет и возвращает
<выражение1>, а если
false, то
<выражение2> .
Java
class Main {
public static void main(String[] args) {
int x = 3 > 2 ? 5 : -3; // 5
String str1 = 3 == 2 ? «YES»: «NO»; //»NO»
System.out.println(x);
System.out.println(str1);
}
}
1 |
classMain{ publicstaticvoidmain(Stringargs){ intx=3>2?5-3;// 5 Stringstr1=3==2?»YES»»NO»;//»NO» System.out.println(x); System.out.println(str1); } } |
Блоки кода и циклы, IIFE
Предыдущие примеры сосредоточены на функциях. Но лексическое окружение существует для любых блоков кода .
Лексическое окружение создаётся при выполнении блока кода и содержит локальные переменные для этого блока. Вот пара примеров.
В следующем примере переменная существует только в блоке :
Когда выполнение попадает в блок , для этого блока создаётся новое лексическое окружение.
У него есть ссылка на внешнее окружение, так что может быть найдена. Но все переменные и Function Expression, объявленные внутри , остаются в его лексическом окружении и не видны снаружи.
Например, после завершения следующий не увидит , что вызовет ошибку.
Для цикла у каждой итерации своё отдельное лексическое окружение. Если переменная объявлена в , то она также в нём:
Обратите внимание: визуально находится снаружи. Но конструкция – особенная в этом смысле, у каждой итерации цикла своё собственное лексическое окружение с текущим в нём
И так же, как и в , ниже цикла невидима.
Мы также можем использовать «простые» блоки кода , чтобы изолировать переменные в «локальной области видимости».
Например, в браузере все скрипты (кроме ) разделяют одну общую глобальную область. Так что, если мы создадим глобальную переменную в одном скрипте, она станет доступна и в других. Но это становится источником конфликтов, если два скрипта используют одно и то же имя переменной и перезаписывают друг друга.
Это может произойти, если название переменной – широко распространённое слово, а авторы скрипта не знают друг о друге.
Если мы хотим этого избежать, мы можем использовать блок кода для изоляции всего скрипта или какой-то его части:
Из-за того, что у блока есть собственное лексическое окружение, код снаружи него (или в другом скрипте) не видит переменные этого блока.
В прошлом в JavaScript не было лексического окружения на уровне блоков кода.
Так что программистам пришлось что-то придумать. И то, что они сделали, называется «immediately-invoked function expressions» (аббревиатура IIFE), что означает функцию, запускаемую сразу после объявления.
Это не то, что мы должны использовать сегодня, но, так как вы можете встретить это в старых скриптах, полезно понимать принцип работы.
IIFE выглядит так:
Здесь создаётся и немедленно вызывается Function Expression. Так что код выполняется сразу же и у него есть свои локальные переменные.
Function Expression обёрнуто в скобки , потому что, когда JavaScript встречает в основном потоке кода, он воспринимает это как начало Function Declaration. Но у Function Declaration должно быть имя, так что такой код вызовет ошибку:
Даже если мы скажем: «хорошо, давайте добавим имя», – это не сработает, потому что JavaScript не позволяет вызывать Function Declaration немедленно.
Так что, скобки вокруг функции – это трюк, который позволяет показать JavaScript, что функция была создана в контексте другого выражения, и, таким образом, это функциональное выражение: ей не нужно имя и её можно вызвать немедленно.
Кроме скобок, существуют и другие пути показать JavaScript, что мы имеем в виду Function Expression:
Во всех перечисленных случаях мы объявляем Function Expression и немедленно выполняем его. Ещё раз заметим, что в настоящий момент нет необходимости писать подобный код.
Разделение
Класс Java String содержит метод split(), который можно использовать для разделения String на массив объектов String:
String source = "A man drove with a car."; String[] occurrences = source.split("a");
После выполнения этого кода Java массив вхождений будет содержать экземпляры String:
"A m" "n drove with " " c" "r."
Исходная строка была разделена на символы a. Возвращенные строки не содержат символов a. Символы a считаются разделителями для деления строки, а разделители не возвращаются в результирующий массив строк.
Параметр, передаваемый методу split(), на самом деле является регулярным выражением Java, которые могут быть довольно сложными. Приведенное выше соответствует всем символам, даже буквам нижнего регистра.
Метод String split() существует в версии, которая принимает ограничение в качестве второго параметра — limit:
String source = "A man drove with a car."; int limit = 2; String[] occurrences = source.split("a", limit);
Параметр limit устанавливает максимальное количество элементов, которое может быть в возвращаемом массиве. Если в строке больше совпадений с регулярным выражением, чем заданный лимит, то массив будет содержать совпадения с лимитом — 1, а последним элементом будет остаток строки из последнего среза — 1 совпадением. Итак, в приведенном выше примере возвращаемый массив будет содержать эти две строки:
"A m" "n drove with a car."
Первая строка соответствует регулярному выражению. Вторая — это остальная часть строки после первого куска.
Выполнение примера с ограничением 3 вместо 2 приведет к тому, что эти строки будут возвращены в результирующий массив String:
"A m" "n drove with " " car."
Обратите внимание, что последняя строка по-прежнему содержит символ в середине. Это потому, что эта строка представляет остаток строки после последнего совпадения (a после ‘n водил с’)
Выполнение приведенного выше примера с пределом 4 или выше приведет к тому, что будут возвращены только строки Split, поскольку в String есть только 4 совпадения с регулярным выражением a.
JVM, JRE и JDK
Вот так и происходит вся магия: логика (т.е. код) прописывается в java файле, который затем преобразуется в файл класса. Машина его читает и выполняет.
Поток JVM, JRE и JDK
А теперь подробнее:
- JVM — виртуальная машина Java, выполняющая байт-код Java.
- JVM можно загружать на разном железе. Байт-коды — это машинный язык JVM. Поэтому Java является самым портируемым языком. JVM — это некий объект, который и обеспечивает портируемость. Для разных операционных систем (Mac, Windows, Linux и т.д.) придуманы свои реализации JVM.
- JRE — среда выполнения Java, достаточная для запуска программы.
- JRE = JVM + файлы библиотеки/пакеты классов (Util, Lang, Math etc).
- JDK — пакет средств разработки на Java. Нужен для написания, компиляции и выполнения программы.
- JDK = JRE + инструменты, необходимые для разработки Java-программы.
Основы
Теперь, когда вы знаете, что такое модуль и каковы преимущества его, давайте взглянем на основы.
Содержат один или несколько пакетов
Модуль — это один или несколько пакетов Java, которые принадлежат друг другу. Может быть либо полным приложением, API-платформой, либо сторонним API.
Наименование
Должен иметь уникальное имя. Например, допустимое имя может быть:
com.blog.mymodule
Имя следует тем же правилам именования, что и для пакетов. Однако не следует использовать подчеркивания (_). В Java 9 и более поздних версиях допустимо использовать подчеркивание в качестве зарезервированного идентификатора.
Рекомендуется называть модуль так же, как и имя корневого пакета, содержащегося в нем. Если это возможно (в некоторых случаях может содержаться несколько корневых пакетов).
До Java 9 все классы для приложения или API были вложены непосредственно в каталог корневого класса (который был добавлен в путь к классам) или непосредственно в файл JAR. Например, структура каталогов для скомпилированных пакетов com.blog.mymodule будет выглядеть следующим образом:
com/blog/mymodule
Чуть графически это будет выглядеть так:
- com
- blog
- blog
- MyModule
Начиная с Java 9, модуль должен быть вложен в корневой каталог с тем же именем, что и он сам. В приведенном выше примере у нас есть структура каталогов для пакета с именем com.blog.mymodule. Он должен содержаться в модуле с тем же именем (также com.blog.mymodule).
Структура в этом случае будет выглядеть следующим образом:
com.blog.mymodule/com/blog/mymodule
Чуть графически это будет выглядеть так:
- com.blog.mymodule
- com
- blog
- com
- com
- blog
- blog
- MyModule
Корневой каталог используется как для исходных файлов, так и для скомпилированных классов. Это означает, что если ваш проект имеет корневой каталог источника с именем src / main / java — тогда каждый модуль в проекте будет иметь свой собственный корневой каталог в каталоге src/main/java. Например:
src/main/java/com.blog.module1 src/main/java/com.blog.module2
Такая же структура каталогов будет видна в выходном каталоге компилятора.
Обычно в одном проекте используется только один модуль. В этом случае вам все равно понадобится корневой каталог, но выходные корневые каталоги исходного кода и компилятора будут содержать только один корневой каталог.
Дескриптор (module-info.java)
Каждый модуль нуждается в дескрипторе с именем module-info.java, который должен находиться в соответствующем корневом каталоге. Для корневого каталога src / main / java / com.blog.mymodule путь к дескриптору будет src / main / java / com.blog.mymodule / module-info.java.
Дескриптор указывает, какие пакеты экспортирует модуль, и какие еще требуются ему. Вот как выглядит базовый пустой дескриптор:
module com.blog.mymodule { }
Сначала следует ключевое слово module, за которым имя модуля, а затем набор фигурных скобок. Экспортированные пакеты и необходимые модули будут указаны в них.
Экспорт
Модуль обязан явно экспортировать все пакеты в нем, которые должны быть доступны для других модулей, использующих его. Экспортируемые пакеты объявляются в дескрипторе. Простое объявление:
module com.blog.mymodule { exports com.blog.mymodule; }
В этом примере экспортируется пакет с именем com.blog.mymodule.
Чтобы экспортировать подпакет также, вы должны объявить его явно в дескрипторе, например так:
module com.blog.mymodule { exports com.blog.mymodule; exports com.blog.mymodule.util; }
Вам не нужно экспортировать родительский пакет, чтобы экспортировать подпакет. Следующий оператор экспорта дескриптора совершенно корректен:
module com.blog.mymodule { exports com.blog.mymodule.util; }
В этом примере экспортируется только пакет com.blog.mymodule.util, а не пакет com.blog.mymodule.
Требуется другой модуль
Если для работы модуля требуется другой, он также должен быть указан в дескрипторе:
module com.blog.mymodule { requires javafx.graphics; }
В этом примере дескриптор объявляет, что ему требуется стандартный модуль с именем javafx.graphics.
Круговые зависимости не допускаются
Не допускается наличие циклических зависимостей между модулями. Другими словами, если один из них (A) требует другой (B), то B не может также требовать A. Граф зависимостей модуля должен быть ациклическим графом.
Static
- Модификатор Static используется для создания чего-то в единственном экземпляре. Например, когда мы хотим создать переменную или объект, доступные для всех объектов класса.
- Static необходим для передачи информации по всем объектам.
- Static подходит для переменных, методов и блоков.
- или переменные принадлежат классу, а не объекту.
- Статичный метод или переменная инициализируются один раз перед переменной экземпляра.
- Статичный метод или переменная могут вызываться напрямую из имени класса. Пример: <className>.<variableName>
- Статичный метод имеет доступ только к статичным данным.
- Статичный метод не может ссылаться на this или super.
- Статичный метод может вызывать только другие статичные методы.
- main () — это статичный метод. Он должен быть доступен приложению до создания экземпляров.
- Конструктор не бывает статичным, потому как компилятор считает его методом. Кроме того, конструктор нужен для инициализации нового объекта, а static выполняет совершенно противоположную функцию.
- Статичная переменная загружается первой. После нее идет статичный блок. И очередность здесь важна. Статичные методы загружаются в конце.
· Иерархия следующая:
Метка
Класс java.awt.Label предоставляет текстовую строку с описанием, видимую в графическом интерфейсе. Объект метки AWT — это компонент для размещения текста в контейнере. Класс Label имеет три конструктора:
// Construct a Label with the given text String, of the text alignment public Label(String strLabel, int alignment); //Construct a Label with the given text String public Label(String strLabel); //Construct an initially empty Label public Label();
Этот класс также предоставляет 3 константы:
public static final LEFT; // Label.LEFT public static final RIGHT; // Label.RIGHT public static final CENTER; // Label.CENTER
Ниже я перечислил открытые методы, предоставляемые этим классом:
public String getText(); public void setText(String strLabel); public int getAlignment(); //Label.LEFT, Label.RIGHT, Label.CENTER public void setAlignment(int alignment);
Текстовое поле
Класс java.awt.TextField создает однострочное текстовое поле для ввода текста пользователями. Класс TextField имеет три конструктора:
//Construct a TextField instance with the given initial text string with the number of columns. public TextField(String initialText, int columns); //Construct a TextField instance with the given initial text string. public TextField(String initialText); //Construct a TextField instance with the number of columns. public TextField(int columns);
Вот несколько методов, предоставляемых классом TextField:
// Get the current text on this TextField instance public String getText(); // Set the display text on this TextField instance public void setText(String strText); //Set this TextField to editable (read/write) or non-editable (read-only) public void setEditable(boolean editable);
Causes of Error Code 0xc0000001
If you have received this error on your PC, it means that there was a malfunction in your system operation. Common reasons include incorrect or failed installation or uninstallation of software that may have left invalid entries in your Windows registry, consequences of a virus or malware attack, improper system shutdown due to a power failure or another factor, someone with little technical knowledge accidentally deleting a necessary system file or registry entry, as well as a number of other causes. The immediate cause of the “Error Code: 0xc0000001” error is a failure to correctly run one of its normal operations by a system or application component.
Операции с числами
Последнее обновление: 05.02.2018
Арифметические операции
Kotlin поддерживает базовые арифметические операции:
-
+ (сложение): возвращает сумму двух чисел.
val x = 5 val y = 6 val z = x + y println(z) // z = 11
-
— (вычитание): возвращает разность двух чисел.
val x = 5 val y = 6 val z = x - y // z = -1
-
* (умножение): возвращает произведение двух чисел.
val x = 5 val y = 6 val z = x * y // z = 30
-
(деление): возвращает частное двух чисел.
val x = 60 val y = 10 val z = x / y // z = 6
-
%: возвращает остаток от целочисленного деления двух чисел.
val x = 65 val y = 10 val z = x % y // z = 5
-
++ (инкремент): увеличивает значение на единицу.
Префиксный инкремент возвращает увеличенное значение:
var x = 5 val y = ++x println(x) // x = 6 println(y) // y = 6
Постфиксный инкремент возвращает значение до увеличения на единицу:
var x = 5 val y = x++ println(x) // x = 6 println(y) // y = 5
-
— (декремент): уменьшает значение на единицу.
Префиксный декремент возвращает уменьшенное значение:
var x = 5 val y = --x println(x) // x = 4 println(y) // y = 4
Постфиксный декремент возвращает значение до уменьшения на единицу:
var x = 5 val y = x-- println(x) // x = 4 println(y) // y = 5
Также есть ряд операций присвоения, которые сочетают арифметические операции и присвоение:
-
+=: присваивание после сложения. Присваивает левому операнду сумму левого и правого операндов: A += B эквивалентно
A = A + B -
-=: присваивание после вычитания. Присваивает левому операнду разность левого и правого операндов:
A -= B эквивалентно A = A — B -
*=: присваивание после умножения. Присваивает левому операнду произведение левого и правого операндов:
A *= B эквивалентно A = A * B -
/=: присваивание после деления. Присваивает левому операнду частное левого и правого операндов:
A /= B эквивалентно A = A / B -
%=: присваивание после деления по модулю. Присваивает левому операнду остаток от целочисленного деления левого операнда на правый:
A %= B эквивалентно A = A % B
Побитовые операторы
Ряд операций выполняется над двоичными разрядми числа
Здесь важно понимать, как выглядит двоичное представление тех или иных чисел. В частности, число 4 в двоичном виде — 100, а число 15 — 1111
Есть следующие побитовые операторы (они применяются только к данным типов Int и Long):
-
shl: сдвиг битов числа со знаком влево
val z = 3 shl 2 // z = 11 << 2 = 1100 println(z) // z = 12 val d = 0b11 shl 2 println(d) // d = 12
В данном случае число сдвигается на два разряда влево, поэтому справа число в двоичном виде дополняется двумя нулями. То есть в двоичном виде 3 представляет 11. Сдвигаем
на два разряда влево (дополняем справа двумя нулями) и получаем 1100, то есть в десятичной системе число 12. -
shr: сдвиг битов числа со знаком вправо
val z = 12 shr 2 // z = 1100 >> 2 = 11 println(z) // z = 3 val d = 0b1100 shr 2 println(d) // d = 3
Число 12 сдвигается на два разряда вправо, то есть два числа справа факически отбрасываем и получаем число 11, то есть 3 в десятичой системе.
-
ushr: сдвиг битов беззнакового числа вправо
val z = 12 ushr 2 // z = 1100 >> 2 = 11 println(z) // z = 3
-
and: побитовая операция AND (логическое умножение или конъюнкция). Эта операция сравнивает соответствующие разряды двух чисел и возвращает единицу, если эти разряды обоих чисел равны 1.
Иначе возвращает 0.val x = 5 // 101 val y = 6 // 110 val z = x and y // z = 101 & 110 = 100 println(z) // z = 4 val d = 0b101 and 0b110 println(d) // d = 4
-
or: побитовая операция OR (логическое сложение или дизъюнкция). Эта операция сравнивают два соответствуюших разряда обоих чисел и
возвращает 1, если хотя бы один разряд равен 1. Если оба разряда равны 0, то возвращается 0.val x = 5 // 101 val y = 6 // 110 val z = x or y // z = 101 | 110 = 111 println(z) // z = 7 val d = 0b101 or 0b110 println(d) // d = 7
-
xor: побитовая операция XOR. Сравнивает два разряда и возвращает 1, если один из разрядов равен 1, а другой равен 0.
Если оба разряда равны, то возвращается 0.val x = 5 // 101 val y = 6 // 110 val z = x xor y // z = 101 ^ 110 = 011 println(z) // z = 3 val d = 0b101 xor 0b110 println(d) // d = 3
-
inv: логическое отрицание или инверсия — инвертирует биты числа
val b = 11 // 1011 val c = b.inv() println(c) // -12
НазадВперед
Кнопка
Класс java.awt.Button используется для создания помеченной кнопки. Компонент графического интерфейса, который запускает определенный запрограммированный при нажатии на него. Класс Button имеет два конструктора:
//Construct a Button with the given label public Button(String btnLabel); //Construct a Button with empty label public Button();
Несколько методов, предоставляемых этим классом, перечислены ниже:
//Get the label of this Button instance public String getLabel(); //Set the label of this Button instancenbsp;nbsp;nbsp; public void setLabel(String btnLabel); //Enable or disable this Button. Disabled Button cannot be clicked public void setEnable(boolean enable);
3 Остаток от деления целых чисел
Кроме сложения, вычитания, умножения и деления для целых чисел в Java есть еще и оператор «остаток от деления». Используется для этого символ процент – . Это именно остаток от деления целого числа на целое, а не дробная часть.
Примеры:
Команда | Результат деления | Примечание |
---|---|---|
и в остатке | В переменной будет значение | |
и в остатке | В переменной будет значение | |
и в остатке | В переменной будет значение | |
и в остатке | В переменной будет значение |
Это очень полезный оператор, и используется он довольно часто. Например, чтобы узнать, четное число или нет, достаточно поделить его на и полученный остаток сравнить с нулем. Если остаток от деления равен нулю, число четное, если равен единице — нечетное.
Выглядит эта проверка так:
Где, как вы уже догадались, – получение остатка от деления на (т.е. или ), а используется для сравнения с нулем.
Стиль оформления кода
Существует негласные правила оформления стиля при написании кода. Старайтесь их придерживаться. Также запоминайте оформление кода в документации и справочниках. Например, принято записывать имена классов с большой буквы (class JavaQuickCourseActivity). Если имя состоит из нескольких слов, то каждое слово в имени также начинается с большой буквы. Использовать символы подчеркивания или тире нежелательно (Java_Quick_Course_Activity или Java-Quick-Course-Activity).
Для методов и переменных используется такой же формат, только первый символ записывается с маленькой буквы, например, resultButton.
Константы принято писать только большими буквами — IDD_LIST_NAMES. В этом случае одного взгляда достаточно, чтобы сразу определить, что перед вами константа.
На первых порах вам этого достаточно.
2.3 Арифметические операторы
По приоритетности за унарными операторами следуют арифметические операторы. Эта группа включает в себя четыре наиболее распространённых оператора: сложение, вычитание, умножение, деление. И не только их. Существует также оператор деления по модулю, который обозначается знаком %. Арифметические операторы разделены на две группы. В первой, более приоритетной, группе находятся *, /, %. Во второй, соответственно, + и -.
Умножение и деление (* и /)
Операторы * и / выполняют умножение и деление над всеми примитивными числовыми типами и char.При делении на ноль возникает ArithmeticException.
Вы, наверное, недоумеваете, зачем я вам рассказываю про умножение и деление известное вам с первого класса. Однако, в программировании мы имеем дело с некоторыми ограничениями, связанными с представлением чисел в компьютере. Эти ограничения накладываются на все числовые форматы, от byte до double. Но наиболее заметны они для целочисленного типа int.
Если вы умножаете или делите два числа, результат вычисляется посредством целочисленной арифметики и сохраняется либо в int, либо в long. Если числа очень большие, то результат будет больше максимального числа, которое можно представить в этих числах. А значит, результат не сможет правильно закодироваться компьютером и не будет иметь смысла. Например, тип byte используется для представления чисел в диапазоне от -128 до 127. Если мы умножим 64 и 4, то результат 256, имеющий в двоичной записи 100000000 девять символов, будет закодирован, как 0, потому что byte использует лишь 8 символов.
Рассмотрим деление. Если вы делите в целочисленной арифметике, результат должен быть обязательно целочисленным. И значит, дробная часть будет потеряна. Например, 7/4 даёт нам 1.75, но в целочисленной арифметике это будет 1.
Таким образом, если вы имеете дело со сложными выражениями, вы можете выбирать последовательность умножений и делений. Но имейте в виду, что умножение может привести к переполнению, а деление — к потере точности. Народная мудрость считает, что выполнение сначала умножений, а потом делений в большинстве случаев выдаёт правильный результат. Рассмотрим пример:
1. int a = 12345, b = 234567, c, d;2. long e, f;3.4. c = a * b / b; // должно равняться а=123455. d = a / b * b; // тоже должно равняться а=123456. System.out.println(“a is “ + a +7. “\nb is “ + b +8. “\nc is “ + c +9. “\nd is “ + d);10.11. e = (long)a * b / b;12. f = (long)a / b * b;13. System.out.println(14. “\ne is “ + e +15. “\nf is “ + f);
Результат работы данного фрагмента выдаст следующее:
a is 12345b is 234567c is -5965d is 0e is 12345f is 0
Пусть вас не смущают числовые значения данного примера
Важно то, что при выполнении умножения первым мы получили переполнение (c is -5965), когда закодировали его в тип int. Однако мы можем получить правильный результат, если закондируем его в более длинный тип, как, например, long
В обоих случаях применение первым деления будет катастрофическим для результата, независимо от длины его типа.
Деление по модулю %
Результат деления по модулю — остаток от деления. Например, 7/4 равно 1 с остатком 3. Поэтому 7%4 = 3. Обычно операнды имеют целочисленный тип, но иногда оператор применяется и к числам с плавающей точкой. Также следует знать некоторые особенности данного оператора, когда операнды отрицательные.
При негативных или дробных операндах правило такое: вычитайте правый операнд из левого до тех пор, пока последний не станет меньше первого. Примеры:
17%5 = ? 17-5=12>5; 12-5=7>5; 7-5=2<5. Значит 17%5 = 2
21%7? 21-7=14>7; 14-7=7=7; 7-7=0<7. Значит 21%7 = 0
7.6%2.9? 7.6-2.9=4.7>2.9; 4.7-2.9=1.8<2.9. Значит 7.6%2.9=1.8
Заметьте: знак результата (положительный или отрицательный) целиком и полностью определён знаком левого операнда, то есть делимого.
Когда деление по модулю производится над дробными числами, то суть этой операции состоит в том, чтобы вычесть делитель несколько раз. Результат может быть также дробным числом.
Простое правило для отрицательных операндов такое: отбросьте знак минуса от операндов, произведите деление по модулю с положительными операндами, а затем поставьте перед результатом минус, если левый операнд (делимое) был отрицательным.
Деление по модулю, как и нормальное деление, может выбросить исключение ArithmeticException, если делитель (правый операнд) ровняется нулю.
Практическое применение побитовых операций
Побитовые операции имеют довольно широкое практическое применение, рассмотрим некоторые случаи:
4.3. Шифрование числа
Операция XOR при применении два раза к одному и тому же битовому массиву восстанавливает ее исходное значение. Это можно использовать при шифровании данных при передаче по сети:
C = A ^ B
A = C ^ B
Представьте, что необходимо отправить в сообщении число 560 — пин-код от банковской карты. Если злоумышленник перехватит сообщение, то узнает пин-код и сможет воспользоваться им. Только отправитель и получатель могут знать пин-код. Чтобы этого не произошло, придумаем какое-то число — маску и сообщим его получателю заранее. Перед отправкой пин-кода, зашифруем его — применим побитовую операцию XOR: . И результат отправим. Если злоумышленник и перехватит сообщение, он не будет знать как его расшифровать. Адресат получает сообщение, расшифровывает пин-код с помощью имеющейся маски: .
Следующий код иллюстрирует этот пример:
4.4. Наложение маски
Маска позволяет получать значения только определенных битов в последовательности. Например, у нас есть маска 00100100. Она позволяет нам получать из последовательности только те биты, которые в ней установлены. В данном случае это 3-й и 7-й разряд. Для этого достаточно выполнить побитовое AND с нашей маской и выбранным числом:
Нам доверяют
Безымянный
Начиная с Java 9 и далее все классы должны быть расположены в модуле, чтобы виртуальная машина могла их использовать. Но что вы делаете со старыми библиотеками, где у вас есть только скомпилированные классы или файл JAR?
Безымянный экспортирует все свои пакеты. Однако классы доступны для чтения только другим классам в нем. Ни один из названных модулей не может читать классы безымянного.
Если пакет экспортируется указанным модулем, но также обнаруживается в неназванном, будет использоваться пакет из названного.
Для всех классов в неназванном требуются все модули, найденные в его пути. Таким образом, все классы в безымянном могут читать все классы, экспортируемые всеми модулями, найденными в его пути.
3 String Pool
Все строки, которые были заданы в коде в , во время работы программы хранятся в памяти в так называемом . — это специальный массив для хранения строк. Цель его создания — оптимизация хранения строк:
Во-первых, строки, заданные в коде, нужно все-таки где-то хранить. Код — это команды, а данные (тем более такие большие как строки) нужно хранить в памяти отдельно от кода. В коде фигурируют только ссылки на объекты-строки.
Во-вторых, все одинаковые литералы можно хранить в памяти только один раз. Так оно и работает. Когда код вашего класса загружается Java-машиной, все строковые литералы добавляются в , если их там еще нет. Если уже есть, просто используется ссылка на строку из .
Поэтому если в своем коде вы присвоите нескольким -переменным одинаковые литералы, переменные будут содержать одинаковые ссылки. В литерал будет добавлен только один раз, во всех остальных случаях будет браться ссылка на уже загруженную в строку.
Как это примерно работает:
Код | Работа с StringPoll |
---|---|
Именно поэтому переменные и будут хранить одинаковые ссылки.
Метод
Ну и самое интересное: вы можете программно добавить любую строку в . Для этого нужно просто вызвать метод у -переменной.
Метод добавит строку в , если ее еще там нет, и вернет ссылку на строку из .
Код | Примечание |
---|---|
Вряд ли вы будете часто пользоваться этим методом, однако о нем любят спрашивать на собеседованиях, поэтому лучше о нем знать, чем не знать.
Запрещенные темы для публикаций
Загрузка статического и динамического класса
- Добавление класса для запуска в JVM называется загрузкой класса.
- Классы загружаются статично с помощью нового оператора.
- Первый класс загружается через метод static main(). Затем подгружаются остальные классы.
- В серверных проектах отсутствует main(), поскольку сервер сам отвечает за всю инфраструктуру. Первый класс для загрузки отмечается в config файле. Довольно часто фреймворк реализует метод main() и предоставляет API. Пример: Контейнерный класс вызывает метод init() в сервлетах.
- main нужен для запуска Java-программы из командной строки в JVM.
- Если при загрузке статического класса не находится ссылка на класс, то выбрасывается NoClassDefinationFoundException.
- Динамические классы загружаются через программный вызов при выполнении. Пример: Class.forName(String ClassName);
- ClassNotFoundException выбрасывается при загрузке динамического класса.
3 Создание подстрок
Кроме сравнения строк и поиска подстрок, есть еще одно очень популярное действие — получение подстроки из строки. В предыдущем примере вы как раз видели вызов метода , который возвращал часть строки.
Вот список из 8 методов получения подстрок из текущей строки:
Методы | Описание |
---|---|
Возвращает подстроку, заданную интервалом символов . | |
Повторяет текущую строку n раз | |
Возвращает новую строку: заменяет символ на символ | |
Заменяет в текущей строке подстроку, заданную регулярным выражением. | |
Заменяет в текущей строке все подстроки, совпадающие с регулярным выражением. | |
Преобразует строку к нижнему регистру | |
Преобразует строку к верхнему регистру | |
Удаляет все пробелы в начале и конце строки |
Вот краткое описание существующих методов:
Метод
Метод возвращает новую строку, которая состоит из символов текущей строки, начиная с символа под номером и заканчивая . Как и во всех интервалах в Java, символ с номером в интервал не входит. Примеры:
Код | Результат |
---|---|
Если параметр не указывается (а так можно), подстрока берется от символа beginIndex и до конца строки.
Метод
Метод repeat просто повторяет текущую строку раз. Пример:
Код | Результат |
---|---|
Метод
Метод возвращает новую строку, в которой все символы заменены на символ . Длина строки при этом не меняется. Пример:
Код | Результат |
---|---|
Методы и
Метод заменяет все вхождения одной подстроки на другую. Метод заменяет первое вхождение переданной подстроки на заданную подстроку. Строка, которую заменяют, задается регулярным выражением. Разбирать регулярные выражения мы будем в квесте Java Multithreading.
Примеры:
Код | Результат |
---|---|
Методы
С этими методами мы познакомились, когда только в первый раз учились вызывать методы класса .
Метод
Метод удаляет у строки пробелы с начала и с конца строки. Пробелы внутри строки никто не трогает. Примеры:
Код | Результат |
---|---|