Java | Фишки и трюки
7.21K subscribers
182 photos
29 videos
6 files
40 links
Java: примеры кода, интересные фишки и полезные трюки

Купить рекламу: https://telega.in/c/java_tips_and_tricks

✍️По всем вопросам: @Pascal4eg
Download Telegram
⌨️ В чем отличие между поверхностным и глубоким клонированием?

Поверхностное копирование копирует настолько малую часть информации об объекте, насколько это возможно. По умолчанию, клонирование в Java является поверхностным, т.е. класс Object не знает о структуре класса, которого он копирует. Клонирование такого типа осуществляется JVM по следующим правилам:

✔️ Если класс имеет только члены примитивных типов, то будет создана совершенно новая копия объекта и возвращена ссылка на этот объект.

✔️ Если класс помимо членов примитивных типов содержит члены ссылочных типов, то тогда копируются ссылки на объекты этих классов. Следовательно, оба объекта будут иметь одинаковые ссылки.

Глубокое копирование дублирует абсолютно всю информацию объекта:

✔️ Нет необходимости копировать отдельно примитивные данные;

✔️ Все члены ссылочного типа в оригинальном классе должны поддерживать клонирование. Для каждого такого члена при переопределении метода clone() должен вызываться super.clone();

✔️ Если какой-либо член класса не поддерживает клонирование, то в методе клонирования необходимо создать новый экземпляр этого класса и скопировать каждый его член со всеми атрибутами в новый объект класса, по одному.

#java #clone
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥1
⌨️ Byte Buddy — это мощная библиотека для Java, предназначенная для создания, модификации и управления байт-кодом на лету, без необходимости использования низкоуровневых инструментов вроде ASM. Основное применение Byte Buddy — это динамическое создание и изменение классов в рантайме, что может быть полезно для написания агентов Java, создания прокси-объектов, внедрения кода в существующие классы и тестирования.

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

Byte Buddy поддерживает широкий диапазон версий Java и интегрируется с такими библиотеками, как Spring и Hibernate.

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.implementation.FixedValue;

import static net.bytebuddy.matcher.ElementMatchers.named;

public class ByteBuddyExample {
public static void main(String[] args) throws Exception {
// Создаем новый класс динамически
Class<?> dynamicType = new ByteBuddy()
.subclass(Object.class) // Класс наследуется от Object
.name("com.example.HelloWorld") // Указываем имя нового класса
.method(named("toString")) // Переопределяем метод toString
.intercept(FixedValue.value("Hello from Byte Buddy!")) // Метод будет возвращать фиксированное значение
.make()
.load(ByteBuddyExample.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();

// Создаем экземпляр нового класса
Object instance = dynamicType.getDeclaredConstructor().newInstance();

// Вызываем переопределенный метод toString
System.out.println(instance.toString()); // Вывод: Hello from Byte Buddy!
}
}

#java #ByteBuddy
Please open Telegram to view this post
VIEW IN TELEGRAM
18🐳9🔥2
public class Quest {
public static void main(String[] args) {
String s = null;
if (s != null & s.length() > 0) {
System.out.println("YES!");
} else {
System.out.println("NO!");
}
}
}

#java #quest
👍5🔥2
Что выведет код?
Anonymous Quiz
8%
YES!
39%
NO!
53%
Ошибка NullPointerException
🎉4
⌨️ Дженерики (generics) — это механизм, который позволяет создавать классы, интерфейсы и методы, работающие с различными типами данных, при этом сохраняя строгую типизацию. Они были введены в Java начиная с версии 5 для повышения безопасности типов и повторного использования кода.

Дженерики позволяют определить параметр типа, который будет заменен конкретным типом данных при создании экземпляра класса или вызове метода. Например, List<T> может использоваться как List<String>, List<Integer> и т.д.

Благодаря дженерикам, ошибки типа (например, попытка вставить объект неправильного типа) обнаруживаются на этапе компиляции, а не во время выполнения программы.

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

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


public class Box<T> {
private T item;

public void setItem(T item) {
this.item = item;
}

public T getItem() {
return item;
}
}

Box<String> stringBox = new Box<>();
stringBox.setItem("Hello");
String str = stringBox.getItem();

В этом примере класс Box<T> является обобщенным и может работать с любым типом данных, который заменит T при создании объекта.

#java #generics #T
Please open Telegram to view this post
VIEW IN TELEGRAM
6👍16🔥3❤‍🔥21
⌨️ Потокобезопасность (Thread-Safe) — это свойство объекта или кода, которое гарантирует корректное поведение при одновременном доступе нескольких потоков. Например, потокобезопасный счетчик будет правильно учитывать каждое увеличение, даже если его используют одновременно несколько потоков. Это означает, что результаты работы будут предсказуемыми и соответствующими ожиданиям, независимо от того, сколько потоков обращаются к объекту или выполняют код одновременно.

#java #ThreadSafe
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤‍🔥1
public class Quest {
public static void main(String[] args) {
int x = 5;
int y = 10;
int result = add(x, y) * multiply(x, y);
System.out.println(result);
}

public static int add(int a, int b) {
try {
return a + b;
} finally {
return a - b;
}
}

public static int multiply(int a, int b) {
try {
return a * b;
} finally {
return a / b;
}
}
}


#java #quest
👍3
Что выведет код?
Anonymous Quiz
29%
750
27%
0
44%
ошибка компиляции
❤‍🔥5
⌨️ Кооперативная и вытесняющая многозадачность. Какой тип многозадачности использует Java? Чем обусловлен этот выбор?

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

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

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

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

В отличие от кооперативной многозадачности управление операционной системе передаётся вне зависимости от состояния работающих приложений, благодаря чему, отдельные зависшие потоки процесса, как правило, не «подвешивают» всю систему целиком. За счёт регулярного переключения между задачами также улучшается отзывчивость приложения и повышается оперативность освобождения ресурсов, которые больше не используются.

В реализации вытесняющая многозадачность отличается от кооперативной, в частности, тем, что требует обработки системного прерывания от аппаратного таймера.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍76❤‍🔥1
⌨️ Чем отличается процесс от потока?

Процесс — экземпляр программы во время выполнения, независимый объект, которому выделены системные ресурсы (например, процессорное время и память). Каждый процесс выполняется в отдельном адресном пространстве: один процесс не может получить доступ к переменным и структурам данных другого. Если процесс хочет получить доступ к чужим ресурсам, необходимо использовать межпроцессное взаимодействие. Это могут быть конвейеры, файлы, каналы связи между компьютерами и многое другое.

Для каждого процесса ОС создает так называемое «виртуальное адресное пространство», к которому процесс имеет прямой доступ. Это пространство принадлежит процессу, содержит только его данные и находится в полном его распоряжении. Операционная система же отвечает за то, как виртуальное пространство процесса проецируется на физическую память.

Поток(thread) — определенный способ выполнения процесса, определяющий последовательность исполнения кода в процессе. Потоки всегда создаются в контексте какого-либо процесса, и вся их жизнь проходит только в его границах. Потоки могут исполнять один и тот же код и манипулировать одними и теми же данными, а также совместно использовать описатели объектов ядра, поскольку таблица описателей создается не в отдельных потоках, а в процессах. Так как потоки расходуют существенно меньше ресурсов, чем процессы, в процессе выполнения работы выгоднее создавать дополнительные потоки и избегать создания новых процессов.

#java #process #thread
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18🔥1
public class Quest {
public static void main(String[] args) {
int i = 1;
inc(i);
System.out.println(i);
}
private static void inc(int num) {
num++;
}
}

#java #quest
3
Что выведет код?
Anonymous Quiz
59%
1
29%
2
12%
ошибка компиляции
🔥3🎉2
⌨️ Виртуальные потоки (Virtual Threads) — это новая возможность, представленная в Java, начиная с версии 19 (в предварительном режиме), а окончательно внедрённая в версии 21. Они позволяют создавать и управлять миллионами потоков с минимальными затратами на системные ресурсы. Виртуальные потоки облегчают работу с конкурентными задачами и устраняют необходимость в сложных библиотеках и фреймворках для управления потоками.

Виртуальные потоки гораздо легче системных (они не привязаны к операционной системе), что позволяет их создавать в большом количестве.

Так же, виртуальные потоки совместимы с существующим экосистемой Java, включая традиционные блокирующие операции, такие как I/O.


public class VirtualThreadsExample {
public static void main(String[] args) throws InterruptedException {
// Создаем виртуальный поток
Thread virtualThread = Thread.ofVirtual().start(() -> {
try {
// Эмуляция длительной задачи
Thread.sleep(1000);
System.out.println("Hello from virtual thread!");
} catch (InterruptedException e) {
e.printStackTrace();
}
});

// Дожидаемся завершения потока
virtualThread.join();
}
}


#java #VirtualThreads
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16❤‍🔥1
⌨️ Класс Pattern

Pattern - это класс, представляющий собой компилированное представление регулярного выражения. Он позволяет создать объект-шаблон, который можно применить к строке для поиска соответствий определенному шаблону. Для создания объекта Pattern используется статический метод compile(), который принимает на вход строку с регулярным выражением.
Пример создания объекта Pattern:

Pattern pattern = Pattern.compile("\\d");


В примере мы компилируем регулярное выражение, которое соответствует любой цифре в строке. После компиляции мы можем использовать объект Pattern для поиска соответствий в строках. В результате будет выведено количество цифр в строке.

#java #Pattern
Please open Telegram to view this post
VIEW IN TELEGRAM
👍162
⌨️ Создание скриншота

Этот код позволяет сделать снимок экрана и сохранить его в формате .png.

Toolkit.getDefaultToolkit().getScreenSize() — для получения размеров экрана;

Robot — объект, который используется для захвата экрана;

BufferedImage — объект, представляющий собой изображение экрана;

ImageIO.write() — метод для сохранения захваченного изображения в файл с заданным именем и форматом.

#Java #Screenshot
Please open Telegram to view this post
VIEW IN TELEGRAM
👍244
⌨️ Каким образом можно создать поток?

✔️ Создать потомка класса Thread и переопределить его метод run();

✔️ Создать объект класса Thread, передав ему в конструкторе экземпляр класса, реализующего интерфейс Runnable. Этот интерфейс содержит метод run(), который будет выполняться в новом потоке. Поток закончит выполнение, когда завершится его метод run().

✔️ Вызвать метод submit() у экземпляра класса реализующего интерфейс ExecutorService, передав ему в качестве параметра экземпляр класса реализующего интерфейс Runnable или Callable (содержит метод call(), в котором описывается логика выполнения).

#java #Thread #Runnable #Callable
Please open Telegram to view this post
VIEW IN TELEGRAM
8👍2
public class Quest {
public static void main(String[] args) {
int j = 0;
for (int i = 0; i < 10; i++) {
j = j++;
}
System.out.println(j);
}
}

#java #quest
❤‍🔥4
Что выведет код?
Anonymous Quiz
23%
0
33%
9
38%
10
6%
11
🎉81
⌨️ Инициализация это процесс задания начальных значений переменным и объектам перед их использованием. Этот процесс необходим для того, чтобы обеспечить корректное начальное состояние переменных и объектов в программе.

Порядок инициализации

1⃣ Статические переменные: если в классе есть статические переменные, то они будут инициализированы в первую очередь. Переменные будут инициализированы в том порядке в котором идут в коде.

2⃣ Статический блок инициализации: далее сработает блок инициализации статических переменных.

3⃣ Переменные экземпляра

4⃣ Блок инициализации переменных экземпляра

5⃣ Конструктор

Вывод кода:
Static Variables initialized!
Static Initialization Block initialized!
Instance Variables initialized!
Instance Initialization Block initialized!
Constructor initialized!


Инициализация в Java является важным аспектом, который гарантирует, что объекты и переменные находятся в правильном состоянии перед их использованием. Понимание порядка инициализации помогает избегать ошибок и создавать надежные программы на Java.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍135