10986
📚 Лайфхаки, приёмы и лучшие практики для Java-разработчиков. Всё, что ускорит код и прокачает навыки. Java, Spring, Maven, Hibernate. По всем вопросам @evgenycarter РКН clck.ru/3KoGeP
📌 Паттерн "Одиночка" (Singleton) – когда и как правильно использовать?
👋 Сегодня хочу поговорить о Singleton – одном из самых популярных (и часто злоупотребляемых) паттернов в Java.
🔥 Что такое Singleton?
Singleton гарантирует, что у класса будет только один экземпляр и предоставляет глобальную точку доступа к нему.
Пример классического Singleton:
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
public enum SingletonEnum {
INSTANCE;
public void someMethod() {
System.out.println("Работаем!");
}
}
Блокировки в HotSpot JVM
Java Virtual Machine (JVM) — это промежуточное звено между скомпилированным Java-кодом и операционной системой (ОС). Благодаря этому механизму Java-приложения можно запускать на разных платформах без модификаций. Существует множество реализаций JVM, но наиболее популярной является HotSpot, входящая в состав OpenJDK.
Однако JVM не просто транслирует Java-код в инструкции ОС. Она включает в себя множество оптимизаций, позволяющих исполнять код быстрее и эффективнее. Одна из таких оптимизаций касается механизма блокировок (synchronization locks).
Виды блокировок в HotSpot
Виртуальная машина HotSpot использует три вида блокировок в зависимости от уровня конкуренции между потоками:
1️⃣ Fat Lock (Inflated Lock) — классическая блокировка на основе мониторов объектов (mutexes). Этот метод используется, когда большое количество потоков одновременно пытаются захватить блокировку.
2️⃣ Thin Lock (Deflated Lock) — облегчённая блокировка, использующая атомарные CAS-операции (Compare-And-Swap). Такой подход быстрее мьютексов, но становится неэффективным при высоком уровне конкуренции, поскольку требует эксклюзивного доступа.
3️⃣ Biased Lock — предвзятая блокировка, предназначенная для сценариев, в которых объект используется одним и тем же потоком. При первом взаимодействии объект привязывается к потоку, и последующие операции с ним выполняются без затрат на синхронизацию. Однако, если другой поток попытается захватить блокировку, произойдёт глобальная аннулирование (bulk revocation), что может привести к значительным накладным расходам.
> Важно! Biased Lock по умолчанию отключён при запуске JVM, поскольку на старте приложения активно взаимодействуют множество потоков. Через некоторое время он автоматически включается и становится основной стратегией блокировки.
Тонкая настройка JVM
JVM позволяет управлять стратегией блокировок с помощью следующих параметров:
- Отключение Biased Lock
-XX:-UseBiasedLocking
-XX:BiasedLockingStartupDelay=500
500 указывает задержку в миллисекундах.
📌 Java Record: Почему Это Круто?
Сегодня расскажу вам о record в Java – мощном инструменте, который упростит вашу жизнь при работе с неизменяемыми объектами.
🔹 Что такое record?
Введённый в Java 14, record – это специальный тип класса, предназначенный для хранения данных. Он автоматически генерирует:
✅ Конструктор
✅ Геттеры (но без get в названии)
✅ equals(), hashCode(), toString()
🔹 Пример использования
public record User(String name, int age) {}
equals/hashCode/toString, но занимает всего одну строку! record всегда final record запрещено
🔹 Разбираем Lombok: как избавиться от шаблонного кода
Ты всё ещё пишешь getters и setters вручную? Используй Lombok!
💡 Как подключить?
Добавь в pom.xml:<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.26</version>
<scope>provided</scope>
</dependency>
💡 Как использовать?import lombok.Data;
@Data
public class User {
private String name;
private int age;
}
Теперь getName(), setName() и toString() сгенерируются автоматически!
👉 Lombok. Полное руководство
https://auth0.com/blog/a-complete-guide-to-lombok/
Кто уже использует Lombok в своих проектах?
👉@BookJava
🔥 5 паттернов проектирования, которые должен знать каждый Java-разработчик
В мире Java есть сотни паттернов проектирования, но эти 5 используются чаще всего. Если вы их освоите, ваш код станет чище, гибче и легче в поддержке.
1️⃣ Singleton
Ограничивает создание объекта одним экземпляром. Полезен для логирования, работы с базами данных, кэшей.
🔹 Пример кода (Lazy Initialization, thread-safe):
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
interface Product {
void create();
}
class ConcreteProductA implements Product {
public void create() { System.out.println("Создан продукт A"); }
}
class ProductFactory {
public static Product createProduct(String type) {
if ("A".equals(type)) return new ConcreteProductA();
throw new IllegalArgumentException("Неизвестный тип продукта");
}
}
@Builder делает его проще!):
@Builder
public class Car {
private String model;
private int year;
private String engine;
}
Car car = Car.builder().model("Tesla").year(2024).engine("Electric").build();
interface Observer {
void update(String message);
}
class User implements Observer {
private String name;
public User(String name) { this.name = name; }
public void update(String message) {
System.out.println(name + " получил уведомление: " + message);
}
}
class Channel {
private List<Observer> observers = new ArrayList<>();
public void subscribe(Observer o) { observers.add(o); }
public void notifyAll(String message) {
for (Observer o : observers) { o.update(message); }
}
}
class LoggingOutputStream extends OutputStream {
private OutputStream wrapped;
public LoggingOutputStream(OutputStream wrapped) { this.wrapped = wrapped; }
@Override
public void write(int b) throws IOException {
System.out.println("Записываем байт: " + b);
wrapped.write(b);
}
}
👩💻Ваши приложения готовы к перегрузкам? А если вдруг лавина запросов?
На открытом вебинаре «Resilience4j. Bulkhead» вы узнаете, как защитить свои сервисы от сбоев. Разберём ключевые возможности Bulkhead и покажем, как ограничение ресурсов может спасти приложение.
Хотите углубить навыки бэкенд-разработки, повысить устойчивость своих микросервисов и освоить Resilience4j?
🗓 Всё это уже 12 февраля в 20:00 мск!
Спикер Сергей Петрелевич — опытный разработчик на Java и Kotlin.
➡️ Регистрируйтесь на открытый урок прямо сейчас! Участники получат скидку на большое обучение на курс «Java Developer. Professional»: https://vk.cc/cIfjodРеклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
🔥 Разбираем CompletableFuture: Асинхронность в Java без боли
Привет, коллеги! Сегодня поговорим о CompletableFuture, который помогает писать асинхронный код в Java без коллбэков и потерь в читабельности.
📌 1. Почему CompletableFuture?
В Java давно есть Future, но он неудобен:
❌ Нельзя комбинировать несколько задач.
❌ Блокирует поток при вызове .get().
❌ Нет удобных методов для обработки результатов.
👉 CompletableFuture решает все эти проблемы, позволяя комбинировать задачи, обрабатывать ошибки и не блокировать потоки.
📌 2. Базовый пример использования
import java.util.concurrent.CompletableFuture;
public class AsyncExample {
public static void main(String[] args) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
sleep(2000);
return "Привет, мир!";
});
future.thenAccept(result -> System.out.println("Результат: " + result));
System.out.println("Этот текст выведется раньше результата!");
sleep(3000); // Чтобы программа не завершилась раньше времени
}
private static void sleep(int ms) {
try { Thread.sleep(ms); } catch (InterruptedException ignored) {}
}
}
supplyAsync() выполняет задачу в другом потоке, а thenAccept() позволяет асинхронно обработать результат.
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World");
CompletableFuture<String> result = future1.thenCombine(future2, (s1, s2) -> s1 + " " + s2);
System.out.println(result.join()); // Hello World
thenCombine() объединяет результаты двух асинхронных задач. exceptionally)
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
if (Math.random() > 0.5) {
throw new RuntimeException("Что-то пошло не так!");
}
return "Все хорошо!";
}).exceptionally(ex -> "Ошибка: " + ex.getMessage());
System.out.println(future.join());
supplyAsync() произошла ошибка, она обработается в exceptionally(), и программа не упадёт.
CompletableFuture<Void> allTasks = CompletableFuture.allOf(
CompletableFuture.runAsync(() -> sleepAndPrint("Задача 1", 1000)),
CompletableFuture.runAsync(() -> sleepAndPrint("Задача 2", 2000)),
CompletableFuture.runAsync(() -> sleepAndPrint("Задача 3", 1500))
);
allTasks.join(); // Дождёмся завершения всех задач
private static void sleepAndPrint(String msg, int ms) {
try { Thread.sleep(ms); } catch (InterruptedException ignored) {}
System.out.println(msg);
}
allOf() позволяет запустить несколько задач параллельно и дождаться их завершения. CompletableFuture – это мощный инструмент для работы с асинхронностью в Java. Future и ExecutorService. CompletableFuture в своих проектах? Делитесь в комментариях! 🚀
🚀Разбираем принцип работы ConcurrentHashMap
Сегодня разберёмся, почему ConcurrentHashMap лучше подходит для многопоточной работы, чем HashMap, и как он работает внутри.
В отличие от HashMap, который не потокобезопасен и может приводить к бесконечным циклам при одновременной модификации, ConcurrentHashMap использует сегментированную блокировку, что позволяет работать с разными частями карты параллельно без полной блокировки всей структуры.
📌 Основные особенности:
- Делит данные на сегменты (до JDK 8 или использует synchronized и CAS операции (начиная с JDK 8).
- Чтение (get()) не требует блокировки.
- Запись (put()) использует минимально возможные блокировки.
- Нет null ключей и значений (в отличие от HashMap).
Пример использования:
import java.util.concurrent.ConcurrentHashMap;
public class Main {
public static void main(String[] args) {
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("Java", 1);
map.put("Python", 2);
map.put("C++", 3);
System.out.println(map.get("Java")); // 1
}
}
ConcurrentHashMap? Поделитесь в комментариях! 👇
В чем разница между Checked и Unchecked исключениями во время выполнения?
Да, в Java есть существенные различия между checked (проверяемыми) и unchecked (непроверяемыми) исключениями во время выполнения.
1. Проверка на этапе компиляции
- Checked исключения: Проверяются на этапе компиляции. Компилятор требует, чтобы вы либо обработали исключение (с помощью try-catch), либо объявили его в сигнатуре метода (с помощью throws). Если этого не сделать, код не скомпилируется.
- Unchecked исключения: Не проверяются на этапе компиляции. Компилятор не требует их обработки или объявления. Обычно они возникают из-за логических ошибок в коде (например, NullPointerException, ArrayIndexOutOfBoundsException).
2. Поведение во время выполнения
- Checked исключения: Эти исключения обычно связаны с внешними факторами (например, проблемы с файловым вводом-выводом, сетевыми соединениями) и могут возникать в ходе нормального выполнения программы. Если такое исключение выбрасывается и не обрабатывается, оно будет передаваться вверх по стеку вызовов, пока не будет перехвачено или программа не завершится.
- Unchecked исключения: Эти исключения часто вызваны ошибками в коде (например, деление на ноль, обращение к null). Если такое исключение выбрасывается и не перехватывается, оно также будет передаваться вверх по стеку вызовов, но, поскольку их не требуется объявлять или обрабатывать, это может привести к неожиданному завершению программы.
3. Наследование
- Checked исключения: Все исключения, которые наследуют Exception (но не RuntimeException), являются проверяемыми.
- Unchecked исключения: Все исключения, которые наследуют RuntimeException или Error, являются непроверяемыми.
4. Примеры
- Checked исключения: IOException, SQLException, ClassNotFoundException.
- Unchecked исключения: NullPointerException, ArrayIndexOutOfBoundsException, ArithmeticException.
5. Обработка во время выполнения
- Checked исключения: Поскольку они проверяются на этапе компиляции, вы обязаны явно их обрабатывать. Это делает код более устойчивым, но может увеличить его объем.
- Unchecked исключения: Поскольку они не проверяются на этапе компиляции, их сложнее отлаживать и обрабатывать, так как они могут быть неочевидными в коде.
6. Производительность
- Нет значительной разницы в производительности между checked и unchecked исключениями во время выполнения. Стоимость выбрасывания и перехвата исключений одинакова для обоих типов.
Итог
- Checked исключения: Контролируются компилятором, должны быть обработаны или объявлены, обычно используются для recoverable (восстанавливаемых) ситуаций.
- Unchecked исключения: Не контролируются компилятором, часто возникают из-за ошибок в коде и могут привести к аварийному завершению программы, если не обработаны.
Оба типа исключений ведут себя схожим образом во время выполнения, но ключевое различие заключается в том, как они контролируются и обрабатываются на этапе разработки.
👉@BookJava
🚀 Совет по Java API 🚀
При использовании Integer.valueOf(int) помните, что значения в диапазоне от -128 до 127 кэшируются для повышения производительности. За пределами этого диапазона создаются новые объекты.
Размер кэша можно контролировать с помощью опции -XX:AutoBoxCacheMax=<размер>. 🔥
👉@BookJava
Совет по Java 💡☕️
Чтобы получить все дни месяца, вы можете начать с объекта YearMonth, получить его первый день, а затем использовать функцию datesUntil(), которая возвращает Stream всех дней до указанной даты.
👉@BookJava
⚡️ Хотите управлять приложениями на Java и Kotlin, как дирижер оркестром?
Spring Framework — ключевой инструмент для создания мощных Java-приложений. Вы научитесь проектировать микросервисы, внедрять Spring Boot, разрабатывать безопасные системы с Spring Security и решать задачи уровня Middle+.
🦾 На курсе вас ждут живые лекции, реальные задачи и экспертное ревью кода. Ваш диплом от OTUS – билет в крупные компании!
Присоединяйтесь к курсу и прокачайте Java-навыки на Spring до профессионального уровня.
📌 Регистрация открыта — успейте записаться: https://vk.cc/cHWc3z
🎫 ПРОМОКОД: Spring_01
Начни обучение со скидкой, подробности у менеджеров.Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
Совет по Spring Boot💡
Когда вам нужно настроить bean, предоставляемый Spring Boot, проверьте наличие интерфейсов *Customizer - велика вероятность, что вы сможете настроить bean, не отказываясь от автоконфигурации.
👉@BookJava
Почему обработка отсортированного массива быстрее, чем неотсортированного? 🚀
Вы когда-нибудь задумывались, почему работа с отсортированными данными быстрее? Разберёмся на примере Java (и программирования в целом). 🧑💻
🔮 1. Предсказание ветвлений (Branch Prediction)
Современные процессоры используют технику под названием предсказание ветвлений, чтобы угадать результат условных операторов (например, if). Если предсказание верное, процессор выполняет инструкции быстро. Но если предсказание ошибочное, процессор вынужден откатить выполнение и начать заново, что замедляет работу.
- Отсортированные массивы: В отсортированном массиве данные следуют предсказуемым шаблонам. Например, если вы проверяете условие if (array[i] > threshold), результаты будут более последовательными (например, все true после определённого момента). Это помогает предсказателю ветвлений угадывать правильно, уменьшая простои.
- Неотсортированные массивы: В неотсортированном массиве результаты условных проверок более случайны. Это затрудняет работу предсказателя, увеличивая количество ошибок и замедляя выполнение.
🧠 2. Эффективность кэша
Кэш процессора — это быстрая память, которая хранит недавно использованные данные. Доступ к данным из кэша намного быстрее, чем из основной памяти.
- Отсортированные массивы: При обработке отсортированного массива данные читаются последовательно. Это улучшает эффективность кэша, так как процессор может заранее загружать соседние элементы, уменьшая количество промахов кэша.
- Неотсортированные массивы: В неотсортированном массиве доступ к данным менее предсказуем, что приводит к большему количеству промахов кэша и замедлению работы.
🛠 3. Алгоритмические оптимизации
Некоторые алгоритмы специально разработаны для работы с отсортированными данными. Например:
- Бинарный поиск: Работает только с отсортированными массивами и имеет сложность O(log n), что намного быстрее линейного поиска (**O(n)**) в неотсортированном массиве.
- Слияние массивов: Объединение двух отсортированных массивов происходит эффективнее, чем неотсортированных.
🧪 Пример: Предсказание ветвлений в действии
Рассмотрим пример кода:
int sum = 0;
for (int i = 0; i < array.length; i++) {
if (array[i] >= 128) {
sum += array[i];
}
}
if будет сначала всегда false, а потом всегда true. Это помогает предсказателю работать эффективно.if будет выполняться хаотично, что приведёт к частым ошибкам предсказания и замедлит программу.
🚀 В Java есть 4 уровня доступа: public, protected, package-private и private.
В Java модификаторы доступа управляют видимостью классов, методов и полей.
1. public:
- Видимость: Доступен из любого другого класса.
- Использование: Когда класс, метод или поле объявлены как public, они доступны из любого класса в любом пакете.
- Пример:
public class MyClass {
public int myField;
public void myMethod() {
// Реализация метода
}
}
myField и myMethod доступны из любого другого класса.protected:
public class MyClass {
protected int myField;
protected void myMethod() {
// Реализация метода
}
}
myField и myMethod доступны для любого подкласса MyClass, даже если он находится в другом пакете.package-private (по умолчанию, без модификатора):
class MyClass {
int myField;
void myMethod() {
// Реализация метода
}
}
myField и myMethod доступны только для классов внутри того же пакета.private:
public class MyClass {
private int myField;
private void myMethod() {
// Реализация метода
}
}
myField и myMethod доступны только внутри MyClass.public | Да | Да | Да | Да |protected | Да | Да | Да | Нет |package-private | Да | Да | Нет | Нет |private | Да | Нет | Нет | Нет |public для API и методов/полей, которые должны быть доступны всем.protected для методов/полей, которые должны быть доступны подклассам, но не всем остальным.package-private для внутренней реализации, которая не должна быть доступна вне пакета.private для инкапсуляции, скрывая детали реализации внутри класса.
🚀 Разбираемся с var в Java: Когда использовать, а когда нет?
Сегодня разберёмся с var в Java. Этот локальный тип вывода переменной появился в Java 10 и сразу вызвал много споров. Давайте посмотрим, когда его стоит использовать, а когда лучше отказаться.
✅ Когда var полезен?
1️⃣ Сокращение шаблонного кода
var list = new ArrayList<String>(); // читается проще
var map = new HashMap<String, List<Integer>>();
var thread = new Thread(() -> System.out.println("Hello"));
for (var entry : map.entrySet()) {
System.out.println(entry.getKey() + " -> " + entry.getValue());
}
var ухудшает код?
var data = fetchData(); // Что вернет метод? Интуитивно непонятно!
var something = doSomethingComplicated(); // А что это такое?
var, мы теряем контракт с пользователем API.var, когда тип очевиден и код становится чище. Не злоупотребляйте им, чтобы не терять читаемость!
Совет Spring Framework💡
Вы можете автосопрягать несколько бинов, реализующих определенный интерфейс, в список, содержащий все реализации. Определите список с общим типом, который вы хотите использовать. Вы можете использовать инъекцию конструктора, как показано на картинке, или инъекцию поля.
👉@BookJava
📌 Record vs Class в Java – когда что использовать?
👋 Сегодня разберёмся с record и class в Java. Когда лучше использовать record, а когда стоит остаться на классах?
🧐 Что такое record?
Record — это специальный тип класса, предназначенный для хранения неизменяемых данных. Он автоматически генерирует:
✅ Конструктор, принимающий все поля
✅ toString(), equals(), hashCode()
✅ Методы доступа (`getter'ы`)
📌 Пример использования Record:
public record User(String name, int age) {}
public final class User {
private final String name;
private final int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String name() { return name; }
public int age() { return age; }
@Override
public boolean equals(Object o) { /* реализация */ }
@Override
public int hashCode() { /* реализация */ }
@Override
public String toString() { /* реализация */ }
}
record? record?
🚀 Stream API в Java: 5 мощных трюков, которые ты мог не знать
Stream API – одна из самых крутых фич в Java, но многие используют только map(), filter() и collect(). Давай разберем 5 полезных трюков, которые сделают код элегантнее и эффективнее!
🔹 1. Группировка элементов (Collectors.groupingBy)
Разбиваем список строк на группы по длине:
List<String> words = List.of("apple", "banana", "cat", "dog", "elephant");
Map<Integer, List<String>> grouped = words.stream()
.collect(Collectors.groupingBy(String::length));
System.out.println(grouped);
// {3=[cat, dog], 5=[apple], 6=[banana], 8=[elephant]}
distinct())
List<Integer> numbers = List.of(1, 2, 2, 3, 4, 4, 5);
List<Integer> unique = numbers.stream()
.distinct()
.collect(Collectors.toList());
System.out.println(unique); // [1, 2, 3, 4, 5]
skip(n))
List<String> names = List.of("Alice", "Bob", "Charlie", "David", "Eve");
List<String> skipped = names.stream()
.skip(3)
.collect(Collectors.toList());
System.out.println(skipped); // [David, Eve]
max())
List<Integer> nums = List.of(10, 20, 30, 5, 15);
Optional<Integer> maxNum = nums.stream().max(Integer::compareTo);
maxNum.ifPresent(System.out::println); // 30
anyMatch())
List<Integer> nums = List.of(10, 50, 200, 30);
boolean hasLargeNumber = nums.stream().anyMatch(n -> n > 100);
System.out.println(hasLargeNumber); // true
2️⃣ Что нового в Java 21? ТОП-5 фич, которые стоит знать
Java 21 – это LTS-релиз, который принесёт важные улучшения. Вот самые интересные новинки:
1️⃣ Виртуальные потоки (Virtual Threads) 🧵
- Теперь Thread больше не проблема!
- Создание тысячи потоков стало дешёвым и быстрым:
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
executor.submit(() -> System.out.println("Hello, Virtual Thread!"));
}
switch
static void test(Object obj) {
switch (obj) {
case String s -> System.out.println("Это строка: " + s);
case Integer i when i > 0 -> System.out.println("Положительное число: " + i);
default -> System.out.println("Что-то другое");
}
}
ThreadLocal)
static final ScopedValue<String> USER = ScopedValue.newInstance();
ScopedValue.runWhere(USER, "Admin", () -> System.out.println(USER.get()));
record, теперь можно удобно распаковывать данные:
record Point(int x, int y) {}
static void printPoint(Object obj) {
if (obj instanceof Point(int x, int y)) {
System.out.println("Координаты: " + x + ", " + y);
}
}
String name = "Alice";
String message = STR."Привет, \{name}!";
1️⃣ Чем record лучше class в Java?
В Java 14 появился record – новый тип классов, предназначенный для удобного хранения данных. Чем он лучше обычного class? Давайте разберёмся!
🔹 Запись против класса
Обычный класс:
class Person {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}
record:
record Person(String name, int age) {}
toString(), equals(), hashCode() record? record в своих проектах? Делитесь опытом! 🚀
🚀Как правильно использовать Optional в Java Optional<T> в Java — это мощный инструмент для работы с возможными null значениями, но часто его используют неправильно. Давайте разберём основные ошибки и лучшие практики.
❌ Плохие примеры:
1️⃣ Использование Optional как поля в классе
class User {
Optional<String> name; // ❌ Плохая практика
}
String, а если нужно, то оборачивать значение в Optional при возврате. isPresent() вместо ifPresent()
if (optionalValue.isPresent()) {
process(optionalValue.get()); // ❌ Неоптимально
}
optionalValue.ifPresent(this::process); // ✅ Правильный подход
public Optional<User> findUserById(int id) {
return Optional.ofNullable(userRepository.get(id));
}
Optional помогает избежать NullPointerException и делает код чище. Optional? Пишите в комментариях! 🚀
Подборка Telegram каналов для программистов
Системное администрирование 📌
/channel/sysadmin_girl Девочка Сисадмин
/channel/srv_admin_linux Админские угодья
/channel/linux_srv Типичный Сисадмин
/channel/linux_odmin Linux: Системный администратор
/channel/devops_star DevOps Star (Звезда Девопса)
/channel/i_linux Системный администратор
/channel/linuxchmod Linux
/channel/sys_adminos Системный Администратор
/channel/tipsysdmin Типичный Сисадмин (фото железа, было/стало)
/channel/sysadminof Книги для админов, полезные материалы
/channel/i_odmin Все для системного администратора
/channel/i_odmin_book Библиотека Системного Администратора
/channel/i_odmin_chat Чат системных администраторов
/channel/i_DevOps DevOps: Пишем о Docker, Kubernetes и др.
/channel/sysadminoff Новости Линукс Linux
1C разработка 📌
/channel/odin1C_rus Cтатьи, курсы, советы, шаблоны кода 1С
Программирование C++📌
/channel/cpp_lib Библиотека C/C++ разработчика
/channel/cpp_knigi Книги для программистов C/C++
/channel/cpp_geek Учим C/C++ на примерах
Программирование Python 📌
/channel/pythonofff Python академия. Учи Python быстро и легко🐍
/channel/BookPython Библиотека Python разработчика
/channel/python_real Python подборки на русском и английском
/channel/python_360 Книги по Python Rus
Java разработка 📌
/channel/BookJava Библиотека Java разработчика
/channel/java_360 Книги по Java Rus
/channel/java_geek Учим Java на примерах
GitHub Сообщество 📌
/channel/Githublib Интересное из GitHub
Базы данных (Data Base) 📌
/channel/database_info Все про базы данных
Мобильная разработка: iOS, Android 📌
/channel/developer_mobila Мобильная разработка
/channel/kotlin_lib Подборки полезного материала по Kotlin
Фронтенд разработка 📌
/channel/frontend_1 Подборки для frontend разработчиков
/channel/frontend_sovet Frontend советы, примеры и практика!
/channel/React_lib Подборки по React js и все что с ним связано
Разработка игр 📌
/channel/game_devv Все о разработке игр
Библиотеки 📌
/channel/book_for_dev Книги для программистов Rus
/channel/programmist_of Книги по программированию
/channel/proglb Библиотека программиста
/channel/bfbook Книги для программистов
/channel/books_reserv Книги для программистов
БигДата, машинное обучение 📌
/channel/bigdata_1 Data Science, Big Data, Machine Learning, Deep Learning
Программирование 📌
/channel/bookflow Лекции, видеоуроки, доклады с IT конференций
/channel/coddy_academy Полезные советы по программированию
/channel/rust_lib Полезный контент по программированию на Rust
/channel/golang_lib Библиотека Go (Golang) разработчика
/channel/itmozg Программисты, дизайнеры, новости из мира IT
/channel/php_lib Библиотека PHP программиста 👨🏼💻👩💻
/channel/nodejs_lib Подборки по Node js и все что с ним связано
/channel/ruby_lib Библиотека Ruby программиста
QA, тестирование 📌
/channel/testlab_qa Библиотека тестировщика
Шутки программистов 📌
/channel/itumor Шутки программистов
Защита, взлом, безопасность 📌
/channel/thehaking Канал о кибербезопасности
/channel/xakep_1 Статьи из "Хакера"
Книги, статьи для дизайнеров 📌
/channel/ux_web Статьи, книги для дизайнеров
Английский 📌
/channel/UchuEnglish Английский с нуля
Математика 📌
/channel/Pomatematike Канал по математике
/channel/phis_mat Обучающие видео, книги по Физике и Математике
Excel лайфхак📌
/channel/Excel_lifehack
/channel/tikon_1 Новости высоких технологий, науки и техники💡
/channel/mir_teh Мир технологий (Technology World)
Вакансии 📌
/channel/sysadmin_rabota Системный Администратор
/channel/progjob Вакансии в IT
🦾👩💻🦾 Вы уже опытный Java-разработчик, но хотите освоить глубины JVM и оптимизацию приложений в облаке?
Курс «Java Developer. Advanced» — ваш билет к продвинутым технологиям, которые востребованы в крупных проектах.
✔️ На курсе вы научитесь профилировать приложения, настраивать GC, работать с реактивными подходами и мониторить метрики в Grafana. Пройдете весь путь от JVM до Kubernetes, научитесь анализировать «горячие точки», оптимизировать приложения и настраивать интеграции с Prometheus.
Представьте, как ваши навыки открывают двери в серьёзные проекты с высокими требованиями. Наши преподаватели-практикующие эксперты поделятся опытом, а диплом OTUS станет отличным усилением к вашему резюме.
➡️ Это последний шанс попасть в группу! Регистрируйтесь сейчас и получите скидку: https://vk.cc/cI1cuV
🎫 ПРОМОКОД: Java_adv
Начните обучение со скидкой, подробности у менеджеров.Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
👩💻 Пройди тест по Java и проверь свои знания, готов ли ты к обучению на курсе.
Ответишь — пройдешь на продвинутый курс "Java Developer. Professional" от OTUS по специальной цене + получишь доступ к записям открытых уроков курса курса
За 6 месяцев обучения вы научитесь создавать современные Java-приложения, освоите Spring WebFlux и Kafka, а также разберётесь в работе JVM изнутри.
Вас ждёт практическая работа с кодом, детальные разборы, ревью от экспертов и подходы, позволяющие писать эффективный и чистый код.
Начните свой путь к уровню Middle+!
➡️ ПРОЙТИ ТЕСТ: https://vk.cc/cHYH2PРеклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
🖥️ Java: передача по значению или по ссылке? 🤔
В Java передача данных происходит ТОЛЬКО по значению (pass-by-value). Однако работа с объектами может ввести в заблуждение и создать впечатление, что передача идет по ссылке.
🔹 Как работает передача в Java?
✅ Примитивные типы (`int`, `double`, `char`): передается копия значения. Изменения внутри метода не влияют на оригинальную переменную.
✅ Объекты (экземпляры классов): передается копия ссылки на объект, а не сам объект. Внутри метода можно изменить состояние объекта, но нельзя изменить саму ссылку на него.
📌 Примеры
🔹 Передача примитивов (значение не изменяется)
public class Test {
public static void modifyPrimitive(int num) {
num = 10; // Это изменение локальное
}
public static void main(String[] args) {
int x = 5;
modifyPrimitive(x);
System.out.println(x); // Выведет: 5 (не изменилось)
}
}
class Person {
String name;
}
public class Test {
public static void modifyObject(Person p) {
p.name = "Alice"; // Изменяет состояние объекта
}
public static void main(String[] args) {
Person person = new Person();
person.name = "Bob";
modifyObject(person);
System.out.println(person.name); // Выведет: Alice
}
}
class Person {
String name;
}
public class Test {
public static void reassignReference(Person p) {
p = new Person(); // Переназначение ссылки (локально)
p.name = "Charlie";
}
public static void main(String[] args) {
Person person = new Person();
person.name = "Bob";
reassignReference(person);
System.out.println(person.name); // Выведет: Bob (не изменилось)
}
}
Совет по Java 💡
Чтобы сделать большие и сложные цепочки компараторов более читаемыми, мне нравится присваивать компараторы переменным, имена которых начинаются с "by". Таким образом, вызов sorted() становится меньше и читается почти как естественный язык. Кроме того, вы можете использовать статический импорт.
👉@BookJava
👩💻 Пройди тест по Java
👩💻 Ответишь — пройдешь на продвинутый курс "Разработчик на Spring Framework" от OTUS по специальной цене.
За 5 месяцев обучения вы освоите современные возможности Spring, научитесь быстро проходить путь от идеи до production-grade, создавать Web-приложения на микросервисной архитектуре и решать высокоуровневые задачи по разработке.
👉 ПРОЙТИ ТЕСТ: https://vk.cc/cHFsiQ
🎫 Начни обучение со скидкой, подробности у менеджеров.Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
👩💻 Хотите, чтобы ваши приложения на Java выдерживали любую нагрузку?
Executors — это не просто инструмент, а секретная «суперсила» JDK для управления потоками. Разберем, как грамотно настраивать пулы потоков и использовать их в реальных проектах.
🗓 На открытом уроке 27 января в 20:00 мск мы покажем, как сделать ваши сервисы быстрее и надежнее, даже если нагрузки растут. Участники получат скидку на большое обучение «Java Developer. Professional».
🎙 Спикер Сергей Петрелевич — опытный разработчик на Java и Kotlin.
➡️ Успейте зарегистрироваться и узнайте, как улучшить свои навыки в многопоточности с помощью Executors: https://vk.cc/cHzkM5Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
💪 Открытый урок «Альтернативные фреймворки Spring Framework» 💪
🗓 Дата: 27 января в 20:00 мск.
На занятии мы разберем, почему Spring столь популярен, почему появились альтернативные решения, и познакомимся с такими фреймворками, как Quarkus, Micronaut и Helidon.
Программа урока:
✔️ Почему Spring Framework занимает лидирующие позиции в разработке.
✔️ Причины появления альтернативных фреймворков.
✔️Обзор Quarkus: основные особенности и возможности.
✔️Обзор Micronaut: ключевые преимущества и использование.
✔️ Обзор Helidon: применение в современных проектах.
🔗 Регистрация на вебинар: https://vk.cc/cHw0MMРеклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru