👍6😱4🥰1🤗1
Реализация стека с помощью интерфейса Deque
Deque (Double-ended queue) представляет собой интерфейс, который расши
Так же, Deque содержит методы для работы со стеком:
Deque (Double-ended queue) представляет собой интерфейс, который расши
ряет функциональность обычной очереди (Queue). Он позволяет добавлять и удалять элементы как в начале, так и в конце очереди. Deque является частью Java Collections Framework и введен в Java 6.Так же, Deque содержит методы для работы со стеком:
// помещает элемент в стек.
void push(E e);
// извлекает элемент из стека.
E pop();
Deque реализуется различными классами, такими как LinkedList и ArrayDeque. Выбор конкретной реализации зависит от требований к производительности и использования памяти.👍9❤3🔥2👏1
Присоединение вызова метода к телу метода называется связыванием. Если связывание проводится компилятором (компоновщиком) перед запуском программы, то оно называется статическим или ранним связыванием (early binding).
В свою очередь, позднее связывание (late binding) это связывание, проводимое непосредственно во время выполнения программы, в зависимости от типа объекта. Позднее связывание также называют динамическим (dynamic) или связыванием на стадии выполнения (runtime binding). В языках, реализующих позднее связывание, должен существовать механизм определения фактического типа объекта во время работы программы, для вызова подходящего метода. Иначе говоря, компилятор не знает тип объекта, но механизм вызова методов определяет его и вызывает соответствующее тело метода. Механизм позднего связывания зависит от конкретного языка, но нетрудно предположить, что для его реализации в объекты должна включаться какая-то дополнительная информация.
Для всех методов Java используется механизм позднего (динамического) связывания, если только метод не был объявлен как
final, static или private (приватные методы являются final по умолчанию).Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥2❤1
JSON Web Token (JWT) — это открытый стандарт (RFC 7519) для создания токенов доступа, основанный на формате JSON. Как правило, используется для передачи данных для аутентификации в клиент-серверных приложениях. Токены создаются сервером, подписываются секретным ключем и передаются клиенту, который в дальнейшем использует данный токен для подтверждения подлинности аккаунта.
JWT состоит из трех частей, разделенных точкой: заголовок (Header), полезная нагрузка (Payload), и подпись (Signature). Каждая часть представлена в кодировке Base64.
Header содержит два элемента - тип токена (typ) и алгоритм хеширования (alg). Тип токена обычно установлен в "JWT", а алгоритм хеширования указывает, как будет создана подпись.
Payload содержит данные о пользователе, например идентификатор, имя и прочие.
Signature создается с использованием алгоритма хеширования и секретного ключа. Подпись обеспечивает проверку целостности токена и подтверждает, что токен был создан доверенной стороной.
В клиент-серверных приложениях используются два вида токена:
Access-токен — это токен, который предоставляет доступ его владельцу к защищённым ресурсам сервера. Обычно он имеет короткий срок жизни и может нести в себе дополнительную информацию, такую как IP-адрес стороны, запрашивающей данный токен.
Refresh-токен — это токен, позволяющий клиентам запрашивать новые access-токены по истечении их времени жизни. Данные токены обычно выдаются на длительный срок.
Как правило, при использовании JSON-токенов в клиент-серверных приложениях реализована следующая схема:
1️⃣ Клиент проходит аутентификацию в приложении (к примеру, с использованием логина и пароля).
2️⃣ В случае успешной аутентификации сервер отправляет клиенту access- и refresh-токены.
3️⃣ При дальнейшем обращении к серверу клиент использует access-токен. Сервер проверяет токен на валидность и предоставляет клиенту доступ к ресурсам.
4️⃣ В случае, если access-токен становится невалидным, клиент отправляет refresh-токен, в ответ на который сервер предоставляет два обновлённых токена.
5️⃣ В случае, если refresh-токен становится невалидным, клиент опять должен пройти процесс аутентификации.
JWT позволяет создавать безопасные механизмы аутентификации и авторизации без необходимости сохранения состояния сессии на сервере. Он также широко используется в распределенных системах и при создании микросервисов для передачи данных о субъекте (пользователе) между различными компонентами системы.
JWT состоит из трех частей, разделенных точкой: заголовок (Header), полезная нагрузка (Payload), и подпись (Signature). Каждая часть представлена в кодировке Base64.
Header содержит два элемента - тип токена (typ) и алгоритм хеширования (alg). Тип токена обычно установлен в "JWT", а алгоритм хеширования указывает, как будет создана подпись.
Payload содержит данные о пользователе, например идентификатор, имя и прочие.
Signature создается с использованием алгоритма хеширования и секретного ключа. Подпись обеспечивает проверку целостности токена и подтверждает, что токен был создан доверенной стороной.
В клиент-серверных приложениях используются два вида токена:
Access-токен — это токен, который предоставляет доступ его владельцу к защищённым ресурсам сервера. Обычно он имеет короткий срок жизни и может нести в себе дополнительную информацию, такую как IP-адрес стороны, запрашивающей данный токен.
Refresh-токен — это токен, позволяющий клиентам запрашивать новые access-токены по истечении их времени жизни. Данные токены обычно выдаются на длительный срок.
Как правило, при использовании JSON-токенов в клиент-серверных приложениях реализована следующая схема:
1️⃣ Клиент проходит аутентификацию в приложении (к примеру, с использованием логина и пароля).
2️⃣ В случае успешной аутентификации сервер отправляет клиенту access- и refresh-токены.
3️⃣ При дальнейшем обращении к серверу клиент использует access-токен. Сервер проверяет токен на валидность и предоставляет клиенту доступ к ресурсам.
4️⃣ В случае, если access-токен становится невалидным, клиент отправляет refresh-токен, в ответ на который сервер предоставляет два обновлённых токена.
5️⃣ В случае, если refresh-токен становится невалидным, клиент опять должен пройти процесс аутентификации.
JWT позволяет создавать безопасные механизмы аутентификации и авторизации без необходимости сохранения состояния сессии на сервере. Он также широко используется в распределенных системах и при создании микросервисов для передачи данных о субъекте (пользователе) между различными компонентами системы.
👍16❤1🔥1🏆1👨💻1
Проще говоря, это способ взаимодействия какого-то программного кода с набором каких-то программных компонентов, с помощью которых одна компьютерная программа (например, бот или сайт) может использовать другую программу.
Если программу (модуль, библиотеку) рассматривать как чёрный ящик, то API — это набор «ручек», которые доступны пользователю данного ящика и которые он может вертеть и переключать.
Примеры API: Windows API, DirectX (DirectDraw/Direct3D), Vulkan.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤1🔥1👏1🤝1
Можно и так и так. Если посмотреть
реализацию equals() в Enum, то мы там увидим сравнение через ==
public final boolean equals(Object other) {
return this==other;
}
При сравнении через
==, мы застрахуем себя от NullPointerException.Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🔥3❤1
В Java абстрактный класс и интерфейс представляют два различных механизма для достижения абстракции и обеспечения множественного наследования. Вот основные различия между ними:
1️⃣ Абстрактный класс (Abstract Class):
👉 Может содержать как абстрактные методы (методы без тела), так и обычные методы с реализацией.
👉 Может иметь переменные экземпляра (поля).
👉 Может содержать конструкторы.
👉 Поддерживает одиночное наследование: подкласс можно наследовать только от одного абстрактного класса.
abstract class Animal {
String name;
abstract void makeSound();
void eat() {
System.out.println(name + " is eating.");
}
}
2️⃣ Интерфейс (Interface):
👉 Содержит только абстрактные методы (в Java 8 и выше может содержать методы с реализацией, помеченные ключевым сло
вом default).👉 Не может иметь переменных экземпляра, кроме переменных, объявленных
как static final.👉 Не содержит конструкторов.
👉 Поддерживает множественное наследование: класс может реализовывать несколько интерфейсов.
interface Animal {
void makeSound();
void eat();
}
Когда использовать:
👉 Используйте абстрактные классы, когда у вас есть общая реализация для нескольких классов и вы хотите предоставить базовый функционал.
👉 Используйте интерфейсы, когда вам нужна поддержка множественного наследования, или когда классы, возможно, уже наследуют от других классов.
Обычно считается хорошей практикой использовать интерфейсы для определения контракта и абстрактные классы для предоставления базовой реализации. В Java 8 и более новых версиях с появлением интерфейсов с методами по умолчанию (default methods), различия стали менее явными, и выбор может зависеть от конкретной ситуации.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16❤2👎1🔥1🤡1🥴1🏆1👨💻1
Считывание файла из стандартного потока ввода
Перенаправление ввода-вывода — возможность командной оболочки ряда операционных систем перенаправлять стандартные потоки в определённое пользователем место, например, в файл. Характерна для Unix-подобных операционных систем, но в разной степени реализована и в операционных системах других семейств.
Перенаправление обычно осуществляется вставкой специального символа > или < после команды.
Обычно синтаксис выглядит так:
команда1 > файл1 — выполняет команду1, помещая стандартный вывод в файл1;
команда1 < файл1 — выполняет команду1, используя в качестве источника ввода файл1 (вместо клавиатуры).
Для перенаправления содержимого файла в поток ввода нашего приложения воспользуемся командой:
Перенаправление ввода-вывода — возможность командной оболочки ряда операционных систем перенаправлять стандартные потоки в определённое пользователем место, например, в файл. Характерна для Unix-подобных операционных систем, но в разной степени реализована и в операционных системах других семейств.
Перенаправление обычно осуществляется вставкой специального символа > или < после команды.
Обычно синтаксис выглядит так:
команда1 > файл1 — выполняет команду1, помещая стандартный вывод в файл1;
команда1 < файл1 — выполняет команду1, используя в качестве источника ввода файл1 (вместо клавиатуры).
Для перенаправления содержимого файла в поток ввода нашего приложения воспользуемся командой:
java -jar app.jar < file.txt
❤5❤🔥2👍2💘1
import java.lang.annotation.*;
// Создание аннотации
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface MethodInfo {
String author() default "unknown";
String date();
int revision() default 1;
String comments();
}
public class Example {
// Использование аннотации
@MethodInfo(author = "John Doe", date = "2022-08-15", comments = "Example method")
public void performAction() {
// Реализация метода
}
}
В этом примере создается аннотация
MethodInfo с параметрами author, date, revision и comments. Затем аннотация применяется к методу performAction. Таким образом, аннотации могут использоваться для предоставления дополнительной информации о вашем коде, что может быть полезно при разработке, тестировании и поддержке проекта.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍3❤1💯1
Методы и конструкторы в enum
Перечисления (enum) — это классы Java, определяющие наборы констант. Самый простой enum выглядит так:
Но на самом деле, enum в Java обладают гораздо более широким фу
Для наглядности давай
Теперь мы можем выполнить перебор элементов массива с помощью статического метода values():
Мы получим следующий результат:
Каждой константе можно присвоить разное поведение при выполнении определенного метода. Например, можно сделать основной метод абстрактным и переопределить его в каждой константе:
Всё это обеспечивает удобную работу с перечислениями в Java.
Перечисления (enum) — это классы Java, определяющие наборы констант. Самый простой enum выглядит так:
public enum Vehicle { CAR, BUS, BICYCLE, SCOOTER }
Но на самом деле, enum в Java обладают гораздо более широким фу
нкционалом. Они поддерживают поля, методы, интерфейсы и т.д. Они также Comparable и Serializable и могут имплементировать все методы объекта.Для наглядности давай
те создадим enum Animal и присвоим каждому элементу цвет:
public enum Animal {
DOG("black"),
CAT("white"),
RAT("gray");
private final String color;
Animal(String color){
this.color = color;
}
public String getColor(){
return color;
}
}
Теперь мы можем выполнить перебор элементов массива с помощью статического метода values():
public class Main {
public static void main(String[] args) {
for (Animal a : Animal.values()) {
System.out.println(a.name() + " - " + a.getColor());
}
}
}
Мы получим следующий результат:
DOG - black
CAT - white
RAT - gray
Каждой константе можно присвоить разное поведение при выполнении определенного метода. Например, можно сделать основной метод абстрактным и переопределить его в каждой константе:
public enum Operation {
PLUS { double evaluate(double x, double y) { return x + y; } },
MINUS { double evaluate(double x, double y) { return x - y; } },
abstract double evaluate(double x, double y);
}
Всё это обеспечивает удобную работу с перечислениями в Java.
👍27❤2🔥2🥰2👏1
JSON – невероятно удобный и полезный формат для хранения и обмена данными. Java полностью поддерживает его.
Сериализовать данные можно так:
Получится вот такая JSON-строка:
Десериализация на Java выглядит примерно так:
Нужно добавить зависимость:
Сериализовать данные можно так:
JSONObject author = new JSONObject();
author.put("name", "J. K. Rowling");
author.put("numberOfBooks", 22);
JSONArray books = new JSONArray();
books.put("Harry Potter and the Philosopher's Stone");
books.put("Harry Potter and the Chamber of Secrets");
books.put("Harry Potter and the Prisoner of Azkaban");
author.put("books", books);
System.out.print(author);
Получится вот такая JSON-строка:
{"books":["Harry Potter and the Philosopher's Stone","Harry Potter and the Chamber of Secrets","Harry Potter and the Prisoner of Azkaban"],"name":"J. K. Rowling","numberOfBooks":22}
Десериализация на Java выглядит примерно так:
JSONObject author = new JSONObject(serializedString);
System.out.println("name: " + author.get("name"));
System.out.println("numberOfBooks: " + author.get("numberOfBooks"));
JSONArray books = (JSONArray) author.get("books");
Iterator<Object> i = books.iterator();
System.out.println("books:");
while (i.hasNext()) {
System.out.println(i.next());
}
Нужно добавить зависимость:
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20231013</version>
</dependency>
👍16🔥6❤4
Array vs ArrayList
Выбор между Array и ArrayList зависит от специфики задачи на Java, которую требуется решить.
📌Помните о следующих особенностях этих типов:
• Array имеет фиксированный размер и память для него выделяется в момент объявления, а размер ArrayLists может динамически изменяться.
• Массивы Java работают гораздо быстрее, а в ArrayList намного проще добавлять/удалять элементы.
• При работе с Array велика вероятность получить ошибку
• У ArrayList только одно измерение, а вот массивы Java могут быть многомерными.
Выбор между Array и ArrayList зависит от специфики задачи на Java, которую требуется решить.
📌Помните о следующих особенностях этих типов:
• Array имеет фиксированный размер и память для него выделяется в момент объявления, а размер ArrayLists может динамически изменяться.
• Массивы Java работают гораздо быстрее, а в ArrayList намного проще добавлять/удалять элементы.
• При работе с Array велика вероятность получить ошибку
ArrayIndexOutOfBoundsException.
• У ArrayList только одно измерение, а вот массивы Java могут быть многомерными.
import java.util.ArrayList;
public class arrayVsArrayList {
public static void main(String[] args) {
// объявление Array
int[] myArray = new int[6];
// обращение к несуществующему индексу
myArray[7]= 10; // ArrayIndexOutOfBoundsException
// объявление ArrayList
ArrayList<Integer> myArrayList = new ArrayList<>();
// простое добавление и удаление элементов
myArrayList.add(1);
myArrayList.add(2);
myArrayList.add(3);
myArrayList.add(4);
myArrayList.add(5);
myArrayList.remove(0);
// получение элементов ArrayList
for(int i = 0; i < myArrayList.size(); i++) {
System.out.println("Element: " + myArrayList.get(i));
}
// многомерный Array
int[][][] multiArray = new int [3][3][3];
}
}
👍16❤1👎1🔥1🤗1
Код:
import java.util.Iterator;
public class CustomClass implements Iterable<String> {
private String[] elements;
public CustomClass(String[] elements) {
this.elements = elements;
}
@Override
public Iterator<String> iterator() {
return new CustomIterator();
}
private class CustomIterator implements Iterator<String> {
private int index = 0;
@Override
public boolean hasNext() {
return index < elements.length;
}
@Override
public String next() {
if (this.hasNext()) {
return elements[index++];
} else {
throw new NoSuchElementException();
}
}
}
public static void main(String[] args) {
String[] arr = {"one", "two", "three"};
CustomClass customClass = new CustomClass(arr);
for (String element : customClass) {
System.out.println(element);
}
}
}
💁♂️ Этот код позволяет создать итератор для пользовательского класса
CustomClass. Итератор позволяет перебирать элементы массива elements и использовать их в цикле for-each.Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤2🔥1🤝1
// Создание интерфейсов
interface Printable {
void print();
}
interface Showable {
void show();
}
// Реализация интерфейсов в классе
class MyClass implements Printable, Showable {
public void print() {
System.out.println("Printing...");
}
public void show() {
System.out.println("Showing...");
}
}
public class Main {
public static void main(String[] args) {
// Создание объекта класса MyClass
MyClass obj = new MyClass();
obj.print();
obj.show();
}
}
MyClass реализует два интерфейса Printable и Showable, и поэтому класс может использовать методы, определенные в обоих интерфейсах. Это позволяет создавать гибкие и модульные программы, используя механизм интерфейсов в Java.Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥4👨💻2❤1
StringBuilder для эффективной конкатенации строк:public class StringBuilderExample {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; i++) {
sb.append("строка ").append(i).append("\n");
}
String result = sb.toString();
System.out.println(result);
}
}
StringBuilder для объединения 10 строк "строка i" в одну строку. Это более эффективно, чем использование оператора "+" или String.concat(), особенно при большом количестве операций конкатенации строк.StringBuilder предоставляет изменяемую последовательность символов и позволяет выполнять эффективные операции вставки, удаления и конкатенации строк.Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥3❤1
💻 Как полезную фишку на Java можно рассмотреть использование лямбда-выражений для упрощения написания анонимных классов. Например, использование лямбда-выражения для выполнения операции над элементами коллекции:
🔝 Использование лямбда-выражений делает код более компактным и удобочитаемым, особенно при работе с коллекциями и функциональными интерфейсами.
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// Использование лямбда-выражения для вывода каждого элемента в консоль
numbers.forEach(n -> System.out.println(n));
// Использование лямбда-выражения для умножения каждого элемента на 2
numbers.replaceAll(n -> n * 2);
System.out.println(numbers); // Вывод: [2, 4, 6, 8, 10]
}
}
🔝 Использование лямбда-выражений делает код более компактным и удобочитаемым, особенно при работе с коллекциями и функциональными интерфейсами.
👍17🔥4❤2🥰2
ExecutorService - это интерфейс, который предоставляет удобный способ для управления параллельным выполнением задач. Он предоставляет пул потоков для выполнения задач и управляет их жизненным циклом:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
// Создание пула потоков
ExecutorService executor = Executors.newFixedThreadPool(5);
// Подача задач на выполнение
for (int i = 0; i < 10; i++) {
executor.execute(new Task(i));
}
// Остановка пула потоков после выполнения задач
executor.shutdown();
}
static class Task implements Runnable {
private int taskId;
public Task(int taskId) {
this.taskId = taskId;
}
@Override
public void run() {
System.out.println("Выполнение задачи " + taskId + " в потоке " +
Thread.currentThread().getName());
}
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥5❤3👨💻1
ерфейса Callable вместе с классом Future для выполнения асинхронных задач и получения их результата:
ExecutorService executor = null;
try {
executor = Executors.newFixedThreadPool(1);
Future<Integer> futureResult = executor.submit(() -> {
// Выполнение сложной вычислительной задачи
int result = 0;
for (int i = 0; i < 100; i++) {
result += i;
Thread.sleep(100);
}
return result;
});
// Другие действия, выполняемые параллельно
// Ожидание завершения асинхронной задачи и получение результата
Integer result = futureResult.get();
System.out.println("Результат: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} finally {
if (executor != null) executor.shutdown();
}
Callable, который возвращает результат типа Integer. Задача выполняет сложное вычисление с задержкой в 100 миллисекунд каждую итерацию.После создания задачи, она отправляется на выполнение в пул потоков. Далее, можно выполнять другие действия параллельно с ожиданием завершения задачи.
Метод
get() вызывается для ожидания завершения задачи и получения результата. Если задача еще не завершилась, вызов этого метода блокируется. Возможны исключения, такие как InterruptedException или ExecutionException, которые необходимо обработать.💁♂️ Затем поток пул завершается вызовом
shutdown().Please open Telegram to view this post
VIEW IN TELEGRAM
👍10👨💻3❤2🔥1💯1