Pascal4eg / Java

 Java | Фишки и трюки

Цепочка методов (Method chaining)

public class Student {
    String name;
    int age;
    String group;

    public Student setName(String name) {
        this.name = name;
        return this;
    }

    public Student setAge(int age) {
        this.age = age;
        return this;
    }

    public Student setGroup(String group) {
        this.group = group;
        return this;
    }
}

...

Student student = new Student()
                .setName( "Piter")
                .setAge(20)
                .setGroup("CS-23");

Цепочка методов (Method chaining) — это общий синтаксис для нескольких вызовов методов в объектно-ориентированных языках программирования. Каждый метод возвращает объект, что позволяет объединить вызовы в один оператор без необходимости использования переменных для хранения промежуточных результатов.

...

Читать дальше

Класс Properties

String rootPath = Thread.currentThread().getContextClassLoader().getResource("").getPath();
String appConfigPath = rootPath + "app.properties";
Properties appProps = new Properties();
appProps.load(new FileInputStream(appConfigPath));
System.out.println(appProps.getProperty("version")); // 1.0
System.out.println(appProps.getProperty("name")); // TestApp

В Java класс Properties представляет собой таблицу хэш-значений ключ-значение. Он является частью пакета java.util, и обычно используется для работы с конфигурационными файлами, настройками приложений и другими данными в формате ключ-значение.

...

Читать дальше

Stream API. Метод dropWhile

// отбросить все первые отрицательные числа
List<Integer> digits = List.of(-2, -1, 0, 1, 2, 1, 0, -1, -2);
digits.stream()
    dropWhile(d -> d < 0)
    forEach(System.out::println);
// 0 1 2 1 0 -1 -2

Метод dropWhile был введен в интерфейсе Stream в JDK 9. Этот метод позволяет пропускать элементы в начале потока данных, пока они удовлетворяют определенному условию, и возвращает новый поток, начиная с первого элемента, который не соответствует условию.

...

Читать дальше

Class Loader (загрузчик классов)

public class CustomClassLoader extends ClassLoader {

    @Override
    public Class findClass(String name) throws ClassNotFoundException {
        byte[] b = loadClassFromFile(name);
        return defineClass(name, b, 0, b.length);
    }

    private byte[] loadClassFromFile(String fileName) {
        InputStream inputStream = getClass().getClassLoader().getResourceAsStream(
                fileName.replace('.', File.separatorChar) + ".class");
        byte[] buffer;
        ByteArrayOutputStream byteStream = new ByteArrayOutputStream() ;
        int nextValue = 0;
        try {
            while ( (nextValue = inputStream.read()) != -1 ) {
                byteStream.write(nextValue);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        buffer = byteStream.toByteArray();
        return buffer;
    }
}

В Java, Class Loader (загрузчик классов) является частью Java Runtime Environment (JRE), которая ответственна за загрузку классов в виртуальную машину Java (JVM) во время выполнения программы. Class Loader осуществляет поиск и загрузку классов в память JVM по их именам.

...

Читать дальше

JIT-компилятор

На начальном этапе выполнения программы байт-код интерпретируется JVM. Это позволяет быстро запускать программы без необходимости предварительной компиляции в машинный код.

JIT-компилятор является ключевым элементом виртуальной машины Java (JVM). Он компилирует байт-код часто вызываемых методов в машинный код во время выполнения. Следовательно, он отвечает за оптимизацию программ Java.

...

Читать дальше

Управление доступом к членам класса

Модификаторы уровня доступа определяют, могут ли другие классы использовать определенное поле или вызывать определенный метод.

Существует 4 уровня доступа:

...

Читать дальше

SOLID — принципы объектно‑ориентированного программирования

SOLID — это аббревиатура пяти основных принципов проектирования в объектно‑ориентированном программировании — Single responsibility, Open-closed, Liskov substitution, Interface segregation и Dependency inversion.

В переводе на русский: принципы единственной ответственности, открытости / закрытости, подстановки Барбары Лисков, разделения интерфейса и инверсии зависимостей.

Аббревиатура SOLID была предложена Робертом Мартином, автором нескольких книг, широко известным в сообществе разработчиков. Следование принципам позволяет строить на базе ООП масштабируемые и сопровождаемые программные продукты с понятной бизнес‑логикой. Код, который написан с соблюдением принципов SOLID, проще понимать, поддерживать, расширять или изменять его функциональность.

...

Читать дальше

Класс PrintStream

try {
    // Создание объекта PrintStream для вывода данных в консоль
    PrintStream printStream = System.out;

    // Использование методов print и println
    printStream.print("Hello, ");
    printStream.println("world!");

    // Использование метода printf
    printStream.printf("Formatted number: %d, Floating-point: %.2f%n", 42, 3.14159);

    // Создание объекта PrintStream для записи данных в файл
    PrintStream filePrintStream = new PrintStream(new FileOutputStream("output.txt"));

    // Вывод данных в файл
    filePrintStream.println("Data written to file.");
    filePrintStream.printf("File size: %d bytes", 1024);

    // Закрытие потока вывода в файл
    filePrintStream.close();
} catch (IOException e) {
    e.printStackTrace();
}

PrintStream является классом, предназначенным для удобного вывода различных типов данных в поток вывода. Он является подклассом OutputStream и предоставляет методы для вывода данных различных примитивных типов, строк и объектов в удобном для чтения текстовом формате.

...

Читать дальше

Проблема N+1 (N+1 Issue)

@Entity
public class Author {
    ...
    @OneToMany(mappedBy = "author")
    private List<Book> books;
}

@Entity
public class Book {
    ...
    @ManyToOne
    @JoinColumn(name = "author_id")
    private Author author;
}
...

List<Author> authors = entityManager.createQuery(
        "SELECT a FROM Author a", Author.class).getResultList();

for (Author author : authors){
    // Каждый вызов author.getBooks() приведет к дополнительному
    //запросу к базе данных
    List<Book> books = author.getBooks();
    // Дополнительная логика обработки
}

Проблема N+1 (N+1 Issue) в JPA (Java Persistence API) возникает, когда при получении списка сущностей с их связанными сущностями (например, при использовании отношения OneToMany или ManyToOne), для каждой основной сущности выполняется дополнительный запрос для загрузки связанной сущности. Это приводит к выполнению N+1 запросов к базе данных, где N - количество основных сущностей.

...

Читать дальше

JPA Entity Graph

@NamedEntityGraph(
        name = "person-with-address",
        attributeNodes = {
                @NamedAttributeNode("name"),
                @NamedAttributeNode(value = "address", subgraph = "address-subgraph")
        },
        subgraphs = {
                @NamedSubgraph(name = "address-subgraph", attributeNodes = {
                        @NamedAttributeNode("city")
                })
        }
)
@Entity
public class Person {
    private String name;
    @ManyToOne
    private Address address;
}

@Entity
public class Address {
    private String city;
}
...

EntityGraph<Person> entityGraph = entityManager.getEntityGraph("person-with-address");
Map<String, Object> properties = new HashMap<>();
properties.put("jakarta.persistence.fetchgraph", entityGraph);
Person person = entityManager.find(Person.class, 1L, properties);

JPA Entity Graph - это механизм, предоставляемый JPA, который позволяет явно указывать, какие атрибуты сущности должны быть загружены или проигнорированы во время выполнения запросов к базе данных. Это может быть полезно для управления жадной загрузкой (eager loading) и ленивой загрузкой (lazy loading) связанных сущностей.

...

Читать дальше