Java | Фишки и трюки
Чистый код: создание, анализ и рефакторинг Автор: Роберт Мартин Эту книгу должен прочитать каждый разработчик. А затем перечитывать каждый год! 😁 Плюс для джавистов в том что в книге все примеры написаны на Java. "Чистый код" Роберта Мартина – это практическое…
📚 Чистый код. Наименования и разделения
✅ Используй понятные и удобнопроизносимые имена для любых сущностей. Они должны описывать почему эта сущность существует, что она делает и как используется.
✅ Не бойся тратить время на выбор лучшего и понятного имени. Ты выиграешь в будущем при работе или чтении этого кода.
✅ Если название сущности не соответствует еë функционалу или по названию не понятно, что сущность делает, то еë надо переименовать в самое понятное название. Если этого сделать невозможно, то значит с еë функционалом что-то не так и еë надо рефакторить.
✅ Сущность, которая имеет в названии "And", "With" — нарушает Single Responsibility. Функционал такой сущности стоит разделять. Но этим правилом стоит иногда пренебрегать.
✅ Непонятные тексты, строки стоит выносить в переменные и давать им понятные названия.
✅ Названия методов должны содержать глагол, который описывает, что этот метод делает и ключевое слово с которым работает данный метод. Если в названии метода нет глагола, то эта сущность не должна быть методом или ему нужно дать правильное название.
✅ Нужно избегать одинаковых наименований для двух разных целей.
✅ Если сущность имеет схожее с другой сущностью название, то скорее всего их функционал очень сильно похож и их нужно объединить? Если нет, то их названия нужно менять так, чтобы они не были похожими.
✅ Если ты мысленно переименовываешь сущность, когда читаешь код, чтобы тебе было понятнее понимать её функционал, то переименуй её в это мысленное название.
✅ Выбери одно слово для одной концепции. Сложно будет понимать функционал, когда у тебя есть fetch, retrieve и get в названиях. Пусть лучше везде будет get.
✅ Длинное и понятное имя лучше, чем короткое, но непонятное.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥3❤1
Пример кода:
$ jshell
| Welcome to JShell -- Version 11.0.12
| For an introduction type: /help intro
jshell> int result = 10 + 20;
result ==> 30
jshell> String message = "Hello, World!";
message ==> "Hello, World!"
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥3❤1
String json = """
{
"Orwell1": "War is Peace.",
"Orwell2": "Freedom is Slavery.",
"Orwell3": "Ignorance is Strength."
}
""";
Type mapType = new TypeToken<Map<String, String>>() { }.getType();
Map<String, String> map = new Gson().fromJson(json, mapType);
Gson или Google Gson — это библиотека Java с открытым исходным кодом, которая сериализует объекты Java в JSON (и десериализует их обратно в Java).
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥1👨💻1
С помощью Java Flight Recorder можно профилировать работу приложения в реальном времени, собирать данные о производительности и возможных узких местах.
Он позволяет записывать и в последствии анализировать огромное количество метрик и событий, происходящих внутри JVM, что значительно облегчает анализ проблем.
Более того, при определённых настройках его накладные расходы настолько малы, что многие (включая Oracle) рекомендуют держать его постоянно включённым везде, в том числе в прод, чтобы в случае возникновения проблем сразу иметь полную картину происходившего с приложением.
JFR это мощный инструмент для оптимизации производительности Java-приложений.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤2🔥1🥰1
Этот метод предлагает удобный способ вычисления и вставки значений в карту, если они отсутствуют.
Пример кода с объяснением:
import java.util.HashMap;
import java.util.Map;
public class MapExample {
public static void main(String[] args) {
Map<String, Integer> wordLengths = new HashMap<>();
String word = "apple";
// Использование computeIfAbsent для вычисления и вставки значения в карту
wordLengths.computeIfAbsent(word, String::length);
// Вывод длины слова "apple", которая была вычислена и вставлена в карту
System.out.println("Длина слова apple: " + wordLengths.get(word));
}
}
Этот метод предоставляет удобный и эффективный способ добавления значений в карту, если они отсутствуют, что может помочь упростить код и избежать лишних проверок на наличие ключей в карте.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤1🔥1👏1
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class MultithreadingExample {
public static void main(String[] args) {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
// Запланировать выполнение задачи через определенное время
ScheduledFuture<?> future = executor.schedule(() -> {
// Выполнить задачу
System.out.println("Выполняется отложенная задача");
}, 3, TimeUnit.SECONDS);
// Планирование регулярного выполнения задачи с определенной задержкой
executor.scheduleAtFixedRate(() -> {
// Выполнить регулярную задачу
System.out.println("Выполняется регулярная задача");
}, 0, 1, TimeUnit.SECONDS);
// Завершение работы с пулом потоков
executor.shutdown();
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4👍2👏1
Начиная с Java 9, была добавлена возможность использования коллекций неизменяемых (immutable) элементов. Это достигается с помощью метода of в классе List, Set и Map. Вот пример:
// Создание неизменяемого списка
List<String> immutableList = List.of("apple", "banana", "cherry");
// Создание неизменяемого множества
Set<String> immutableSet = Set.of("apple", "banana", "cherry");
// Создание неизменяемой карты
Map<String, Integer> immutableMap = Map.of("apple", 1, "banana", 2, "cherry", 3);
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤2
CountDownLatch - это класс в Java, который предоставляет возможность создания ожидания, пока не завершится определенное количество операций или событий. Он часто используется для ожидания завершения параллельных потоков.
Пример кода:
import java.util.concurrent.CountDownLatch;
public class Main {
public static void main(String[] args) throws InterruptedException {
int count = 3;
CountDownLatch latch = new CountDownLatch(count);
// Потоки, которые будут уменьшать счетчик
new Thread(new Worker(latch)).start();
new Thread(new Worker(latch)).start();
new Thread(new Worker(latch)).start();
// Ожидание завершения всех потоков
latch.await();
System.out.println("Все потоки завершили работу");
}
}
class Worker implements Runnable {
private CountDownLatch latch;
Worker(CountDownLatch latch) {
this.latch = latch;
}
public void run() {
// Имитация выполнения работы
try {
Thread.sleep((long) (Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Поток завершил работу");
latch.countDown(); // Уменьшение счетчика
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍1
Данная фишка используется для реализации перехватов событий и внедрения дополнительной логики в код без изменения его основной логики.
Пример кода:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.JoinPoint;
@Aspect
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void beforeServiceMethod(JoinPoint joinPoint) {
System.out.println("Логирование: Вызов метода " + joinPoint.getSignature().getName());
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥2❤1👨💻1
Отлов багов – это, возможно, самая трудоемкая составляющая процесса разработки на Java. Трассировка стека позволяет отследить, в каком именно месте проекта было выброшено исключение.
public class StackTraceExample {
public static void main(String[] args) {
try {
method1();
} catch (Exception e) {
e.printStackTrace(); // Вывод трассировки стека
}
}
public static void method1() {
method2();
}
public static void method2() {
method3();
}
public static void method3() {
throw new RuntimeException("Custom exception message");
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤2👏2
Java Reflection API позволяет получать информацию о классах, создавать экземпляры классов, вызывать методы, получать и устанавливать значения полей, а также работать с аннотациями и конструкторами.
Пример использования Java Reflection API:
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class MyClass {
private String name;
public MyClass(String name) {
this.name = name;
}
public void printInfo() {
System.out.println("Name: " + name);
}
}
public class Main {
public static void main(String[] args) throws Exception {
MyClass obj = new MyClass("John");
// Получение класса
Class<?> clazz = obj.getClass();
// Получение и установка значения поля
Field field = clazz.getDeclaredField("name");
field.setAccessible(true);
System.out.println("Original value: " + field.get(obj));
field.set(obj, "Alice");
System.out.println("Updated value: " + field.get(obj));
// Вызов метода
Method method = clazz.getDeclaredMethod("printInfo");
method.invoke(obj);
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥1
Аннотация @SuppressWarnings в Java используется для подавления предупреждений компилятора или IDE. Это может быть полезно, если вы уверены, что определенное предупреждение не является критическим и хотите, чтобы компилятор пропустил его. Однако следует использовать эту аннотацию осторожно, поскольку она может скрыть проблемы в коде.
Вот пример использования аннотации @SuppressWarnings:
public class DeprecatedExample {
@SuppressWarnings("deprecation")
public void useDeprecatedMethod() {
// Используем устаревший метод
DeprecatedClass deprecatedClass = new DeprecatedClass();
deprecatedClass.deprecatedMethod();
}
public static void main(String[] args) {
DeprecatedExample example = new DeprecatedExample();
example.useDeprecatedMethod();
}
}
Помните, что использование аннотации @SuppressWarnings должно быть обосновано, и важно следить за качеством кода, чтобы не упустить потенциальные проблемы в вашем приложении.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🎉1🤩1🍾1
Пример кода:
import lombok.Getter;
import lombok.Setter;
public class User {
@Getter @Setter
private String name;
@Getter @Setter
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
❤14👍3👏1
public class QuickSort {
// Метод для обмена элементов
private static void swap(int[] array, int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
// Основной метод быстрой сортировки
public static void quickSort(int[] array, int low, int high) {
if (array == null || array.length == 0){
return;
}
if (low >= high){
return;
}
// Выбор опорного элемента (pivot)
int middle = low + (high - low) / 2;
int pivot = array[middle];
// Разделение на подмассивы
int i = low, j = high;
while (i <= j) {
while (array[i] < pivot) {
i++;
}
while (array[j] > pivot) {
j--;
}
if (i <= j) {
swap(array, i, j);
i++;
j--;
}
}
// Рекурсивные вызовы для подмассивов
if (low < j){
quickSort(array, low, j);
}
if (high > i){
quickSort(array, i, high);
}
}
// Тестирование алгоритма
public static void main(String[] args) {
int[] array = {9, -3, 5, 2, 6, 8, -6, 1, 3};
System.out.println("Исходный массив: " + Arrays.toString(array));
quickSort(array, 0, array.length - 1);
System.out.println("Отсортированный массив: " + Arrays.toString(array));
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤2🔥1👏1😁1
Пример:
List<String> names = Arrays.asList("Alice", "Bob", "Charlotte", "David");
Optional<String> nameOptional = names.stream()
.filter(name -> name.startsWith("A"))
.findFirst();
nameOptional.ifPresent(name -> System.out.println("Найдено имя, начинающееся на 'A': " + name));
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10
Этот метод позволяет выполнять параллельные операции над элементами стрима. Это полезно при работе с большими наборами данных или при выполнении тяжелых вычислений, которые можно распараллелить.
Вот пример использования метода
parallel() для вычисления суммы квадратов всех чисел от 1 до 100:
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
int sumOfSquares = IntStream.rangeClosed(1, 100)
.parallel() // запускаем параллельные операции
.map(x -> x * x) // применяем квадратное преобразование к каждому числу
.sum(); // находим сумму всех чисел
System.out.println("Sum of squares: " + sumOfSquares);
}
}
В данном примере метод
parallel() позволяет выполнять вычисления одновременно для нескольких чисел параллельно, что может значительно ускорить время выполнения программы.Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤1🤡1
Java | Фишки и трюки
Чистый код: создание, анализ и рефакторинг Автор: Роберт Мартин Эту книгу должен прочитать каждый разработчик. А затем перечитывать каждый год! 😁 Плюс для джавистов в том что в книге все примеры написаны на Java. "Чистый код" Роберта Мартина – это практическое…
📚 Чистый код. Функции
✅ Функции должны быть короткими и компактными.
✅ Функции должны быть очень короткими и очень компактными.
✅ Приблизительный максимум 20 строк и 150 символов в одной строке, если не влезает, то нужно разделять.
✅ Функция должна выполнять только одну операцию.
- Она должна выполнять её хорошо и ничего другого она делать не должна.
- Если функция выполняет только те действия, которые находятся на одном уровне абстракции, то функция выполняет одну операцию.
- Чтобы определить выполняет ли функция более одной операции, попробуй извлечь из нее другую функцию, которая не будет являться простой переформулировкой реализации.
✅ Чтобы определить выполняет ли функция более одной операции, попробуй извлечь из нее другую функцию, которая не будет являться простой переформулировкой реализации.
✅
✅ Идеальное количество входных аргументов для функции = 0. Если входных аргументов больше трех, то стоит задуматься каким образом лучше от них избавиться, например, создать класс для этих аргументов.
✅ Чем больше входных аргументов, тем тяжелее понимается функция.
✅ Функция в которую передается аргумент-флаг, от которого зависит работа функции говорит о том, что функция выполняет более одной операции. Такие функции следует разбить на две и вызывать их уровнем выше.
✅ Функция, которая изменяет входной аргумент, должна отдавать ссылку на измененный объект, а не просто изменять без возврата.
✅ Если функция, должна изменять входной аргумент, то пусть она изменяет состояние своего объекта-владельца.
✅ Если входной аргумент функции не должен меняться (и используется дальше в коде), то следует скопировать значение аргумента и внутри функции работать с копией.
✅ Вместо
✅ Всегда старайся использовать нестатические функции. Если это невозможно, то используй статические.
✅ Если есть код, который должен следовать один за другим, то передавай результаты первой функции во вторую, чтобы кто-нибудь не изменил последовательность вызовов.
✅ Используй полиморфизм вместо
✅ Избегай отрицательных условий.
- Она должна выполнять её хорошо и ничего другого она делать не должна.
- Если функция выполняет только те действия, которые находятся на одном уровне абстракции, то функция выполняет одну операцию.
- Чтобы определить выполняет ли функция более одной операции, попробуй извлечь из нее другую функцию, которая не будет являться простой переформулировкой реализации.
If, else, while и т.д. должны содержать вызов одной функции. Так будет читабельнее, понятнее и проще.String transform(String text)return null лучше использовать пустой объект — Collection.empty() или null-объект -EmptyObject().if/else или switch/case или when.Please open Telegram to view this post
VIEW IN TELEGRAM
👍16🤣3👏2🔥1👨💻1
Библиотека JUnit предназначена для написания и запуска юнит-тестов в Java. Она позволяет программистам проверять правильность работы отдельных частей и методов их приложений. Вот некоторые основные методы JUnit с их объяснениями и примерами кода:
1.
@Test - аннотация, указывающая, что метод является тестовым.
import org.junit.Test;
import static org.junit.Assert.*;
public class MyTest {
@Test
public void testSum() {
assertEquals(5, Calculator.sum(2, 3));
}
}
2.
assertEquals(expected, actual) - метод, который проверяет, что ожидаемое значение совпадает с фактическим значением.
import static org.junit.Assert.*;
public class MyTest {
@Test
public void testMultiply() {
assertEquals(6, Calculator.multiply(2, 3));
}
}
3.
assertTrue(condition) - метод, который проверяет, что условие истинно.
import static org.junit.Assert.*;
public class MyTest {
@Test
public void testIsEven() {
assertTrue(Calculator.isEven(4));
}
}
4.
assertFalse(condition) - метод, который проверяет, что условие ложно.
import static org.junit.Assert.*;
public class MyTest {
@Test
public void testIsPrime() {
assertFalse(Calculator.isPrime(4));
}
}
5.
@Before и @After - аннотации, которые используются для выполнения определенных методов перед и после каждого теста соответственно.
import org.junit.Before;
import org.junit.After;
public class MyTest {
@Before
public void setUp() {
// код инициализации
}
@After
public void tearDown() {
// код очистки
}
}
JUnit облегчает процесс тестирования кода и помогает обнаруживать дефекты на ранних стадиях разработки. Его методы позволяют программистам писать понятные и эффективные тесты для своих приложений.
Please open Telegram to view this post
VIEW IN TELEGRAM
💯12👍1